Панды считают уникальные значения для списка значений

Я пытаюсь выяснить, как подсчитать уникальные значения в одном столбце в зависимости от другого значения. Мой DataFrame выглядит так:

   id_user  id_track  
       1        1           
       1        2 
       1        4
       3        1
       3        1    
       3        4
       1        1
       2        5

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

id_user uniqueTracks
   1         3
   3         2
   2         1

Я попытался сделать это таким образом (слушания - мой DataFrame):

uniqueTracks=[]  #list of numbers of unique tracks
for i in range(len(hearings['id_user'].unique())):
     uniqueTracks.append(len(hearings[hearings['id_user']==i['titles'].unique()))           

но он работает ужасно медленно для таблицы из 27 миллионов строк и 70 000 уникальных пользователей. Кто-нибудь знает, как это сделать в Pandas? Заранее спасибо:)

2 ответа

Решение

Вот подход NumPy, предназначенный для производительности:

def nunique_groupby_col0_in_col1(a):
    b = a[np.lexsort(a[:,::-1].T)]

    m = np.r_[True, b[1:,1] != b[:-1,1]]
    split_idx = np.r_[0, np.flatnonzero(b[1:,0] != b[:-1,0])+1]
    m[split_idx] = 1
    count = np.add.reduceat(m,split_idx)
    userIDs = b[split_idx,0]

    sidx = count.argsort()[::-1]
    out_data = np.column_stack(( userIDs, count ))[sidx]
    return out_data

Пробный прогон -

In [69]: df
Out[69]: 
   id_user  id_track
0        1         1
1        1         2
2        1         4
3        3         1
4        3         1
5        3         4
6        1         1
7        2         5

In [70]: out_data = nunique_groupby_col0_in_col1(df.values)
    ...: cnames = list(['id_user','uniqueTracks'])
    ...: dfout = pd.DataFrame(out_data,columns=cnames)
    ...: 

In [71]: dfout
Out[71]: 
   id_user  uniqueTracks
0        1             3
1        3             2
2        2             1

Использование groupby.nunique() рассчитывать уникальные значения для каждого пользователя и sort_values отсортировать результат:

df.groupby('id_user')['id_track'].nunique().sort_values(ascending=False)

#id_user
#1    3
#3    2
#2    1
#Name: id_track, dtype: int64

Чтобы вернуть результат в виде фрейма данных, reset_index:

df.groupby('id_user')['id_track'].nunique().reset_index().sort_values("id_track", ascending=False)

введите описание изображения здесь

Другие вопросы по тегам