Pandalar toplu sayım farklı


95

Diyelim ki bir kullanıcı etkinliği günlüğüm var ve toplam süre ve günlük benzersiz kullanıcı sayısı raporu oluşturmak istiyorum.

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

Toplama süresi oldukça basittir:

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

Yapmak istediğim şey, süreyi toplamak ve aynı zamanda farklıları saymak, ancak count_distinct için bir eşdeğer bulamıyorum:

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

Bu işe yarıyor, ama kesinlikle daha iyi bir yolu var, değil mi?

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

Bir Series nesnesinin farklı öğelerinin sayısını toplama işlevine döndüren bir işlev sağlamam gerektiğini düşünüyorum, ancak elimdeki çeşitli kitaplıklara çok fazla maruz kalmıyorum. Ayrıca, groupby nesnesi bu bilgiyi zaten biliyor gibi görünüyor, bu yüzden sadece çabayı kopyalıyor olmaz mıyım?

Yanıtlar:


156

Şunlardan birine ne dersiniz:

>>> 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
Bu kadar. pd.Series.nunique bulamadığım şey, peki, düzgün çalışamıyordu. Geriye dönüp bakıldığında oldukça açık. Teşekkürler!
dave

5
Bu cevap güncel değil. Artık nuniquedoğrudan kullanabilirsiniz . Aşağıdaki @Blodwyn Pig çözümüne bakın
Ted Petrou

Teşekkürler @TedPetrou, Ben Eskiden Blodwyn Pig olarak bilinen Kodlayıcıyım;)
Ricky McMaster

Yinelenmeyen sayımı nasıl elde edeceğinizi biliyor musunuz?
Ambleu

62

"nunique", pandalar 0.20.0'dan beri .agg () için bir seçenektir, bu nedenle:

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

Eşsiz değerleri toplamak ve elde etmek mümkün mü? gibi bir şeyduration: np.unique
adam

@guy Trydf.groupby('date').agg({'user_id': lambda s: s.unique().reset_index(drop=True)})
BallpointBen

Çıktıyı nasıl elde ederiz?

17

Daha önce verilen yanıtlara ek olarak, dizeyi kullanan çözüm "nunique"çok daha hızlı görünüyor, burada ~ 21 milyon satırlık veri çerçevesinde test edildi, sonra ~ 2 milyon olarak gruplandı

%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
İyi yakaladın! Sanırım bir "lambda" / "diğer işlev" durumunda b / c sıralı olarak uygulanırken, "bilinen" işlevler tüm sütuna vektörize olarak uygulanır.
Ufos

@Blodwyn Pig'den hangi çözüm var?
Chogg

@Chogg, en hızlısı!
m-dz

@Chogg - üzgünüm kullanıcı adımı değiştirdim. O bendim.
Ricky McMaster
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.