Pandalar GroupBy kullanarak her grup için istatistik (sayım, ortalama, vb.) Alın?


438

Bir veri çerçevesi var dfve ondan birkaç sütun kullanın groupby:

df['col1','col2','col3','col4'].groupby(['col1','col2']).mean()

Yukarıdaki şekilde neredeyse ihtiyacım olan tabloyu (veri çerçevesi) alıyorum. Eksik olan, her gruptaki satır sayısını içeren ek bir sütundur. Başka bir deyişle, demek istediğim ama aynı zamanda bu araçları elde etmek için kaç tane sayı kullanıldığını da bilmek istiyorum. Örneğin ilk grupta 8 değer, ikincisinde 10 vb. Vardır.

Kısacası: Bir veri çerçevesi için grup bazında istatistikleri nasıl edinebilirim?

Yanıtlar:


427

On groupbynesne, aggişlev için bir liste alabilir birkaç toplama yöntemlerini uygulamak seferde. Bu size ihtiyacınız olan sonucu vermelidir:

df[['col1', 'col2', 'col3', 'col4']].groupby(['col1', 'col2']).agg(['mean', 'count'])

2
Liste olması için sütun başvurusuna ihtiyacınız olduğunu düşünüyorum. Şunu mu demek istediniz: df[['col1','col2','col3','col4']].groupby(['col1','col2']).agg(['mean', 'count'])
rysqui

43
Bu dört sayma sütunu oluşturur, ancak yalnızca bir tane nasıl alınır? (Soru "ek bir sütun" istiyor ve ben de bunu istiyorum.)
Jaan

16
countGrup başına yalnızca bir sütun almak istiyorsanız lütfen cevabımı görün .
Pedro M Duarte

Ben Sayımlar adında ayrı bir var ve gruplandırılmış türün satırları saymak yerine, Sayımlar sütununda eklemeniz gerekir.
Abhishek Bhatia

@Jaan result = df['col1','col2','col3','col4'].groupby(['col1', 'col2']).mean() ; counts = times.groupby(['col1', 'col2']).size() ; result['count'] = counts
alvitawa

912

Hızlı cevap:

Grup arama gereğidir başına en basit yolu satır sayılarını almak için .size()bir döner, Series:

df.groupby(['col1','col2']).size()


Genellikle bu sonucu DataFrame(a yerine Series) olarak istersiniz, böylece şunları yapabilirsiniz:

df.groupby(['col1', 'col2']).size().reset_index(name='counts')


Her bir grup için satır sayılarını ve diğer istatistikleri nasıl hesaplayacağınızı öğrenmek istiyorsanız, aşağıdaki okumaya devam edin.


Ayrıntılı örnek:

Aşağıdaki örnek veri çerçevesini düşünün:

In [2]: df
Out[2]: 
  col1 col2  col3  col4  col5  col6
0    A    B  0.20 -0.61 -0.49  1.49
1    A    B -1.53 -1.01 -0.39  1.82
2    A    B -0.44  0.27  0.72  0.11
3    A    B  0.28 -1.32  0.38  0.18
4    C    D  0.12  0.59  0.81  0.66
5    C    D -0.13 -1.65 -1.64  0.50
6    C    D -1.42 -0.11 -0.18 -0.44
7    E    F -0.00  1.42 -0.26  1.17
8    E    F  0.91 -0.47  1.35 -0.34
9    G    H  1.48 -0.63 -1.14  0.17

Önce .size()satır sayılarını almak için kullanalım :

In [3]: df.groupby(['col1', 'col2']).size()
Out[3]: 
col1  col2
A     B       4
C     D       3
E     F       2
G     H       1
dtype: int64

Sonra .size().reset_index(name='counts')satır sayılarını almak için kullanalım :

In [4]: df.groupby(['col1', 'col2']).size().reset_index(name='counts')
Out[4]: 
  col1 col2  counts
0    A    B       4
1    C    D       3
2    E    F       2
3    G    H       1


Daha fazla istatistik için sonuçları dahil etme

Gruplandırılmış verilerdeki istatistikleri hesaplamak istediğinizde, genellikle şöyle görünür:

In [5]: (df
   ...: .groupby(['col1', 'col2'])
   ...: .agg({
   ...:     'col3': ['mean', 'count'], 
   ...:     'col4': ['median', 'min', 'count']
   ...: }))
Out[5]: 
            col4                  col3      
          median   min count      mean count
