Давайте предположим, что у нас есть следующий фрейм данных:

d = {'col1': [[1,2], [1,2], [2,1]], 'col2': ['A', 'B', 'C']}
df = pd.DataFrame(data=d)
df

col1 col2
[1, 2] A 
[1, 2] B
[2, 1] C 

Где у меня есть список в столбце в кадре данных, как я могу подсчитать различные значения в каждом столбце? Функция df.nunique() не работает, выдает эту ошибку: TypeError: ("unhashable type: 'list'", 'occurred at index :97A::SAFE')

Ожидаемый результат будет:

col1 2
col2 3

Мне нужно решение, которое применимо к большему количеству столбцов, мой исходный фрейм данных будет иметь несколько столбцов, и я не буду знать, какой из них содержит список, а какой нет.

2
PV8 26 Июн 2019 в 12:46

3 ответа

Лучший ответ

Если у вас нет типа, в котором равенство данных и равенство строкового представления могут различаться, я бы преобразовал весь массив данных в строку:

df.astype(str).nunique()

Для вашего примера dataframe дает ожидаемый результат:

col1    2
col2    3
dtype: int64
2
Serge Ballesta 26 Июн 2019 в 11:15

Чтобы получить уникальные значения по столбцу, вы можете сделать

import numpy as np

np.unique(np.vstack(df['col1'].values))

И получить количество уникальных значений:

len(np.unique(np.vstack(df['col1'].values)))

Вы также можете использовать np.hstack или np.concatenate вместо np.vstack, но здесь я хотел сохранить двумерность значений столбцов.

1
0 0 26 Июн 2019 в 09:51

Для столбца, содержащего списки, вы можете сопоставить значения с tuples, , которые можно хэшировать , а затем использовать nunique:

df.col1.map(tuple).nunique()
# 2

df['col1'] = df.col1.map(tuple)
df.nunique()

col1    2
col2    3
dtype: int64

Если вы не знаете, какие столбцы могут содержать списки:

df.applymap(tuple).nunique()

col1    2
col2    3
dtype: int64

Или проверка, какие столбцы содержат списки:

cols = [i for i, ix in enumerate(df.loc[0].values) if isinstance(ix, list)]
df.iloc[:,cols] = df.iloc[:,cols].applymap(tuple) 
df.nunique()
3
yatu 26 Июн 2019 в 10:01