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?

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

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

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

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.