我有一个数据框

import pandas as pd

df=pd.DataFrame({'Players': [ 'Sam', 'Greg', 'Steve', 'Sam',
                 'Greg', 'Steve', 'Greg', 'Steve', 'Greg', 'Steve'],
                 'Wins': [10,5,5,20,30,20,6,9,3,10],
                 'Losses': [5,5,5,2,3,2,16,20,3,12],
                 'Type': ['A','B','B','B','A','B','B','A','A','B'],
                 })


如果我想总结一下,我可以手动制作另一个数据框:

p=df.groupby('Players')

summary = pd.DataFrame({'Total Games': p.Players.count(),
                        'Average Wins':p.Wins.mean(),
                        'Greatest Wins':p.Wins.max(),
                        'Unique games':p.Type.nunique()})


假设我要自动执行此汇总过程以创建数据帧(如果存在列X)执行汇总Y,那么这样做的最佳方法是什么?我曾尝试使用字典,但我认为我做错了

p=df.groupby('Players')
sumdict = {'Total Games': ['Players', p.Players.count()],
            'Average Wins':['Wins', p.Wins.mean()],
            'Greatest Wins':['Wins', p.Wins.max()],
            'Unique games':['Type', p.Type.nunique()],
            'Max Score':['Score', p.Score.max()]}

summary=pd.DataFrame()

for key, value in sumdict.items():
        if value[0] in df.columns:
            data = pd.DataFrame({key: value[1],})
            summary=summary.append(data)
        else:
            continue

最佳答案

熊猫DataFrame支持大多数dict方法,包括get(允许您将值替换为空键)。因此,您可以对所有列进行所需的统计,然后获取所需列的值,用空的Series替换缺少的列,然后删除NaN列(我使用Bad Value来演示丢失的情况列):

eser = pd.Series()
count = p.count().max(axis=1)
all_max = p.max()
score_max = all_max.get('Score', eser)
wins_max = all_max.get('Wins', eser)
wins_mean = p.mean().get('Wins', eser)
type_nunique = p.agg(lambda x: x.nunique()).get('Type', eser)

summary = pd.DataFrame({'Total Games': count,
                        'Average Wins': wins_mean,
                        'Greatest Wins': wins_max,
                        'Unique games': type_nunique,
                        'Max Score': score_max})
summary.dropna(axis=1, how='all', inplace=True)


或单行(涉及在所有列上两次计算max,对于少量的值应该不是问题):

summary = pd.DataFrame({'Total Games': p.count().max(axis=1),
                        'Average Wins': p.mean().get('Wins', pd.Series()),
                        'Greatest Wins': p.max().get('Wins', pd.Series()),
                        'Unique games': p.agg(lambda x: x.nunique()).get('Type', pd.Series()),
                        'Max Score': p.max().get('Score', pd.Series())}).dropna(axis=1, how='all')


两种方法的结果:

       Average Wins  Greatest Wins  Total Games  Unique games
Greg             11             30            4             2
Sam              15             20            2             2
Steve            11             20            4             2


没有dropna

       Average Wins  Greatest Wins  Max Score  Total Games  Unique games
Greg             11             30        NaN            4             2
Sam              15             20        NaN            2             2
Steve            11             20        NaN            4             2


如果性能是一个问题,那么上述操作将很慢,因为它们需要在所有列上计算多个统计信息,这意味着要先计算然后丢弃统计信息。一种更快但更丑陋的方法类似于在dict上使用循环的方法。

实现的问题是dict项没有被延迟评估,它们在创建dict时进行评估,这意味着它仍然尝试访问不存在的列。

下面的方法仅在找到该列时才获取该项并应用该函数(对count情况进行特殊处理,因为任何现有的列都将起作用):

sumdict = {'Total Games': (None, 'count'),
           'Average Wins': ('Wins', 'mean'),
           'Greatest Wins': ('Wins', 'max'),
           'Unique games': ('Type', 'nunique'),
           'Max Score': ('Score', 'max')}

summary = []
for key, (column, op) in sumdict.items():
    if column is None:
        res = p.agg(op).max(axis=1)
    elif column not in df:
        continue
    else:
        res = p[column].agg(lambda x: getattr(x, op)())
    summary.append(pd.DataFrame({key: res}))
summary = pd.concat(summary, axis=1)


尽管列顺序不同,但结果与上述方法相同。

关于python - Pandas 根据存在的列生成数据框,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29964552/

10-13 08:39