Pandas 使用另一列作为条件计算平均值

Pandas calculate mean using another column as condition

我有一个这样的数据框:

         observation_time  temperature
2021-11-24 10:00:00+00:00  7.22
2021-11-24 10:30:00+00:00  7.33
2021-11-24 11:00:00+00:00  7.44
2021-11-24 11:30:00+00:00  7.50
2021-11-24 12:00:00+00:00  7.50
2021-11-24 12:30:00+00:00  7.50
2021-11-24 13:00:00+00:00  7.44
2021-11-24 13:30:00+00:00  7.61
2021-11-24 14:00:00+00:00  7.67
2021-11-24 14:30:00+00:00  7.78
...
2021-11-27 08:30:00+00:00  7.22
2021-11-27 09:00:00+00:00  7.33
2021-11-27 09:30:00+00:00  7.44
2021-11-27 10:00:00+00:00  7.50

时间步长为30分钟,理论上应该涵盖3天,但很可能会遗漏一些数据。 (数据框只是一个例子,我没有放所有的值。)

我想计算每个时间值在 3 天内的平均值,例如在 10:30 我需要这些天的温度值:2021-11-24、2021-11-25、2021-11-26、 但仅当所有 3 个值都存在时,否则为 NaN。

我开始使用 groupbyGrouper:

df[["observation_time", "temperature"]].groupby(pd.Grouper(key="observation_time", freq="30min", offset="0m", label="right")).mean()

或:

df[["observation_time", "temperature"]].groupby(pd.Grouper(key="observation_time", freq="24H", offset="0m", label="right")).mean()

但是,当然,它们不是正确的解决方案。

然后我试图计算每个时间值的行数:

num = df[["observation_time", "temperature"]].groupby(df["observation_time"].dt.time)["temperature"].count().reset_index()

num.rename(columns={"observation_time": "observation_hour", "temperature": "count_temperature"}, inplace=True)

并使用公共列 observation_hour:

将此数据框合并到原始数据框
df["observation_hour"] = df["observation_time"].dt.time
df = pd.merge(df, num, how="left")

因此要在同一数据帧上显示时间、温度以及同一小时重复的次数。

我可以使用 groupby 对时间进行分组,但我不知道如何在 count_temperature 上使用条件。

我应该添加到这个:

df.groupby("observation_hour")["temperature"].mean()

某处有类似if df["count_temperature"] == 3的东西,我不知道在哪里。

最终结果应该是这样的(只是一个例子):

observation_hour  mean_temperature
00:00:00+00:00  7.22
00:30:00+00:00  7.44
01:00+00:00  NaN
01:30:00+00:00  7.44
...
22:00:00+00:00  7.44
22:30:00+00:00  NaN
23:00:00+00:00  7.44
23:30:00+00:00  NaN

NaN 值,以防因为我们没有 3 个温度值而无法计算平均值。

有什么想法吗?

您可以从日期时间列中提取时间并仅按时间分组。如果那个 time slow 的观测值少于 3 个,则其平均值为 NaN:

t = pd.date_range("2022-01-01", "2022-01-02", freq="30T").time

grp = df.groupby(df["observation_time"].dt.time)
result = (
    grp["temperature"].mean()     # Calculate the mean temperature for each 30-min period
    .mask(grp.size() < 3, np.nan) # If the period has less than 3 observations, make it nan
    .reindex(t)                   # Make sure we have all periods of a day
    .reset_index()
)