Pandas GroupBy çıkışını Seriden DataFrame'e dönüştürme


495

Bunun gibi girdi verileriyle başlıyorum

df1 = pandas.DataFrame( { 
    "Name" : ["Alice", "Bob", "Mallory", "Mallory", "Bob" , "Mallory"] , 
    "City" : ["Seattle", "Seattle", "Portland", "Seattle", "Seattle", "Portland"] } )

Yazdırıldığında şu şekilde görünür:

   City     Name
0   Seattle    Alice
1   Seattle      Bob
2  Portland  Mallory
3   Seattle  Mallory
4   Seattle      Bob
5  Portland  Mallory

Gruplama yeterince basittir:

g1 = df1.groupby( [ "Name", "City"] ).count()

ve baskı bir GroupBynesne verir :

                  City  Name
Name    City
Alice   Seattle      1     1
Bob     Seattle      2     2
Mallory Portland     2     2
        Seattle      1     1

Ama sonunda istediğim GroupBy nesnesindeki tüm satırları içeren başka bir DataFrame nesnesidir. Başka bir deyişle, aşağıdaki sonucu elde etmek istiyorum:

                  City  Name
Name    City
Alice   Seattle      1     1
Bob     Seattle      2     2
Mallory Portland     2     2
Mallory Seattle      1     1

Panda belgelerinde bunu nasıl başaracağımı tam olarak göremiyorum. Herhangi bir ipucu memnuniyetle karşılanacaktır.


1
Soru bir yana: hangi panda versiyonunu kullanıyorsunuz? İlk 2 komutu yürütürsem g1'i alıyorumEmpty DataFrame Columns: [] Index: [(Alice, Seattle), (Bob, Seattle), (Mallory, Portland), (Mallory, Seattle)]
Timofey

1
Sorunun başlığı kabul edilen cevapla ilgili yanıltıcı
Matanster

@matanster cevabı bilmek için buraya ne geldiğinizi sorabilir miyim? Daha doğru bir cevap yazmayı ve kullanıcıların dikkatini soru altındaki bir yorumla yönlendirmeyi düşünebiliriz.
cs95

@coldspeed Bu sadece SO ile ilgili tipik bir konudur, soru başlıklarının soru ve cevapların içeriğinden önemli ölçüde ayrılmasına izin verilir. Meta kadar düşmanca olmasaydı, muhtemelen orada yetiştirmek için yararlı bir özellik olurdu.
Ocak'ta

@matanster Katılıyorum, ancak cevabı gerçekten aradığınızı bilmeyi merak ediyordum, böylece sizi buraya götürdü.
cs95

Yanıtlar:


530

g1Burada olan bir DataFrame. Yine de hiyerarşik bir dizine sahiptir:

In [19]: type(g1)
Out[19]: pandas.core.frame.DataFrame

In [20]: g1.index
Out[20]: 
MultiIndex([('Alice', 'Seattle'), ('Bob', 'Seattle'), ('Mallory', 'Portland'),
       ('Mallory', 'Seattle')], dtype=object)

Belki de böyle bir şey ister misin?

In [21]: g1.add_suffix('_Count').reset_index()
Out[21]: 
      Name      City  City_Count  Name_Count
0    Alice   Seattle           1           1
1      Bob   Seattle           2           2
2  Mallory  Portland           2           2
3  Mallory   Seattle           1           1

Ya da şöyle bir şey:

In [36]: DataFrame({'count' : df1.groupby( [ "Name", "City"] ).size()}).reset_index()
Out[36]: 
      Name      City  count
0    Alice   Seattle      1
1      Bob   Seattle      2
2  Mallory  Portland      2
3  Mallory   Seattle      1

27
reset.index()işi yapar, harika!
gented

54
Sen kullanılmış olabilir:df1.groupby( [ "Name", "City"] ).size().to_frame(name = 'count').reset_index()
Nehal J Wani

3
İkinci örnek .reset_index(), bana elde edeceğiniz çıktıya katılmanın en iyi yolu gibi görünüyor df.groupby('some_column').apply(your_custom_func). Bu benim için sezgisel değildi.
Alexander

5
Bu Python 3'te de geçerli mi? pandas.core.groupby.DataFrameGroupByNesneyi döndüren bir groupby işlevi buluyorum , değil pandas.core.frame.DataFrame.
Adrian Keister

