Pandas 基于时间的平均值
Pandas timebased mean
我已经将不同的数据从 homeassistant 导入到 influx db,现在我将它放在 pandas 数据框中,我想获取 mean() 但它应该基于索引中的时间。
我选了一个小的 df 来测试,它看起来像这样:
value
time
2021-03-09 07:25:41.989791+00:00 0.0
2021-03-09 07:26:45.165453+00:00 0.0
2021-03-09 16:56:04.806150+00:00 1.0
2021-03-09 18:10:57.762609+00:00 0.0
2021-03-09 19:45:55.182860+00:00 1.0
2021-03-09 19:49:27.519186+00:00 0.0
所以这只是我家里的一盏灯。我想随着时间的推移平均。所以我可以看到有多少百分比的时间它是打开的。当它说 1 它应该是 1 直到下一个数据点。在此 df 中,平均值应该非常低,因为大多数时候灯是关闭的。它仅在 16:56:04 到 18:10:57 和 19:45:55 到 19:49:27 之间打开。所以它打开大约:1 小时 19 分钟,总记录时间为 12 小时 23 分钟。因此,灯亮的时间约为记录时间的 10%。
还有两个问题:
我的传感器的值不同于 1 和 0(例如温度)
2.the天会变
我真的不知道如何开始,有人知道吗?
您可以计算每个值的持续时间(time_next
- time
,然后转换为秒),然后对每一天取加权平均值:
# calculate durations
df['date'] = df['time'].dt.date
df['time_next'] = df['time'].shift(-1).ffill()
df['duration_s'] = (df['time_next'] - df['time']).dt.seconds
# calculate weighted average by date
df.groupby('date').apply(
lambda z: np.average(z['value'], weights=z['duration_s']))
输出:
date
2021-03-09 0.105416
dtype: float64
P.S。值可以是任意数字,当然不能只是二进制
更新:
为了正确处理多日系列,我们可以更改数据框,在每天结束时(或第二天开始时)使用当天看到的最后一个值添加记录。
例如,在原始 post 的示例数据中,2021-03-10 00:00:00
处的值为 0
。这样,当天最后一条记录的持续时间将显示到当天结束前剩余的秒数,从而使我们的加权平均值计算正确。
这是在代码中如何完成的(这里我假设 time
是原始数据帧的索引):
# add day-end values
z = df.append(
df.resample('1d', label='right').last().ffill()
).sort_index()
# calculate durations
z['duration_s'] = -z.index.to_series().diff(-1).dt.total_seconds()
# calculate weighted average by date
z.groupby(z.index.date).apply(
lambda z: np.average(z['value'], weights=z['duration_s'])).dropna()
我已经将不同的数据从 homeassistant 导入到 influx db,现在我将它放在 pandas 数据框中,我想获取 mean() 但它应该基于索引中的时间。
我选了一个小的 df 来测试,它看起来像这样:
value
time
2021-03-09 07:25:41.989791+00:00 0.0
2021-03-09 07:26:45.165453+00:00 0.0
2021-03-09 16:56:04.806150+00:00 1.0
2021-03-09 18:10:57.762609+00:00 0.0
2021-03-09 19:45:55.182860+00:00 1.0
2021-03-09 19:49:27.519186+00:00 0.0
所以这只是我家里的一盏灯。我想随着时间的推移平均。所以我可以看到有多少百分比的时间它是打开的。当它说 1 它应该是 1 直到下一个数据点。在此 df 中,平均值应该非常低,因为大多数时候灯是关闭的。它仅在 16:56:04 到 18:10:57 和 19:45:55 到 19:49:27 之间打开。所以它打开大约:1 小时 19 分钟,总记录时间为 12 小时 23 分钟。因此,灯亮的时间约为记录时间的 10%。
还有两个问题:
我的传感器的值不同于 1 和 0(例如温度)
2.the天会变
我真的不知道如何开始,有人知道吗?
您可以计算每个值的持续时间(time_next
- time
,然后转换为秒),然后对每一天取加权平均值:
# calculate durations
df['date'] = df['time'].dt.date
df['time_next'] = df['time'].shift(-1).ffill()
df['duration_s'] = (df['time_next'] - df['time']).dt.seconds
# calculate weighted average by date
df.groupby('date').apply(
lambda z: np.average(z['value'], weights=z['duration_s']))
输出:
date
2021-03-09 0.105416
dtype: float64
P.S。值可以是任意数字,当然不能只是二进制
更新:
为了正确处理多日系列,我们可以更改数据框,在每天结束时(或第二天开始时)使用当天看到的最后一个值添加记录。
例如,在原始 post 的示例数据中,2021-03-10 00:00:00
处的值为 0
。这样,当天最后一条记录的持续时间将显示到当天结束前剩余的秒数,从而使我们的加权平均值计算正确。
这是在代码中如何完成的(这里我假设 time
是原始数据帧的索引):
# add day-end values
z = df.append(
df.resample('1d', label='right').last().ffill()
).sort_index()
# calculate durations
z['duration_s'] = -z.index.to_series().diff(-1).dt.total_seconds()
# calculate weighted average by date
z.groupby(z.index.date).apply(
lambda z: np.average(z['value'], weights=z['duration_s'])).dropna()