Существует ли более быстрый способ подсчета значений в нескольких столбцах, исключая дублированные значения в одной строке? - PullRequest
0 голосов
/ 23 мая 2018

Учитывая следующее df

   id val1 val2 val3
0   1    A    A    B
1   1    A    B    B
2   1    B    C  NaN
3   1  NaN    B    D
4   2    A    D  NaN

Я хотел бы суммировать значения в каждой группе id для всех столбцов;однако мне нужно только посчитать значения, которые появляются в одной строке, поэтому ожидаемый результат:

id   
1   B    4
    A    2
    C    1
    D    1
2   A    1
    D    1

Я могу сделать это с помощью

import pandas as pd
df.set_index('id').apply(lambda x: list(set(x)), axis=1).apply(pd.Series).stack().groupby(level=0).value_counts()

, но apply(...axis=1)(и, возможно, apply(pd.Series)) действительно убивает производительность в целом DataFrames.Поскольку у меня небольшое количество столбцов, я думаю, что я мог бы просто проверить все попарные дубликаты, заменить один на np.NaN, а затем просто использовать df.set_index('id').stack().groupby(level=0).value_counts(), но это не похоже на правильный подход, когда количество столбцов становится большим,

Есть какие-нибудь идеи относительно более быстрого решения этой проблемы?

Ответы [ 2 ]

0 голосов
/ 23 мая 2018

Я использую get_dummies

s=df.set_index('id',append=True).stack().str.get_dummies().sum(level=[0,1]).gt(0).sum(level=1).stack().astype(int)
s[s.gt(0)]
Out[234]: 
id   
1   A    2
    B    4
    C    1
    D    1
2   A    1
    D    1
dtype: int32
0 голосов
/ 23 мая 2018

Вот недостающие шаги, которые удаляют дубликаты строк из вашего фрейма данных:

nodups = df.stack().reset_index(level=0).drop_duplicates()
nodups = nodups.set_index(['level_0', nodups.index]).unstack()
nodups.columns = nodups.columns.levels[1]
#        id  val1  val2  val3
#level_0                     
#0        1     A  None     B
#1        1     A     B  None
#2        1     B     C  None
#3        1  None     B     D
#4        2     A     D  None

Теперь вы можете выполнить следующие действия:

nodups.set_index('id').stack().groupby(level=0).value_counts()

Возможно, вы сможете дополнительно оптимизировать код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...