col1 col2                                   
A    B    -0.810 -1.32     4 -0.372500     4
C    D    -0.110 -1.65     3 -0.476667     3
E    F     0.475 -0.47     2  0.455000     2
G    H    -0.630 -0.63     1  1.480000     1

Yukarıdaki sonuç, iç içe sütun etiketleri nedeniyle ve satır sayılarının sütun başına bazında olması nedeniyle biraz can sıkıcıdır.

Çıktı üzerinde daha fazla kontrol elde etmek için genellikle istatistikleri daha sonra kullanarak birleştirdiğim bireysel toplamalara bölerim join. Şöyle görünüyor:

In [6]: gb = df.groupby(['col1', 'col2'])
   ...: counts = gb.size().to_frame(name='counts')
   ...: (counts
   ...:  .join(gb.agg({'col3': 'mean'}).rename(columns={'col3': 'col3_mean'}))
   ...:  .join(gb.agg({'col4': 'median'}).rename(columns={'col4': 'col4_median'}))
   ...:  .join(gb.agg({'col4': 'min'}).rename(columns={'col4': 'col4_min'}))
   ...:  .reset_index()
   ...: )
   ...: 
Out[6]: 
  col1 col2  counts  col3_mean  col4_median  col4_min
0    A    B       4  -0.372500       -0.810     -1.32
1    C    D       3  -0.476667       -0.110     -1.65
2    E    F       2   0.455000        0.475     -0.47
3    G    H       1   1.480000       -0.630     -0.63



Dipnotlar

Test verilerini oluşturmak için kullanılan kod aşağıda gösterilmiştir:

In [1]: import numpy as np
   ...: import pandas as pd 
   ...: 
   ...: keys = np.array([
   ...:         ['A', 'B'],
   ...:         ['A', 'B'],
   ...:         ['A', 'B'],
   ...:         ['A', 'B'],
   ...:         ['C', 'D'],
   ...:         ['C', 'D'],
   ...:         ['C', 'D'],
   ...:         ['E', 'F'],
   ...:         ['E', 'F'],
   ...:         ['G', 'H'] 
   ...:         ])
   ...: 
   ...: df = pd.DataFrame(
   ...:     np.hstack([keys,np.random.randn(10,4).round(2)]), 
   ...:     columns = ['col1', 'col2', 'col3', 'col4', 'col5', 'col6']
   ...: )
   ...: 
   ...: df[['col3', 'col4', 'col5', 'col6']] = \
   ...:     df[['col3', 'col4', 'col5', 'col6']].astype(float)
   ...: 


Yasal Uyarı:

Topladığınız bazı sütunlarda null değerler varsa, grup satır sayılarına her sütun için bağımsız bir toplama olarak bakmak istersiniz. Aksi takdirde, ortalama gibi şeyleri hesaplamak için gerçekte kaç kayıt kullanıldığına dair yanlış yönlendirilebilirsiniz, çünkü pandalar NaNortalama hesaplamadaki girdileri size söylemeden bırakacaktır .


1
Hey, yöntem zincirlemeyi kullandığınız çözümünüzü, özellikle de son çözümünüzü gerçekten çok seviyorum. Bununla birlikte, genellikle farklı sütunlara farklı toplama işlevleri uygulamak gerektiğinden, pd.concat kullanılarak elde edilen veri çerçeveleri de kapatılabilir. Bu belki daha kolay subsqeuent zincirleme daha okumak
Quickbeam2k1

4
güzel bir çözüm, ancak In [5]: counts_df = pd.DataFrame(df.groupby('col1').size().rename('counts')), eğer daha fazla analiz için veri çerçevesini değiştirmek istiyorsanız, boyutu () yeni bir sütun olarak ayarlamak daha iyidir, ki bucounts_df = pd.DataFrame(df.groupby('col1').size().reset_index(name='counts')
LancelotHolmes

2
"Daha fazla istatistik için sonuçlar dahil" biti için teşekkürler! Bir sonraki aramam, sonuçta ortaya çıkan çoklu dizini sütunlarda düzleştirmekle ilgili olduğundan, buradaki cevaba bağlayacağım: stackoverflow.com/a/50558529/1026
Nickolay

Harika! isnullBu soruna bir sütunda da eklemem için bana bir ipucu verebilir misiniz ? 'col4': ['median', 'min', 'count', 'isnull']
Peter.k

38

Hepsini Yöneten Bir İşlev: GroupBy.describe

İade count, mean, stdve diğer yararlı istatistikleri başına grupta.

df.groupby(['col1', 'col2'])['col3', 'col4'].describe()

# Setup
np.random.seed(0)
df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar',
                          'foo', 'bar', 'foo', 'foo'],
                   'B' : ['one', 'one', 'two', 'three',
                          'two', 'two', 'one', 'three'],
                   'C' : np.random.randn(8),
                   'D' : np.random.randn(8)})

