Быстрая и эффективная операция групповой суммы панд - PullRequest
1 голос
/ 03 мая 2019

У меня огромный набор данных из примерно 10 миллионов строк, и у меня огромные проблемы с производительностью и скоростью.Я пытался использовать pandas, numpy (также используя библиотеку numba) и dask.Однако я не смог добиться достаточного успеха.

Необработанные данные (минимальные и упрощенные)

df = pd.read_csv('data.csv',sep=';', names=['ID', 'UserID'], error_bad_lines=False, 
     encoding='latin-1', dtype='category')

For problem reproduction:

df = pd.DataFrame({'ID': [999974708546523127, 999974708546523127, 999974708546520000], 'UserID': ['AU896', 'ZZ999', 'ZZ999']}, dtype='category')
df

ID                  UserID
999974708546523127  AU896  
999974708546523127  ZZ999
999974708546520000  ZZ999  

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

User   999974708546520000   999974708546523127
AU896           1                     0            
ZZ999           1                     1    

Я могу добиться этого, используя следующие различные сценарии.Однако на больших наборах данных сценарии ужасно медленные.Наконец, мне нужно вычислить матрицу корреляции между всеми пользователями на основе ожидаемого результата.Это является причиной структуры выхода:

Панд

results_id = pd.crosstab(df.UserID, df.ID, dropna=False)

Numpy и Numba

import numpy as np
import numba

records = df.to_numpy()

unique_id =  np.unique(records[:, 0])
unique_userid = np.unique(records[:, 1])

results_id = np.zeros((len(unique_userid), len(unique_id)))

@numba.jit(nopython=True):
def ID_PreProcess(records, records_tcode, records_user):    
   for userid in range(len(unique_userid)):
        user = np.where(records[:, 1] == unique_userid[userid])

        for id in range(len(unique_id)):
            tcode_row= np.where(records[:, 0] == unique_id[id])
            inter = records[np.where((records[:,1] == id) * (records[:,0] == id))]
            results_id[userid, id]=len(inter)
   return results_id

results_id = ID_PreProcess(records, records_tcode, records_user)

Dask

import pandas as pd
import dask.dataframe as dd


dask_logs = dd.from_pandas(df, npartitions=2)
results_id = dd.concat([dask_logs.UserID ,dd.get_dummies(dask_logs.ID)],axis=1).groupby('UserID').sum().compute()

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

Я нашел этот пост , который, кажется, очень близок к моей проблеме, но я не смог включитьрешения моей проблемы.

Большое спасибо за вашу помощь!

1 Ответ

0 голосов
/ 06 мая 2019

С учетом полезных комментариев я сам нашел решение.

df.groupby(['UserID', 'ID'], as_index=False).size()
df.reset_index(inplace = True)
df.columns = ['UserID', 'ID', 'Counter']
Expected_Output = pd.pivot('UserID', 'ID', 'Counter')
...