我有一个大约每10秒用时间戳索引一次的pandas数据框架(python)。我想找到小时平均值,但我找到的所有函数都以偶数小时开始平均(例如,小时9包括从08.00:00到08:59:50的数据)。假设我有下面的数据框。
Timestamp value data
2022-01-01 00:00:00 0.0 5.31
2022-01-01 00:00:10 0.0 0.52
2022-01-01 00:00:20 1.0 9.03
2022-01-01 00:00:30 1.0 4.37
2022-01-01 00:00:40 1.0 8.03
...
2022-01-01 13:52:30 1.0 9.75
2022-01-01 13:52:40 1.0 0.62
2022-01-01 13:52:50 1.0 3.58
2022-01-01 13:53:00 1.0 8.23
2022-01-01 13:53:10 1.0 3.07
Freq: 10S, Length: 5000, dtype: float64
那么我要做的是:
- 只看那些持续1小时的数据值为1的数据
- 找到这些小时的每小时平均值(例如,可以在01:30:00-02:29:50和11:16:30 - 12:16:20之间)。
我希望我把问题讲清楚了。我该怎么做呢?
编辑:
也许这个问题的措辞有点不清楚。我增加了第三列data
,这是我想求的均值。我只对value = 1
持续一小时的时间间隔感兴趣,其余的数据可以排除。
编辑# 2:
我的问题的一点背景:我有一个传感器给我每10秒的数据。对于待"批准"的数据;某些需求是要满足的(在这个例子中是value
),我需要每小时的平均值(最好是发生这种情况的时间戳)。因此,为了将可能包含在我的分析中的小时数最大化,我希望找到完整的小时数,即使它们不是在偶数时间戳开始的。
如果我理解正确,你想要一个条件平均值-计算data
列的每小时平均值条件在value
列上,每10秒行1
。
假设您的数据框名为df
,执行此操作的步骤如下:
创建分组列
这是您的"小时"列,可以通过
创建df['hour'] = df.Timestamp.hour
<<p>创建条件/strong>现在我们有了一个列来标识组,我们可以检查哪些组符合条件-只有那些value
始终等于1
的组。如果我们有10秒的间隔,并且是每小时,那么如果我们按小时分组,然后和这一列,那么我们应该得到360,因为每小时有360个10秒的间隔。
分组计算
现在可以对aggregate函数进行分组和使用:
- 对
value
列求和,根据条件 求值 - 计算
data
列返回的有效小时数的平均值
# group and aggregate
df_mean = df[['hour', 'value', 'data']].groupby('hour').aggregate({'value': 'sum', 'data': 'mean'})
# apply condition
df_mean = df_mean[df_mean['value'] == 360]
就是这样-你剩下的数据帧包含data
的平均值,只有在你有完整的value=1
小时的时候。
如果你想增加这一列,这样你就不必从08:00:00-09:00:00开始按小时分组,也许你想从08:00:10-09:00:10开始,那么解决方案很简单-增加分组列,但在此过程中不改变任何其他内容。
为了做到这一点,你可以使用datetime.timedelta
来向前或向后移动东西,这样df.Timestamp.hour
仍然可以利用来保持事情简单。
从数据推断分组
最后一个想法——如果你想推断在滚动的基础上你有完整的数据,那么你可以用滚动和来做——这更容易。你:
- 计算
value
的滚动和和data
的平均值 - 只选择
value
等于360的地方
df_roll = df.rolling(360).aggregate({'value': 'sum', 'data': 'mean'})
df_roll = df_roll[df_roll['value'] == 360]
是的,有。你需要resample
和offset
。
制作一些测试数据
请确保下次提供有意义的测试数据。
import pandas as pd
import numpy as np
# One day in 10 second intervals
index = pd.date_range(start='1/1/2018', end='1/2/2018', freq='10S')
df = pd.DataFrame({"data": np.random.random(len(index))}, index=index)
# This will set the first part of the data to 1, the rest to 0
df["value"] = (df.index < "2018-01-01 10:00:10").astype(int)
结果如下:
>>> df
data value
2018-01-01 00:00:00 0.377082 1
2018-01-01 00:00:10 0.574471 1
2018-01-01 00:00:20 0.284629 1
2018-01-01 00:00:30 0.678923 1
2018-01-01 00:00:40 0.094724 1
... ... ...
2018-01-01 23:59:20 0.839973 0
2018-01-01 23:59:30 0.890321 0
2018-01-01 23:59:40 0.426595 0
2018-01-01 23:59:50 0.089174 0
2018-01-02 00:00:00 0.351624 0
用偏移量
获取每小时的平均值下面是一个小函数,检查片中所有value
行是否都等于1,如果等于,则返回mean
,否则(隐式)返回None
。
def get_conditioned_average(frame):
if frame.value.eq(1).all():
return frame.data.mean()
现在只需将此应用于每小时切片,例如,在整小时后10秒开始。
df2 = df.resample('H', offset='10S').apply(get_conditioned_average)
这是最后的结果:
>>> df2
2017-12-31 23:00:10 0.377082
2018-01-01 00:00:10 0.522144
2018-01-01 01:00:10 0.506536
2018-01-01 02:00:10 0.505334
2018-01-01 03:00:10 0.504431
... ... ...
2018-01-01 19:00:10 NaN
2018-01-01 20:00:10 NaN
2018-01-01 21:00:10 NaN
2018-01-01 22:00:10 NaN
2018-01-01 23:00:10 NaN
Freq: H, dtype: float64