Pandalar groupby (). Sum () çıktısından nasıl yeni bir sütun oluşturabilirim?


84

groupbyHesaplamadan yeni bir sütun oluşturmaya çalışıyorum . Aşağıdaki kodda, her tarih için doğru hesaplanmış değerleri alıyorum (aşağıdaki gruba bakın) ancak onunla yeni bir sütun ( df['Data4']) oluşturmaya çalıştığımda NaN alıyorum. Bu yüzden, dataframe içinde Data3tüm tarihlerin toplamı ile yeni bir sütun oluşturmaya ve bunu her tarih satırına uygulamaya çalışıyorum. Örneğin, 2015-05-08 2 satırda (toplam 50 + 5 = 55) ve bu yeni sütunda her iki satırda da 55 olmasını istiyorum.

import pandas as pd
import numpy as np
from pandas import DataFrame

df = pd.DataFrame({
    'Date' : ['2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05', '2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05'], 
    'Sym'  : ['aapl', 'aapl', 'aapl', 'aapl', 'aaww', 'aaww', 'aaww', 'aaww'], 
    'Data2': [11, 8, 10, 15, 110, 60, 100, 40],
    'Data3': [5, 8, 6, 1, 50, 100, 60, 120]
})

group = df['Data3'].groupby(df['Date']).sum()

df['Data4'] = group

Yanıtlar:


192

Bunu kullanmak istiyorsanız transform, dizini df ile hizalanmış bir Seri döndürecektir, böylece daha sonra yeni bir sütun olarak ekleyebilirsiniz:

In [74]:

df = pd.DataFrame({'Date': ['2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05', '2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05'], 'Sym': ['aapl', 'aapl', 'aapl', 'aapl', 'aaww', 'aaww', 'aaww', 'aaww'], 'Data2': [11, 8, 10, 15, 110, 60, 100, 40],'Data3': [5, 8, 6, 1, 50, 100, 60, 120]})
​
df['Data4'] = df['Data3'].groupby(df['Date']).transform('sum')
df
Out[74]:
   Data2  Data3        Date   Sym  Data4
0     11      5  2015-05-08  aapl     55
1      8      8  2015-05-07  aapl    108
2     10      6  2015-05-06  aapl     66
3     15      1  2015-05-05  aapl    121
4    110     50  2015-05-08  aaww     55
5     60    100  2015-05-07  aaww    108
6    100     60  2015-05-06  aaww     66
7     40    120  2015-05-05  aaww    121

Burada olduğu gibi ikinci bir grubumuz varsa ne olur: stackoverflow.com/a/40067099/281545
Mr_and_Mrs_D

@Mr_and_Mrs_D Bu durumda, sütunu geri eklemek için dizini sıfırlamanız ve ortak sütunlarda bir sol birleştirme
yapmanız gerekir

10
Alternatif olarak df.groupby('Date')['Data3'].transform('sum')(hatırlaması biraz daha kolay bulduğum) kullanabilirsiniz.
Cleb

43

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.groupbyziyade Series.groupby. Bu, daha basit sözdizimi ile sonuçlanır.

# The setup.
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 transformyerine doğrudan işlevini GroupBykullanı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 mapbiraz daha hızlı olduğunu doğrudan kullanmak gelemez GroupByiş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 transformilk 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
)

1
Bunu bilmek güzel! (En azından gelecekteki performans grafiklerinde) sürüm numaralarını dahil eder misiniz? Performans farkı ilginç, ama sonuçta bunlar gelecekte düzeltilebilecek uygulama detayları. Özellikle geliştiriciler gönderilerinizi not alırsa.
jpp

@jpp evet, bu adil! Sürümleri eklediniz. Bu 0.23'te test edildi, ancak 0.20'nin üzerinde herhangi bir sürüme sahip olduğunuz sürece farkın görüldüğüne inanıyorum.
cs95
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.