Сукупний підрахунок панд різний


94

Скажімо, у мене є журнал активності користувачів, і я хочу сформувати звіт про загальну тривалість та кількість унікальних користувачів за день.

import numpy as np
import pandas as pd
df = pd.DataFrame({'date': ['2013-04-01','2013-04-01','2013-04-01','2013-04-02', '2013-04-02'],
    'user_id': ['0001', '0001', '0002', '0002', '0002'],
    'duration': [30, 15, 20, 15, 30]})

Тривалість агрегування досить проста:

group = df.groupby('date')
agg = group.aggregate({'duration': np.sum})
agg
            duration
date
2013-04-01        65
2013-04-02        45

Що я хотів би зробити, це одночасно підсумувати тривалість і підрахувати різницю, але я не можу знайти еквівалент для count_distinct:

agg = group.aggregate({ 'duration': np.sum, 'user_id': count_distinct})

Це працює, але, звичайно, є кращий спосіб, ні?

group = df.groupby('date')
agg = group.aggregate({'duration': np.sum})
agg['uv'] = df.groupby('date').user_id.nunique()
agg
            duration  uv
date
2013-04-01        65   2
2013-04-02        45   1

Я думаю, мені просто потрібно надати функцію, яка повертає кількість різних елементів об'єкта Серії до сукупної функції, але я не маю великого впливу різних бібліотек у своєму розпорядженні. Крім того, здається, що об'єкт groupby вже знає цю інформацію, тож чи не просто б я дублював зусилля?

Відповіді:


154

Як щодо одного з:

>>> df
         date  duration user_id
0  2013-04-01        30    0001
1  2013-04-01        15    0001
2  2013-04-01        20    0002
3  2013-04-02        15    0002
4  2013-04-02        30    0002
>>> df.groupby("date").agg({"duration": np.sum, "user_id": pd.Series.nunique})
            duration  user_id
date                         
2013-04-01        65        2
2013-04-02        45        1
>>> df.groupby("date").agg({"duration": np.sum, "user_id": lambda x: x.nunique()})
            duration  user_id
date                         
2013-04-01        65        2
2013-04-02        45        1

1
Це воно. pd.Series.nunique - це те, що я не міг знайти, ну, не зміг правильно працювати. Дуже очевидно з огляду на минуле. Дякую!
dave

5
Ця відповідь застаріла. Тепер ви можете використовувати nuniqueбезпосередньо. Дивіться рішення @Blodwyn Pig нижче
Тед Петру,

Дякую @TedPetrou, я кодер, який раніше називався Свиня Блодуін;)
Ricky McMaster

Гей, ти знаєш, як отримати недублічний підрахунок?
Амбл

61

'nunique' - це варіант для .agg (), оскільки pandas 0.20.0, отже:

df.groupby('date').agg({'duration': 'sum', 'user_id': 'nunique'})

Чи можна agg і отримати унікальні значення? щось на кшталтduration: np.unique
хлопець

@guy Спробуйтеdf.groupby('date').agg({'user_id': lambda s: s.unique().reset_index(drop=True)})
BallpointBen

Як отримати результат?

17

Просто додавши до вже наведених відповідей, рішення, що використовує рядок, "nunique"здається набагато швидшим, протестовано тут на ~ 21M рядках даних, а потім згруповано до ~ 2M

%time _=g.agg({"id": lambda x: x.nunique()})
CPU times: user 3min 3s, sys: 2.94 s, total: 3min 6s
Wall time: 3min 20s

%time _=g.agg({"id": pd.Series.nunique})
CPU times: user 3min 2s, sys: 2.44 s, total: 3min 4s
Wall time: 3min 18s

%time _=g.agg({"id": "nunique"})
CPU times: user 14 s, sys: 4.76 s, total: 18.8 s
Wall time: 24.4 s

1
Хороший улов! Я думаю, це b / c у випадку "лямбда" / "інша функція", воно застосовується послідовно, тоді як "відомі" функції застосовуються до цілого стовпця векторизованим способом.
Ufos

яке рішення від @Blodwyn Pig?
Chogg

@Chogg, найшвидший!
m-dz

@Chogg - вибачте, я змінив своє ім'я користувача. Це був я.
Ricky McMaster
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.