Jumlah agregat panda berbeda

95

Misalkan saya memiliki log aktivitas pengguna dan saya ingin membuat laporan tentang durasi total dan jumlah pengguna unik per hari.

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]})

Durasi penggabungan cukup mudah:

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

Yang ingin saya lakukan adalah menjumlahkan durasi dan menghitung perbedaan pada saat yang sama, tetapi sepertinya saya tidak dapat menemukan padanan untuk count_distinct:

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

Ini berhasil, tapi pasti ada cara yang lebih baik, bukan?

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

Saya berpikir saya hanya perlu menyediakan fungsi yang mengembalikan jumlah item berbeda dari objek Seri ke fungsi agregat, tetapi saya tidak memiliki banyak eksposur ke berbagai perpustakaan yang saya miliki. Juga, tampaknya objek groupby sudah mengetahui informasi ini, jadi bukankah saya hanya akan menduplikasi usaha?

dave
sumber

Jawaban:

156

Bagaimana jika salah satu dari:

>>> 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
DSM
sumber
1
Itu dia. pd.Series.nunique adalah apa yang tidak dapat saya temukan, yah, tidak dapat berfungsi dengan benar. Cukup jelas kalau dipikir-pikir. Terima kasih!
Dave
5
Jawaban ini sudah ketinggalan zaman. Sekarang Anda dapat menggunakan nuniquesecara langsung. Lihat solusi @Blodwyn Pig di bawah
Ted Petrou
Terima kasih @TedPetrou, Saya Coder Sebelumnya Dikenal sebagai Blodwyn Pig;)
Ricky McMaster
Hai, apakah Anda tahu cara menghitung non-duplikat?
Ambleu
62

'nunique' adalah opsi untuk .agg () sejak pandas 0.20.0, jadi:

df.groupby('date').agg({'duration': 'sum', 'user_id': 'nunique'})
Ricky McMaster
sumber
Apakah mungkin untuk mendapatkan agg dan mendapatkan nilai-nilai unik? sesuatu sepertiduration: np.unique
pria
@guy Trydf.groupby('date').agg({'user_id': lambda s: s.unique().reset_index(drop=True)})
Ballpointen
Bagaimana kita mendapatkan hasilnya?
17

Hanya menambahkan ke jawaban yang sudah diberikan, solusi menggunakan string "nunique"tampak jauh lebih cepat, diuji di sini pada ~ 21 juta baris dataframe, kemudian dikelompokkan ke ~ 2 juta

%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
pengguna6903745
sumber
1
Tangkapan bagus! Saya kira itu b / c dalam kasus "lambda" / "fungsi lain" itu diterapkan secara berurutan, sementara fungsi "yang dikenal" diterapkan ke seluruh kolom dalam mode vektor.
Ufos
solusi mana dari @Blodwyn Pig?
Chogg
@Chogg, yang tercepat!
m-dz
@Chogg - maaf saya mengubah nama pengguna saya. Itu aku.
Ricky McMaster