从一天开始的n天将Pandas DataFrame分组

时间:2016-11-11 14:21:14

标签: python pandas

我刚刚发现了熊猫的力量,我喜欢它,但我无法弄清楚这个问题:

我有一个DataFrame df.head()

   lon   lat  h  filename                  time
0  19.961216  80.617627    -0.077165     60048 2002-05-15 12:59:31.717467
1  19.923916  80.614847    -0.018689     60048 2002-05-15 12:59:31.831467
2  19.849396  80.609257    -0.089205     60048 2002-05-15 12:59:32.059467
3  19.830776  80.607857     0.076485     60048 2002-05-15 12:59:32.116467
4  19.570708  80.588183     0.162943     60048 2002-05-15 12:59:32.888467

我想将我的数据分组为九天

gb = df.groupby(pd.TimeGrouper(key='time', freq='9D'))

第一组:

2002-05-15 12:59:31.717467       lon   lat  h filename                  time
0    19.961216  80.617627    -0.077165     60048 2002-05-15 12:59:31.717467
1    19.923916  80.614847    -0.018689     60048 2002-05-15 12:59:31.831467
2    19.849396  80.609257    -0.089205     60048 2002-05-15 12:59:32.059467
3    19.830776  80.607857     0.076485     60048 2002-05-15 12:59:32.116467
...

下一组:

2002-05-24 12:59:31.717467        lon   lat  height  filename                  time
815   18.309498  80.457024     0.187387     60309 2002-05-24 16:35:39.553563
816   18.291458  80.458514     0.061446     60309 2002-05-24 16:35:39.610563
817   18.273408  80.460014     0.129255     60309 2002-05-24 16:35:39.667563
818   18.255358  80.461504     0.046761     60309 2002-05-24 16:35:39.724563
...

所以数据从第一次(12:59:31.717467)算起,分为9天,而不是我想要的那天。

分组一天时:

gb = df.groupby(pd.TimeGrouper(key='time', freq='D'))

给了我:

2002-05-15 00:00:00       lon   lat  h  filename                  time
0    19.961216  80.617627    -0.077165     60048 2002-05-15 12:59:31.717467
1    19.923916  80.614847    -0.018689     60048 2002-05-15 12:59:31.831467
2    19.849396  80.609257    -0.089205     60048 2002-05-15 12:59:32.059467
3    19.830776  80.607857     0.076485     60048 2002-05-15 12:59:32.116467
...

我可以循环过去,直到我得到九天的间隔,但我认为它可以更聪明地完成,我正在寻找一个与YS(年初)相当的Grouper freq选项仅仅几天,一种设置开始时间的方法(可能是通过Grouper选项convention : {‘start’, ‘end’, ‘e’, ‘s’}),或???

我正在运行Python 3.5.2,而Pandas的版本是:0.19.0

4 个答案:

答案 0 :(得分:1)

如果将日期时间截断为给定日期的午夜,则分组将按预期工作(从当天开始)。我希望通过转换为日期时间来工作,例如

df['date'] = df['time'].apply(lambda x:x.date())

但是,除非索引是TimeGrouper,否则您无法使用datetime。 您可以使用两个选项,将日期时间直接截断为午夜,如下所示:

df['date'] = df['time'].apply(lambda x:x.replace(hour=0, minute=0, second=0, microsecond=0)))

或者,您可以先生成date个值,然后使用pd.to_datetime()函数将它们转换回日期时间:

df['date'] = df['time'].apply(lambda x: x.date() )
df['date'] = pd.to_datetime(df['date'])

答案 1 :(得分:1)

完成@mfitzp答案你可以这样做:

df['dateonly'] = df['time'].apply(lambda x: x.date())

唯一的问题是df['dateonly']不是DatetimeIndex

你需要先转换它:

df['dateonly'] = pd.to_datetime(df['dateonly'])

现在你可以分组了

gb = df.groupby(pd.TimeGrouper(key='dateonly', freq='9D'))

有关额外信息conventionPeriodIndex而非DatetimeIndex

一起使用

答案 2 :(得分:1)

删除第一行:

您最好的选择是normalize datetime列的第一行,以便将时间重置为00:00:00(午夜)并根据 9D <分组/ em> interval:

df.loc[0, 'time'] = df['time'].iloc[0].normalize()
for _, grp in df.groupby(pd.TimeGrouper(key='time', freq='9D')):
    print (grp)

#          lon        lat         h  filename                       time
# 0  19.961216  80.617627 -0.077165     60048 2002-05-15 00:00:00.000000
# 1  19.923916  80.614847 -0.018689     60048 2002-05-15 12:59:31.831467
# 2  19.849396  80.609257 -0.089205     60048 2002-05-15 12:59:32.059467
# 3  19.830776  80.607857  0.076485     60048 2002-05-15 12:59:32.116467
# 4  19.570708  80.588183  0.162943     60048 2002-05-15 12:59:32.888467
# ......................................................................

这会恢复其他行中的时间,因此您不会丢失该信息。

保留第一时间行:

如果你想保留第一次的行并且不对其进行任何更改,但只想从午夜开始分组,你可以这样做:

df_t_shift = df.shift()    # Shift one level down
df_t_shift.loc[0, 'time'] = df_t_shift['time'].iloc[1].normalize()
# Concat last row of df with the shifted one to account for the loss of row
df_t_shift = df_t_shift.append(df.iloc[-1], ignore_index=True)  

for _, grp in df_t_shift.groupby(pd.TimeGrouper(key='time', freq='9D')):
    print (grp)

#          lon        lat         h  filename                       time
# 0        NaN        NaN       NaN       NaN 2002-05-15 00:00:00.000000
# 1  19.961216  80.617627 -0.077165   60048.0 2002-05-15 12:59:31.717467
# 2  19.923916  80.614847 -0.018689   60048.0 2002-05-15 12:59:31.831467
# 3  19.849396  80.609257 -0.089205   60048.0 2002-05-15 12:59:32.059467
# 4  19.830776  80.607857  0.076485   60048.0 2002-05-15 12:59:32.116467
# 5  19.570708  80.588183  0.162943   60048.0 2002-05-15 12:59:32.888467

答案 3 :(得分:1)

我知道这是一个迟到的条目。但是根据pandas.Grouper documentation,您可以将origin对象的pandas.Grouper选项设置为"start_day",如下所示:

for _, grp in df.groupby(pd.Grouper(freq="9D", origin="start_day")):
    print(grp)

此选项是在 1.1.0 版本中添加的。