Groupby (). Sum () ile nasıl yeni bir sütun oluştururum?
İki yol var - biri basit, diğeri biraz daha ilginç.
Herkesin Favorisi: GroupBy.transform()
ile'sum'
@Ed Chum'un cevabı biraz basitleştirilebilir. Çağrı DataFrame.groupby
ziyade Series.groupby
. Bu, daha basit sözdizimi ile sonuçlanır.
df[['Date', 'Data3']]
Date Data3
0 2015-05-08 5
1 2015-05-07 8
2 2015-05-06 6
3 2015-05-05 1
4 2015-05-08 50
5 2015-05-07 100
6 2015-05-06 60
7 2015-05-05 120
df.groupby('Date')['Data3'].transform('sum')
0 55
1 108
2 66
3 121
4 55
5 108
6 66
7 121
Name: Data3, dtype: int64
Biraz daha hızlı
df2 = pd.concat([df] * 12345)
%timeit df2['Data3'].groupby(df['Date']).transform('sum')
%timeit df2.groupby('Date')['Data3'].transform('sum')
10.4 ms ± 367 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
8.58 ms ± 559 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Alışılmadık ama Düşünmeye Değer: GroupBy.sum()
+Series.map()
API'de ilginç bir özelliğe rastladım. Söylediklerime göre, bunu 0.20 üzerindeki herhangi bir ana sürümde yeniden üretebilirsiniz (bunu 0.23 ve 0.24'te test ettim). Bunun transform
yerine doğrudan işlevini GroupBy
kullanır ve aşağıdakileri kullanarak yayınlarsanız , geçen sürenin birkaç milisaniyesini sürekli olarak kısaltabilirsiniz gibi görünüyor map
:
df.Date.map(df.groupby('Date')['Data3'].sum())
0 55
1 108
2 66
3 121
4 55
5 108
6 66
7 121
Name: Date, dtype: int64
İle karşılaştırmak
df.groupby('Date')['Data3'].transform('sum')
0 55
1 108
2 66
3 121
4 55
5 108
6 66
7 121
Name: Data3, dtype: int64
Benim testler gösteriyor map
biraz daha hızlı olduğunu doğrudan kullanmak gelemez GroupBy
işlevini (örneğin mean
, min
, max
, first
, vs). Yaklaşık 200 bin kayda kadar çoğu genel durum için aşağı yukarı daha hızlıdır. Bundan sonra, performans gerçekten verilere bağlı.
(Sol: v0.23, Sağ: v0.24)
Bilmek için güzel bir alternatif ve daha az sayıda grup içeren daha küçük çerçeveleriniz varsa daha iyi. . . ama transform
ilk seçenek olarak tavsiye ederim . Bunun paylaşmaya değer olduğunu düşündüm.
Referans için kıyaslama kodu:
import perfplot
perfplot.show(
setup=lambda n: pd.DataFrame({'A': np.random.choice(n//10, n), 'B': np.ones(n)}),
kernels=[
lambda df: df.groupby('A')['B'].transform('sum'),
lambda df: df.A.map(df.groupby('A')['B'].sum()),
],
labels=['GroupBy.transform', 'GroupBy.sum + map'],
n_range=[2**k for k in range(5, 20)],
xlabel='N',
logy=True,
logx=True
)