web-dev-qa-db-fra.com

Conversion d'une sortie Pandas GroupBy de Series en DataFrame

Je commence avec des données d'entrée comme celle-ci

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

Qui, une fois imprimé, apparaît comme ceci:

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

Le regroupement est assez simple:

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

et l’impression donne un objet GroupBy:

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

Mais ce que je veux finalement, c’est un autre objet DataFrame qui contient toutes les lignes de l’objet GroupBy. En d'autres termes, je veux obtenir le résultat suivant:

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

Je ne vois pas trop comment y parvenir dans la documentation pandas. Toute allusion serait la bienvenue.

405
saveenr

g1 ici est un DataFrame. Il a un index hiérarchique, cependant:

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)

Peut-être que vous voulez quelque chose comme ça?

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

Ou quelque chose comme:

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
443
Wes McKinney

Simplement, cela devrait faire la tâche:

import pandas as pd

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

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

Grouped_df.size () extrait le nombre unique groupby et la méthode reset_index () réinitialise le nom de la colonne souhaitée. Enfin, la fonction pandas Dataframe () est appelée pour créer un objet DataFrame.

12
Surya

Peut-être que je comprends mal la question, mais si vous voulez reconvertir le groupe en un cadre de données, vous pouvez utiliser .to_frame (). Je voulais réinitialiser l'index lorsque j'ai fait cela, alors j'ai également inclus cette partie.

exemple de code sans rapport avec la question

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

J'ai trouvé cela a fonctionné pour moi.

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()
5
thefebruaryman

La clé consiste à utiliser la méthode reset_index () .

Utilisation:

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()

Maintenant vous avez votre nouvelle base de données en g1 :

result dataframe

3
Ferd

La solution ci-dessous peut être plus simple:

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

J'ai agrégé avec Qty wise data et enregistre dans dataframe

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

Ces solutions ne fonctionnaient que partiellement pour moi car je faisais plusieurs agrégations. Voici un exemple de sortie de mon regroupé par ce que je voulais convertir en un cadre de données:

Groupby Output

Parce que je voulais plus que le nombre fourni par reset_index (), j'ai écrit une méthode manuelle pour convertir l'image ci-dessus en image. Je comprends que ce n’est pas la façon la plus pythonique/pandas de le faire, car elle est assez verbeuse et explicite, mais c’était tout ce dont j'avais besoin. Fondamentalement, utilisez la méthode reset_index () expliquée ci-dessus pour démarrer un cadre de données "scaffolding", puis parcourez les paires de groupes dans le cadre de données groupé, récupérez les index, effectuez vos calculs par rapport au cadre de données non groupé et définissez la valeur dans votre nouveau cadre de données agrégé. .

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]

Si vous n'avez pas besoin d'un dictionnaire, les calculs pourraient être appliqués en ligne dans la boucle for:

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