Python Pandas:将日期时间列分组为小时和分钟聚合

86

这似乎是相当简单的,但经过近一整天的尝试,我仍未找到解决方案。我使用read_csv加载了我的数据帧,并轻松解析、合并和索引了日期和时间列成为一个列,但现在我想能够按小时和分钟分组进行重塑和计算,类似于在Excel中数据透视表进行分组并选择“小时”和“分钟”,而不选择其他内容。

我知道如何进行按小时或按分钟重新采样,但它仍会保留与每个小时/分钟相关联的日期部分,而我只想聚合数据集到小时和分钟,类似于在Excel数据透视表中进行分组并选择“小时”和“分钟”,但不选择其他任何内容。

非常感谢您的任何帮助。


从你拥有的每个datetime对象中获取一个time对象是否有帮助?您可以从dataframe.index创建一个pandas.Series对象,然后将其分配给索引(替换当前索引)。您能“打印”一些数据框的行吗? - heltonbiker
1
谢谢。如果您是指使用时间对象从日期时间列中获取时间,我不太熟悉。我刚刚找到了一种非常接近我所需的方法,分别使用以下代码进行小时和分钟,但是否有更简单的方法来做到这一点,特别是将小时和分钟放在一起的方法?:hourly = ims_havas.groupby(ims_havas.index.hour).sum() - horatio1701d
5个回答

77

不能做吗,其中 df 是您的DataFrame:

times = pd.to_datetime(df.timestamp_col)
df.groupby([times.dt.hour, times.dt.minute]).value_col.sum()

1
是的,这对我也完美地起作用了,但我有一个后续问题:我如何在matlibplot中使用这个“分组时间序列”作为我的x轴? - 2705114-john
27
我必须处理 df.groupby([times.dt.hour, times.dt.minute]) ... - akilat90
10
这在Python 3中可行吗?pd.to_datetime函数似乎会创建一个pandas.core.series.Series对象,但没有任何datetime特性。我得到了“AttributeError:'Series'对象没有'hour'属性”。 - Adrian Keister
7
它可行,你只需要在前面加上 "dt" 前缀。在这种情况下,它将像 @akilat90 所说的那样写为 times.dt.hour - Roughmar

54

威斯的代码对我没用。但是DatetimeIndex函数(文档)起到了作用:

times = pd.DatetimeIndex(data.datetime_col)
grouped = df.groupby([times.hour, times.minute])

DatetimeIndex对象是pandas中时间的表示形式。第一行创建了一个datetime数组。第二行使用该数组获取所有行的小时和分钟数据,允许按这些值进行分组(文档)。


1
我喜欢你使用另一个数据框进行分组的方式。我本来会创建不必要的列。 - bonobo
如果您有一个日期时间索引,您可以使用grouped = df.groupby([df.index.hour, df.index.minute])进行分组。 - squarespiral

21

我在搜索这种分组的方法时发现了这篇文章。Wes上面的代码对我不起作用,我不确定是因为 pandas 版本的变化。

pandas 0.16.2 中,我最终做的是:

grp = data.groupby(by=[data.datetime_col.map(lambda x : (x.hour, x.minute))])
grp.count()

如果你希望使用分组索引,则会得到(小时,分钟)元组。 如果你想要多重索引:

grp = data.groupby(by=[data.datetime_col.map(lambda x : x.hour),
                       data.datetime_col.map(lambda x : x.minute)])

7

我有一个与Wes&Nix的答案不同的备选方案,只需一行代码,假设您的列已经是日期时间列,您无需单独获取小时和分钟属性:

df.groupby(df.timestamp_col.dt.time).value_col.sum()

3
这可能有点晚了,但我找到了一个非常好的解决方案,适用于遇到相同问题的任何人。 我有一个像这样的df:
datetime              value
2022-06-28 13:28:08   15
2022-06-28 13:28:09   30
...                   ...
2022-06-28 14:29:11   20
2022-06-28 14:29:12   10

我想将那些时间戳按秒间隔转换为每分钟间隔的时间戳,并在该过程中添加值列。

有一种简洁的方法来完成这个任务:

df['datetime'] = pd.to_datetime(df['datetime']) #if not already as datetime object
grouped = df.groupby(pd.Grouper(key='datetime', axis=0, freq='T')).sum()
print(grouped.head())

结果:

datetime              value
2022-06-28 13:28:00   45
...                   ...
2022-06-28 14:29:00   30

freq = 'T' 代表分钟。你也可以按小时或天分组。它们被称为偏移别名


这对于按照例如5分钟或15分钟的间隔进行聚合非常有用,但我认为OP(包括我自己)正在寻找一种按时间间隔计数而不带日期的方法,以便例如在30天的月份中计算出所有发生在8:00和8:14之间的条目,以及所有发生在8:15和8:29之间的条目,而不考虑它们发生的日期。我自己尝试了几个变化,但无法找到一种既可以重新采样为15T又可以忽略datetime的日期部分的方法。我可以做其中之一,但不能同时做两者。 - Don 'FreihEitner' Eitner
请忽略我之前的帖子。我的问题是使用.resample()获取15分钟间隔的时间,但没有意识到这也在聚合行。现在我正在对找到的每一行使用lambda函数和math.floor(dt.minute/15)*15来提取每一行的15分钟间隔,然后使用仅包含这些时间值的列进行操作。 - Don 'FreihEitner' Eitner
忽略我之前的帖子。我的问题是使用 .resample() 方法以 15 分钟的间隔获取时间,但没有意识到这也在聚合行。我现在对每一行找到的数据使用 lambda 函数和 math.floor(dt.minute/15)*15 来提取每行的 15 分钟间隔,然后只使用这些时间值的一列进行操作。 - Don 'FreihEitner' Eitner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接