在python中按特定年份对数据进行分组

Posted

技术标签:

【中文标题】在python中按特定年份对数据进行分组【英文标题】:Grouping data by specific years in python 【发布时间】:2018-09-17 03:50:51 【问题描述】:

我想创建一个按地区和日期分组的数据框,以显示特定年份中某个地区的平均年龄。所以我的列看起来像

地区、年份、平均年龄

目前为止:

#specify aggregation functions to column'age'    
ageAverage = 'age':'average age':'mean' 

#groupby and apply functions    
ageDataFrame = data.groupby(['Region', data.Date.dt.year]).agg(ageAverage)

这很好用,但我怎样才能做到只对特定年份的数据进行分组呢?比如在 2010 年到 2015 年之间?

【问题讨论】:

【参考方案1】:

使用@jezrael 的数据的两个变体(谢谢) 这些非常接近@jezrael 已经展示的内容。仅将此视为可以做其他事情的演示。正如@jezrael 在 cmets 中指出的那样,最好先进行预过滤,因为它会减少整体处理。

pandas.IndexSlice

而不是使用between进行预过滤

data.groupby(
    ['Region', data.Date.dt.year]

)['average age'].agg(
    [('age', 'mean')]

).loc[pd.IndexSlice[:, 2010:2015], :]

             age
Region Date     
reg1   2010    2
       2011    2
reg2   2012    6
       2013   17
       2014   19
       2015   10

between 作为groupby 的一部分

data.groupby(
    [data.Date.dt.year.between(2010, 2015),
     'Region', data.Date.dt.year]

)['average age'].agg(
    [('age', 'mean')]

).loc[True]

             age
Region Date     
reg1   2010    2
       2011    2
reg2   2012    6
       2013   17
       2014   19
       2015   10

【讨论】:

我认为为了获得更好的性能,最好先删除不必要的数据,然后再删除groupby - 通常更少的数据处理,更好的性能。你怎么看? 我完全同意。我正要进一步编辑。先检查其他问题(-:【参考方案2】:

你需要先过滤between:

ageDataFrame = (data[data.Date.dt.year.between(2010, 2015)]
                  .groupby(['Region', data.Date.dt.year])
                  .agg(ageAverage))

同样在last version of pandas 0.22.0获取:

规范错误:无法使用嵌套字典执行年龄重命名

正确的解决方案是在groupby 之后指定列表中的列并按tuple 聚合 - 第一个值是新列名和第二个聚合函数:

np.random.seed(123)

rng = pd.date_range('2009-04-03', periods=10, freq='13M')
data = pd.DataFrame('Date': rng,
                     'Region':['reg1'] * 3 + ['reg2'] * 7,
                     'average age': np.random.randint(20, size=10))  
print (data)
        Date Region  average age
0 2009-04-30   reg1           13
1 2010-05-31   reg1            2
2 2011-06-30   reg1            2
3 2012-07-31   reg2            6
4 2013-08-31   reg2           17
5 2014-09-30   reg2           19
6 2015-10-31   reg2           10
7 2016-11-30   reg2            1
8 2017-12-31   reg2            0
9 2019-01-31   reg2           17

ageAverage = ('age','mean')

#groupby and apply functions    
ageDataFrame = (data[data.Date.dt.year.between(2010, 2015)]
                 .groupby(['Region', data.Date.dt.year])['average age']
                 .agg(ageAverage))
print (ageDataFrame)
             age
Region Date     
reg1   2010    2
       2011    2
reg2   2012    6
       2013   17
       2014   19
       2015   10

【讨论】:

哦,太好了!我不知道我可以在两者之间使用。非常感谢,工作完美。 一种相关但随机的问题,我试图弄清楚如何在箱线图中绘制该数据框,但似乎无法正确解决。到目前为止,我使用 seaborn:sns.plot(kind='box', y='age', x='date', hue='age', data=ageDataFrame, size=8, aspect=1.5, legend_out=true) 有什么想法吗? @user3452963 - 我认为首先需要reset_index(),比如ageDataFrame = (data[data.Date.dt.year.between(2010, 2015)] .groupby(['Region', data.Date.dt.year])['average age'] .agg(ageAverage) .reset_index()) print (ageDataFrame),然后是sns.boxplot(y='age', x='Date', hue='age', data=ageDataFrame),docs @user3452963 - 不确定,但似乎问题是需要未聚合的数据。 @user3452963 - 例如我测试np.random.seed(123) L = list('abcde') N = 100 rng = pd.date_range('2009-04-03', periods=N, freq='1M') data = pd.DataFrame('Date': rng, 'Region':np.random.choice(L, size=N), 'average age': np.random.rand(N)) print (data) data = data[data.Date.dt.year.between(2010, 2015)] data.Date = data.Date.dt.year sns.boxplot(y='average age', x='Date', hue='Region', data=data)

以上是关于在python中按特定年份对数据进行分组的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Freemarker 中按特定值对列表进行分组?

在 SQL/Impala 中按特定的分钟数对日期时间进行分组

在python中按半小时间隔对文件列表进行分组

在R中具有相同组ID的另一个数据帧中按值过滤分组数据帧

MDX 查询以对具有特定日期范围的日期维度进行分组

在 jQuery 中按数据属性对 HTML 元素进行分组和计数