Pandas GroupBy.agg () kullanılarak aynı sütunun birden çok toplamı


129

Birden çok kez çağrı yapmak zorunda kalmadan f1, f2aynı sütuna iki farklı toplama işlevini uygulamanın yerleşik bir yolu var mı?df["returns"]agg()

Örnek veri çerçevesi:

import pandas as pd
import datetime as dt

pd.np.random.seed(0)
df = pd.DataFrame({
         "date"    :  [dt.date(2012, x, 1) for x in range(1, 11)], 
         "returns" :  0.05 * np.random.randn(10), 
         "dummy"   :  np.repeat(1, 10)
}) 

Sözdizimsel olarak yanlış, ancak sezgisel olarak doğru olan bunu yapmanın yolu şöyle olacaktır:

# Assume `f1` and `f2` are defined for aggregating.
df.groupby("dummy").agg({"returns": f1, "returns": f2})

Açıkçası, Python yinelenen anahtarlara izin vermez. Girdiyi ifade etmenin başka bir yolu var mı agg()? Belki [(column, function)]birden fazla işlevin aynı sütuna uygulanmasına izin vermek için bir tuple listesi daha iyi çalışırdı ? Ama agg()sadece bir sözlüğü kabul ediyor gibi görünüyor.

Bunun için, içindeki her iki işlevi de uygulayan bir yardımcı işlevi tanımlamanın yanı sıra bir geçici çözüm var mı? (Bu, toplama ile nasıl çalışır?)



2
0,25'ten itibaren pandalar, birden çok toplama için daha sezgisel bir sözdizimi sağlar ve çıktı sütunlarını yeniden adlandırır. Adlandırılmış Toplamalar hakkındaki belgelere bakın .
cs95

Bilginize bu soru 9/2012 tarihinde Pandalar 0.8.x tarihinde tekrar sorulmuştu
smci

1
Bilginize, kabul edilen cevap da kabul edilmiyor - agg () bir dikt diktesini geçmeyin.
cs95

@ cs95: Kullanımdan kaldırıldığını biliyorum, SO'nun eski sürümlerdeki eski eski çözümlerle dolup taştığını söylüyorum. SO'nun bunu işaretlemenin bir yolu yok - yorumlar dışında.
smci

Yanıtlar:


159

İşlevleri bir liste olarak kolayca aktarabilirsiniz:

In [20]: df.groupby("dummy").agg({"returns": [np.mean, np.sum]})
Out[20]:         
           mean       sum
dummy                    
1      0.036901  0.369012

veya sözlük olarak:

In [21]: df.groupby('dummy').agg({'returns':
                                  {'Mean': np.mean, 'Sum': np.sum}})
Out[21]: 
        returns          
           Mean       Sum
dummy                    
1      0.036901  0.369012

5
Sonuç sütun adlarını belirlemenin bir yolu var mı?
Ben

3
@Ben Daha sonra yeniden adlandırmanız gerektiğini düşünüyorum. örnek Tom Augspurger (bkz. hücre 25)
Stewbaca

1
@Ben: Bir örnek ekledim
bmu

10
@sparc_spread Birden fazla işlevi bir liste olarak aktarmak , pandaların belgelerinde iyi açıklanmıştır . Pandaların gelecekteki bir sürümünde birden çok işlevi bir sözlük olarak yeniden adlandırmak ve aktarmak kullanımdan kaldırılacaktır. Ayrıntılar, SO'da başka bir yerde de özetlediğim 0.20 değişiklik günlüğünde .
joelostblom

3
Zaten söylendi, ancak çıktı sütunlarını yaştan itibaren yeniden adlandırmak için sözlük kullanmak artık kullanılmıyor. Bunun yerine bir tuple listesi belirtebilirsiniz. Bu cevaba bakın.
cs95

102

TLDR; Pandalar groupby.agg, (1) birden çok sütunda toplamaları ve (2) bir sütunda birden çok kümeyi belirtmek için yeni ve daha kolay bir sözdizimine sahiptir. Bunu pandalar> = 0.25 için yapmak için şunu kullanın:

df.groupby('dummy').agg(Mean=('returns', 'mean'), Sum=('returns', 'sum'))

           Mean       Sum
dummy                    
1      0.036901  0.369012

VEYA

df.groupby('dummy')['returns'].agg(Mean='mean', Sum='sum')

           Mean       Sum
dummy                    
1      0.036901  0.369012

Pandalar> = 0.25: Adlandırılmış Toplama

Pandalar, GroupBy.aggadlandırılmış toplamaları belirlemek için daha sezgisel bir sözdizimi lehine davranışı değiştirdi . Geliştirmeler hakkındaki 0.25 dokümanlar bölümüne ve ilgili GitHub sorunları GH18366 ve GH26512'ye bakın .

Belgelerden,

Çıktı sütun adları üzerinde denetimle sütuna özgü toplamayı desteklemek için, pandalar GroupBy.agg()"adlandırılmış toplama" olarak bilinen özel sözdizimini kabul eder.

  • Anahtar kelimeler çıktı sütun isimleridir
  • Değerler, ilk öğesi seçilecek sütun ve ikinci öğe bu sütuna uygulanacak kümedir. Pandas, argümanların ne olduğunu daha net hale getirmek için pandas.NamedAgg adlı tuple'a ['sütun', 'aggfunc'] alanlarını sağlar. Her zaman olduğu gibi, toplama çağrılabilir veya dize takma adı olabilir.