3
Bu cevap en son python ve pandalar için ilgisiz görünüyor
Matanster

127

Sürüm 0.16.2 gerektirdiği için Wes tarafından verilen cevabı biraz değiştirmek istiyorum as_index=False. Ayarlamazsanız, boş bir veri çerçevesi alırsınız.

Kaynak :

Toplama işlevleri, sütunlar olarak adlandırıldıysa toplandığınız grupları as_index=Truevarsayılan olarak döndürmez . Gruplandırılmış sütunlar, döndürülen nesnenin dizinleri olacaktır.

Geçme as_index=False, sütunlar olarak adlandırılmışlarsa, topladığınız grupları döndürür.

Fonksiyonları, örneğin dönen nesnelerin boyut azaltmak olanlar vardır verilerini birleştirme: mean, sum, size, count, std, var, sem, describe, first, last, nth, min, max. Örneğin yaptığınızda DataFrame.sum()ve geri döndüğünüzde olan budur a Series.

n. redüktör veya filtre görevi görebilir, buraya bakınız .

import pandas as pd

df1 = pd.DataFrame({"Name":["Alice", "Bob", "Mallory", "Mallory", "Bob" , "Mallory"],
                    "City":["Seattle","Seattle","Portland","Seattle","Seattle","Portland"]})
print df1
#
#       City     Name
#0   Seattle    Alice
#1   Seattle      Bob
#2  Portland  Mallory
#3   Seattle  Mallory
#4   Seattle      Bob
#5  Portland  Mallory
#
g1 = df1.groupby(["Name", "City"], as_index=False).count()
print g1
#
#                  City  Name
#Name    City
#Alice   Seattle      1     1
#Bob     Seattle      2     2
#Mallory Portland     2     2
#        Seattle      1     1
#

DÜZENLE:

Versiyonda 0.17.1ve daha sonra kullanabileceğiniz subsetiçinde countve reset_indexparametresi ile namede size:

print df1.groupby(["Name", "City"], as_index=False ).count()
#IndexError: list index out of range

print df1.groupby(["Name", "City"]).count()
#Empty DataFrame
#Columns: []
#Index: [(Alice, Seattle), (Bob, Seattle), (Mallory, Portland), (Mallory, Seattle)]

print df1.groupby(["Name", "City"])[['Name','City']].count()
#                  Name  City
#Name    City                
#Alice   Seattle      1     1
#Bob     Seattle      2     2
#Mallory Portland     2     2
#        Seattle      1     1

print df1.groupby(["Name", "City"]).size().reset_index(name='count')
#      Name      City  count
#0    Alice   Seattle      1
#1      Bob   Seattle      2
#2  Mallory  Portland      2
#3  Mallory   Seattle      1

Arasındaki fark countve sizeolmasıdır sizeederken NaN değerleri sayar countdeğil.


8
Bence bu en kolay yol - reset_index ile seri sütununu adlandırabileceğiniz güzel gerçeği kullanan bir astar:df1.groupby( [ "Name", "City"]).size().reset_index(name="count")
Ben

1
Bir nedeni var mı as_index=False' stopped working in latest versions? I also tried to run df1.groupby ([ "Ad", "Şehir"], as_index Yanlış =) .size) ( `fakat gruplaşma sonucudur muhtemelen çünkü (sonucunu etkilemez SeriesdeğilDataFrame
Roma Pekar

1
Emin değilim, ama sadece 2 sütun var ve groupbybu sütunlar tarafından görünüyor . Ama emin değilim çünkü panda geliştiricisi değilim.
jezrael

20

Basitçe, bu görevi yapmalıdır:

import pandas as pd

grouped_df = df1.groupby( [ "Name", "City"] )

pd.DataFrame(grouped_df.size().reset_index(name = "Group_Count"))

Burada, grouped_df.size()benzersiz groupby sayısını yukarı çeker ve reset_index()yöntem olmasını istediğiniz sütunun adını sıfırlar. Son olarak, Dataframe()bir DataFrame nesnesi oluşturmak için panda işlevi çağrılır.


2
.To_frame () yöntemine göz atın: grouped_df.size (). To_frame ('Group_Count')
Sealander

12

Anahtar, reset_index () yöntemini kullanmaktır.

kullanın:

import pandas

df1 = pandas.DataFrame( { 
    "Name" : ["Alice", "Bob", "Mallory", "Mallory", "Bob" , "Mallory"] , 
    "City" : ["Seattle", "Seattle", "Portland", "Seattle", "Seattle", "Portland"] } )

