如何将数年的数据汇总到一个数据帧中

时间:2014-03-07 11:14:47

标签: python pandas

我有一个数据框df1,其中包含有关商家的信息。每一行都是一项业务。 G列具有业务ID,R和Z列(以及其他列)具有整数,告诉我不同​​的收入指标。 A列有年份。我想生成一个新的数据框架,每个企业只有一行,其中不同年份的值合并在一起。比如B-Q列每年不会改变,但R和Z会改变。

为实现这一目标,我正在进行df1.groupby("G", as_index=False)["Z"].sum()以获得列Z的总收入。我会同样做df1.groupby("G", as_index=False)["R"].sum()等等。

我希望名为df2的最终数据框每个业务有一行,其中df1的所有列都不会更改,而且新的Sum列也不会更改。以下代码是我的尝试,但它不对。问题是我不明白如何将groupby的结果添加到列中。

df2['SumZ'] = df.groupby("G")["Z"].sum()
df2['SumR'] = df.groupby("G")["R"].sum()
df2['RZ'] =df2['SumR']/df2['SumZ']

一种方法是使用B-Q列的副本创建一个新的数据帧df2,然后将这些列添加到其中。

怎么能这样做?我试图创建一个新的数据帧然后添加列失败。

这是我的完整代码。

from __future__ import division
import sys
import pandas as pd

inputfile = sys.argv[1]
city = sys.argv[2]
xl = pd.ExcelFile(inputfile)

df1 = xl.parse(xl.sheet_names[0], skiprows=4,skip_footer=9)   
df1.columns = [chr(65+i) for i in xrange(len(df1.columns))]
df1.replace('*', 3, inplace=True)
df1 = df1.convert_objects(convert_numeric=True)

for c in ['R', 'T', 'V', 'X', 'Z']:
    df1[c] = df1[c].astype(int)

for c in ['B','E', 'H', 'J', 'O', 'Q', 'S', 'U', 'W', 'Y']:
    df1.pop(c)
print "Read in..."
#Now attempt and fail to make a new dataframe summarized by year    
df2['SumZ'] = df1.groupby("G", as_index=False)["Z"].sum()
df2['SumR'] = df1.groupby("G", as_index=False)["R"].sum()

这就是我需要的,但看起来非常难看。

summary_data = df1[['G', 'R','T', 'V', 'X', 'Z']].groupby('G').sum()
constant_data = df1.drop(['R', 'T', 'V', 'X', 'Z'], axis=1).groupby('G').first()
df2 = summary_data.join(constant_data)

1 个答案:

答案 0 :(得分:2)

您需要在groupby对象上调用.agg方法。 .agg代表聚合。您基本上同意将数据整合到一个观察中。然后,您可以将函数字典传递给agg,告诉它如何处理每列。所以想象一下你的数据框看起来像这样:

import pandas as pd
import random

df = pd.DataFrame({'business' : ['business_1', 'business_2', 'business_3', 'usiness_4', 'business_1', 'business_2', 'business_3', 'business_4'], \
               'years' : [2013, 2013, 2013, 2013, 2014, 2014, 2014, 2014], \
               'zip_code' : ['101', '102', '103', '104', '101', '102', '103', '104'], \
               'profit' : [random.randint(1000, 2000) for x in xrange(8)]})

现在'business'就像你的id变量,zip_code是你的数据不会改变,利润就是你想要的东西。

你已经知道用什么函数来得到和,它的总和。但是你需要编写一个函数来获取邮政编码唯一的唯一值。你可以这样做:

def take_single(series):
    return series.unique()[0]

现在创建你的groupby对象,创建一个要在每列上执行的函数字典,然后将该字符串传递给.agg方法(聚合),如下所示:

df_grouped = df.groupby('business') 
function_dict = {'business' : take_single, 'zip_code' : take_single, 'profit' : sum}
df_grouped.agg(function_dict)

这会得到你想要的结果。

有一点需要注意的是,传递给它的聚合函数的一系列数据会自动作为函数的第一个参数传递。因此在take_single函数中,您会看到一个名为series的参数。但是这个参数在调用.agg时自动传递,因此不需要在函数字典中指定它。

Sum是内置函数,因此无需单独编写。

要复制它,只需使用带有take_single值的B-Q键创建字典,然后使用sum函数值创建R和Z.这有意义吗?

它不容易理解groupby(对我来说无论如何),但它是有用的....