Artık anahtar kelime argümanları aracılığıyla bir demeti iletebilirsiniz. Demetler, biçimini takip eder (<colName>, <aggFunc>).

import pandas as pd

pd.__version__                                                                                                                            
# '0.25.0.dev0+840.g989f912ee'

# Setup
df = pd.DataFrame({'kind': ['cat', 'dog', 'cat', 'dog'],
                   'height': [9.1, 6.0, 9.5, 34.0],
                   'weight': [7.9, 7.5, 9.9, 198.0]
})

df.groupby('kind').agg(
    max_height=('height', 'max'), min_weight=('weight', 'min'),)

      max_height  min_weight
kind                        
cat          9.5         7.9
dog         34.0         7.5

Alternatif olarak, pd.NamedAggişleri daha açık hale getiren (esasen adlandırılmış bir çift) kullanabilirsiniz .

df.groupby('kind').agg(
    max_height=pd.NamedAgg(column='height', aggfunc='max'), 
    min_weight=pd.NamedAgg(column='weight', aggfunc='min')
)

      max_height  min_weight
kind                        
cat          9.5         7.9
dog         34.0         7.5

Seri için daha da basittir, sadece agfunc'u bir anahtar kelime argümanına aktarın.

df.groupby('kind')['height'].agg(max_height='max', min_height='min')    

      max_height  min_height
kind                        
cat          9.5         9.1
dog         34.0         6.0       

Son olarak, sütun adlarınız geçerli python tanımlayıcıları değilse, paketi açarken bir sözlük kullanın:

df.groupby('kind')['height'].agg(**{'max height': 'max', ...})

Pandalar <0.25

0.24'e kadar çıkan pandaların daha yeni sürümlerinde, toplama çıktısı için sütun adlarını belirtmek için bir sözlük kullanıyorsanız, bir FutureWarning:

df.groupby('dummy').agg({'returns': {'Mean': 'mean', 'Sum': 'sum'}})
# FutureWarning: using a dict with renaming is deprecated and will be removed 
# in a future version

Sütunları yeniden adlandırmak için sözlük kullanmak v0.20'de kullanımdan kaldırılmıştır. Pandaların daha yeni sürümlerinde, bu daha basit bir şekilde bir tuple listesi iletilerek belirlenebilir. İşlevler bu şekilde belirtiliyorsa, bu sütun için tüm işlevlerin (ad, işlev) çiftlerinin demetleri olarak belirtilmesi gerekir.

df.groupby("dummy").agg({'returns': [('op1', 'sum'), ('op2', 'mean')]})

        returns          
            op1       op2
dummy                    
1      0.328953  0.032895

Veya,

df.groupby("dummy")['returns'].agg([('op1', 'sum'), ('op2', 'mean')])

            op1       op2
dummy                    
1      0.328953  0.032895

4
Arayüzün daha yeni sürümünü kullanarak daha net ve temiz bir çözüm kullandığından bu en iyi cevap olmalıdır.
NKSHELL

Adlandırılmış toplama için kullanılan örnekler, aynı sütunda birden çok toplama kullanma orijinal sorununu çözmez. Örneğin, ilk alt kümeleme yapmadan yükseklik için hem minimum hem de maksimuma göre toplama yapabilir misiniz df.groupby('kind')['height']?
victor

1
@victor Cevabın tepesine soruyu doğrudan ele alan bir TLDR ekledim. Ve ikinci sorunuzun cevabı evet, lütfen cevabımdaki düzenlemeye bir göz atın.
cs95

Son örneğinize> = 0.25 yanıtınızın bu şekilde birden çok sütunu bir araya getirmeyi ele alan daha genel bir kod harika olurdu. df.groupby("kind").agg(**{ 'max height': pd.NamedAgg(column='height', aggfunc=max), 'min weight': pd.NamedAgg(column='weight', aggfunc=min) })
Onur Ece

6

Bunun işe yarayacağı gibi bir şey:

In [7]: df.groupby('dummy').returns.agg({'func1' : lambda x: x.sum(), 'func2' : lambda x: x.prod()})
Out[7]: 
              func2     func1
dummy                        
1     -4.263768e-16 -0.188565

2
Hayır, bu çalışmıyor. Doküman dizesine bakarsanız, aggregateaçık bir dictşekilde a geçildiğinde anahtarların sütun adları olması gerektiğini söyler . Yani ya örneğiniz bu hatayı kontrol etmeden yazdığınız bir şeydir ya da Pandas burada kendi belgelerini bozar.
ely

N / MI returns, orada fazladan arama görmedi . Yani bu, toplamın Seri versiyonu mu? Toplamanın DataFrame sürümünü yapmak istiyorum ve her sütuna aynı anda birkaç farklı toplama uygulamak istiyorum.
ely

1
Şunu deneyin: df.groupby ('kukla'). Agg ({'döndürür': {'func1': lambda x: x.sum (), 'func2': lambda x: x.mean ()}})
Chang O

Mesajsız bir onaylama hatası verir. Kodun görünümüne göre (pandas.core.internals.py, satır 406-408, sürüm 0.7.3), ilkinde anahtarlardan daha fazla sütun döndürmediğinden emin olmak için sonunda bir kontrol yapıyor gibi görünüyor. toplama sözlüğünün katmanı.
ely

Usta üzerinde iyi çalışıyor. Güncellemeyi denemek ister misin?
Chang She
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.