g1 = df1.groupby( [ "Name", "City"] ).count().reset_index()

Şimdi de yeni dataframe var g1 :

sonuç veri çerçevesi


9

Belki soruyu yanlış anlıyorum, ancak grubu tekrar bir veri çerçevesine dönüştürmek istiyorsanız .to_frame () kullanabilirsiniz. Bunu yaptığımda indeksi sıfırlamak istedim, bu yüzden de bu kısmı dahil ettim.

soru ile ilgili olmayan örnek kod

df = df['TIME'].groupby(df['Name']).min()
df = df.to_frame()
df = df.reset_index(level=['Name',"TIME"])

6

Bunun benim için işe yaradığını gördüm.

import numpy as np
import pandas as pd

df1 = pd.DataFrame({ 
    "Name" : ["Alice", "Bob", "Mallory", "Mallory", "Bob" , "Mallory"] , 
    "City" : ["Seattle", "Seattle", "Portland", "Seattle", "Seattle", "Portland"]})

df1['City_count'] = 1
df1['Name_count'] = 1

df1.groupby(['Name', 'City'], as_index=False).count()

6

Aşağıdaki çözüm daha basit olabilir:

df1.reset_index().groupby( [ "Name", "City"],as_index=False ).count()

4

Ben Qty bilge veri ile toplama ve veri karesinde sakladım

almo_grp_data = pd.DataFrame({'Qty_cnt' :
almo_slt_models_data.groupby( ['orderDate','Item','State Abv']
          )['Qty'].sum()}).reset_index()

3

Bu çözümler sadece kısmen benim için çalıştı çünkü birden fazla toplama yapıyordum. İşte bir veri çerçevesine dönüştürmek istedim tarafından gruplandırılmış örnek bir çıktı:

Groupby Çıkışı

Ben reset_index () tarafından sağlanan sayım daha istedim, yukarıdaki görüntü bir veri karesine dönüştürmek için manuel bir yöntem yazdım. Bunun oldukça ayrıntılı ve açık olduğu için bunu yapmanın en pitonik / panda yolu olmadığını anlıyorum, ama tüm ihtiyacım olan buydu. Temel olarak, bir "iskele" veri çerçevesi başlatmak için yukarıda açıklanan reset_index () yöntemini kullanın, ardından gruplandırılmış veri çerçevesinde grup eşleştirmeleri arasında döngü yapın, endeksleri alın, hesaplarınızı çözülmemiş veri çerçevesine göre yapın ve yeni toplu veri çerçevenizdeki değeri ayarlayın .

df_grouped = df[['Salary Basis', 'Job Title', 'Hourly Rate', 'Male Count', 'Female Count']]
df_grouped = df_grouped.groupby(['Salary Basis', 'Job Title'], as_index=False)

# Grouped gives us the indices we want for each grouping
# We cannot convert a groupedby object back to a dataframe, so we need to do it manually
# Create a new dataframe to work against
df_aggregated = df_grouped.size().to_frame('Total Count').reset_index()
df_aggregated['Male Count'] = 0
df_aggregated['Female Count'] = 0
df_aggregated['Job Rate'] = 0

def manualAggregations(indices_array):
    temp_df = df.iloc[indices_array]
    return {
        'Male Count': temp_df['Male Count'].sum(),
        'Female Count': temp_df['Female Count'].sum(),
        'Job Rate': temp_df['Hourly Rate'].max()
    }

for name, group in df_grouped:
    ix = df_grouped.indices[name]
    calcDict = manualAggregations(ix)

    for key in calcDict:
        #Salary Basis, Job Title
        columns = list(name)
        df_aggregated.loc[(df_aggregated['Salary Basis'] == columns[0]) & 
                          (df_aggregated['Job Title'] == columns[1]), key] = calcDict[key]

Bir sözlük sizin işiniz değilse, hesaplamalar for döngüsünde satır içi uygulanabilir:

    df_aggregated['Male Count'].loc[(df_aggregated['Salary Basis'] == columns[0]) & 
                                (df_aggregated['Job Title'] == columns[1])] = df['Male Count'].iloc[ix].sum()

Çözümünüz için kullandığınız veri kümesini paylaşabilir misiniz? Çok teşekkürler!
JeffZheng
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.