熊猫数据帧的每日气候学

时间:2017-07-20 05:11:27

标签: python pandas

        id      vi       dates     f_id
0  5532714  0.549501  2015-07-07    ff_22
1  5532715  0.540969  2015-07-08    ff_22
2  5532716  0.531477  2015-07-09    ff_22
3  5532717  0.521029  2016-07-09    ff_22
4  5532718  0.509694  2017-07-11    ff_22

在上面的数据框中,我想计算气候学,即跨越多年的数据帧的每日平均值。目前我试过这个:

df.index = pd.to_datetime(df.dates)
df.groupby([df.index.month, df.index.day])['vi'].transform('mean')

我希望输出没有多索引。

2 个答案:

答案 0 :(得分:3)

如果我理解正确,您需要创建分组索引以进行分组。我选择使用'%b, %d'格式化日期,但您可以使用strftime.org选项中的任何月/日组合。

考虑由4年随机每日数据组成的数据框df

tidx = pd.date_range('2010-01-01', '2013-12-31', name='dates')

np.random.seed([3,1415])
df = pd.DataFrame(dict(vi=np.random.rand(tidx.size)), tidx)

我会选择从2012制作我的类别标签,因为它是闰年,并且会包含Feb 29。通过创建类别,大熊猫将知道Jan, 01之前的Aug, 31

fmt = '%b, %d'
categories = pd.CategoricalIndex(
    df.index.strftime(fmt),
    pd.date_range('2012-01-01', '2012-12-31').strftime(fmt)
)
df.groupby(categories).mean()

               vi
Jan, 01  0.452812
Jan, 02  0.422205
Jan, 03  0.409369
Jan, 04  0.620173
Jan, 05  0.456044
Jan, 06  0.616172
Jan, 07  0.693760
Jan, 08  0.636427
Jan, 09  0.490981
Jan, 10  0.412720
Jan, 11  0.516009
Jan, 12  0.372129
...           ...
Dec, 20  0.523669
Dec, 21  0.372038
Dec, 22  0.609447
Dec, 23  0.568481
Dec, 24  0.612216
Dec, 25  0.765035
Dec, 26  0.368508
Dec, 27  0.558909
Dec, 28  0.371733
Dec, 29  0.516978
Dec, 30  0.654397
Dec, 31  0.793721

[366 rows x 1 columns]

答案 1 :(得分:2)

我认为您需要分配到新列:

df.index = pd.to_datetime(df.dates)
df['new'] = df.groupby([df.index.month, df.index.day])['vi'].transform('mean')
print (df)
                 id        vi       dates   f_id       new
dates                                                     
2015-07-07  5532714  0.549501  2015-07-07  ff_22  0.549501
2015-07-08  5532715  0.540969  2015-07-08  ff_22  0.540969
2015-07-09  5532716  0.531477  2015-07-09  ff_22  0.526253
2016-07-09  5532717  0.521029  2016-07-09  ff_22  0.526253
2017-07-11  5532718  0.509694  2017-07-11  ff_22  0.509694
df.index = pd.to_datetime(df.dates)
df = df.assign(new=df.groupby([df.index.month, df.index.day])['vi'].transform('mean'))
print (df)
                 id        vi       dates   f_id       new
dates                                                     
2015-07-07  5532714  0.549501  2015-07-07  ff_22  0.549501
2015-07-08  5532715  0.540969  2015-07-08  ff_22  0.540969
2015-07-09  5532716  0.531477  2015-07-09  ff_22  0.526253
2016-07-09  5532717  0.521029  2016-07-09  ff_22  0.526253
2017-07-11  5532718  0.509694  2017-07-11  ff_22  0.509694

然后在必要时reset_index

df = df.reset_index(drop=True)
print (df)
        id        vi       dates   f_id       new
0  5532714  0.549501  2015-07-07  ff_22  0.549501
1  5532715  0.540969  2015-07-08  ff_22  0.540969
2  5532716  0.531477  2015-07-09  ff_22  0.526253
3  5532717  0.521029  2016-07-09  ff_22  0.526253
4  5532718  0.509694  2017-07-11  ff_22  0.509694

但将列date转换为datetime似乎更好,然后reset_index不是必需的:

df.dates = pd.to_datetime(df.dates)
df['new'] = df.groupby([df.dates.dt.month, df.dates.dt.day])['vi'].transform('mean')
print (df)

        id        vi      dates   f_id       new
0  5532714  0.549501 2015-07-07  ff_22  0.549501
1  5532715  0.540969 2015-07-08  ff_22  0.540969
2  5532716  0.531477 2015-07-09  ff_22  0.526253
3  5532717  0.521029 2016-07-09  ff_22  0.526253
4  5532718  0.509694 2017-07-11  ff_22  0.509694

如果由于某种原因无法将列转换为datetime,则可以使用:

d = pd.to_datetime(df.dates)
df['new'] = df.groupby([d.dt.month, d.dt.day])['vi'].transform('mean')
print (df)
        id        vi       dates   f_id       new
0  5532714  0.549501  2015-07-07  ff_22  0.549501
1  5532715  0.540969  2015-07-08  ff_22  0.540969
2  5532716  0.531477  2015-07-09  ff_22  0.526253
3  5532717  0.521029  2016-07-09  ff_22  0.526253
4  5532718  0.509694  2017-07-11  ff_22  0.509694

---

transformaggregation之间的差异:

#changed sample data - dates    
print (df)
        id        vi       dates   f_id
0  5532714  0.549501  2015-07-07  ff_22
1  5532715  0.540969  2016-07-07  ff_22
2  5532716  0.531477  2015-07-09  ff_22
3  5532717  0.521029  2016-07-11  ff_22
4  5532718  0.509694  2017-07-11  ff_22

GroupBy.transform用于原始DataFrame中的新列 - 输出df的大小未更改,因此相同组的数据相同:

df.dates = pd.to_datetime(df.dates)
df['new'] = df.groupby([df.dates.dt.month, df.dates.dt.day])['vi'].transform('mean')
print (df)
        id        vi      dates   f_id       new
0  5532714  0.549501 2015-07-07  ff_22  0.545235
1  5532715  0.540969 2016-07-07  ff_22  0.545235
2  5532716  0.531477 2015-07-09  ff_22  0.531477
3  5532717  0.521029 2016-07-11  ff_22  0.515362
4  5532718  0.509694 2017-07-11  ff_22  0.515362

但是,如果输出GroupBy.mean输出agg的大小已更改,但输出中没有其他列(如果需要,则需要按here聚合每列):

df