from IPython.display import display

with pd.option_context('precision', 2):
    display(df.groupby(['A', 'B'])['C'].describe())

           count  mean   std   min   25%   50%   75%   max
A   B                                                     
bar one      1.0  0.40   NaN  0.40  0.40  0.40  0.40  0.40
    three    1.0  2.24   NaN  2.24  2.24  2.24  2.24  2.24
    two      1.0 -0.98   NaN -0.98 -0.98 -0.98 -0.98 -0.98
foo one      2.0  1.36  0.58  0.95  1.15  1.36  1.56  1.76
    three    1.0 -0.15   NaN -0.15 -0.15 -0.15 -0.15 -0.15
    two      2.0  1.42  0.63  0.98  1.20  1.42  1.65  1.87

Belirli istatistikleri almak için bunları seçin,

df.groupby(['A', 'B'])['C'].describe()[['count', 'mean']]

           count      mean
A   B                     
bar one      1.0  0.400157
    three    1.0  2.240893
    two      1.0 -0.977278
foo one      2.0  1.357070
    three    1.0 -0.151357
    two      2.0  1.423148

describebirden çok sütun için çalışır (değiştir ['C']- ['C', 'D']veya tamamen kaldır - ve ne olduğunu gör, sonuç bir MultiIndexed sütunlu veri çerçevesi).

Ayrıca dize verileri için farklı istatistikler de alırsınız. İşte bir örnek,

df2 = df.assign(D=list('aaabbccc')).sample(n=100, replace=True)

with pd.option_context('precision', 2):
    display(df2.groupby(['A', 'B'])
               .describe(include='all')
               .dropna(how='all', axis=1))

              C                                                   D                
          count  mean       std   min   25%   50%   75%   max count unique top freq
A   B                                                                              
bar one    14.0  0.40  5.76e-17  0.40  0.40  0.40  0.40  0.40    14      1   a   14
    three  14.0  2.24  4.61e-16  2.24  2.24  2.24  2.24  2.24    14      1   b   14
    two     9.0 -0.98  0.00e+00 -0.98 -0.98 -0.98 -0.98 -0.98     9      1   c    9
foo one    22.0  1.43  4.10e-01  0.95  0.95  1.76  1.76  1.76    22      2   a   13
    three  15.0 -0.15  0.00e+00 -0.15 -0.15 -0.15 -0.15 -0.15    15      1   c   15
    two    26.0  1.49  4.48e-01  0.98  0.98  1.87  1.87  1.87    26      2   b   15

Daha fazla bilgi için belgelere bakın .


Tüm dağılımlar normal değildir. IQR harika olurdu.
Brad

7

Bunu groupby ve count kullanarak kolayca yapabiliriz. Ancak, reset_index () 'i kullanmayı unutmamalıyız.

df[['col1','col2','col3','col4']].groupby(['col1','col2']).count().\
reset_index()

3
Bu çözüm, sütunlarda boş değer olmadığı sürece çalışır, aksi takdirde yanıltıcı olabilir (sayı, gruba göre gerçek gözlem sayısından daha düşük olacaktır).
Adrien Pacifico

4

Birden çok istatistik almak için dizini daraltın ve sütun adlarını koruyun:

df = df.groupby(['col1','col2']).agg(['mean', 'count'])
df.columns = [ ' '.join(str(i) for i in col) for col in df.columns]
df.reset_index(inplace=True)
df

üretir:

** buraya resim açıklamasını girin **


1

Bir grup nesnesi oluşturun ve aşağıdaki örnekte olduğu gibi çağrı yöntemlerini çağırın:

grp = df.groupby(['col1',  'col2',  'col3']) 

grp.max() 
grp.mean() 
grp.describe() 

1

Lütfen bu kodu deneyin

new_column=df[['col1', 'col2', 'col3', 'col4']].groupby(['col1', 'col2']).count()
df['count_it']=new_column
df

Ben kod her grubun saymak 'saymak' adlı bir sütun ekleyeceğini düşünüyorum

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.