Pandas技术实现:用月度均值填充DataFrame中的NaN值
问题描述
原始数据集为1996年至2021年的传感器小时读数,结构如下:
date AA1 AB2 AC3 AD4 0 1996-01-01 00:00:00 NaN NaN NaN NaN 1 1996-01-01 01:00:00 NaN 19.2 NaN NaN 2 1996-01-01 02:00:00 NaN 16.4 NaN NaN 3 1996-01-01 03:00:00 NaN 23.5 NaN NaN 4 1996-01-01 04:00:00 20.4 NaN NaN NaN ... ... ... ... ... ... 219164 2020-12-31 20:00:00 13.4 NaN 23.0 26.6 219165 2020-12-31 21:00:00 14.2 NaN 19.6 28.3 219166 2020-12-31 22:00:00 13.5 NaN 17.9 20.5 219167 2020-12-31 23:00:00 NaN NaN 16.7 20.7 219168 2021-01-01 00:00:00 NaN NaN NaN NaN
目标是用各列的月度均值填充对应位置的NaN值,保留原数据集的索引、日期和列结构,全NaN的月份暂不处理。
已尝试通过以下代码分组计算月度均值,但无法将均值回填到原DataFrame:
df['year'] = df['date'].dt.year df['month'] = df['date'].dt.month tem = df.groupby(['year', 'month']).mean().reset_index()
分组后的结果结构如下(行数远少于原数据集):
year month AA1 AB2 AC3 AD4 0 1996 1 20.1 18.3 NaN NaN 1 1996 2 NaN NaN NaN NaN 2 1996 3 NaN NaN NaN NaN 3 1996 4 NaN NaN NaN NaN 4 1996 5 NaN NaN NaN NaN ... ... ... ... ... ... ... 296 2020 9 NaN NaN 15.7 20.2 297 2020 10 NaN NaN 15.3 19.7 298 2020 11 NaN NaN 26.7 25.9 299 2020 12 NaN NaN 24.6 25.3 300 2021 1 NaN NaN NaN NaN
解决方案
不需要单独生成year和month列,直接利用transform方法即可将分组均值匹配回原数据集的每一行,步骤如下:
方法1:直接按年月周期分组(推荐)
# 按日期的年月周期分组,计算各列月度均值并广播到对应组的所有行 monthly_means = df.groupby(df['date'].dt.to_period('M')).transform('mean') # 用月度均值填充原DataFrame的NaN df_filled = df.fillna(monthly_means)
方法2:基于已有的year和month列分组
如果你已经生成了year和month列,可直接用这两列分组:
# 按年、月分组,生成与原数据集行数一致的月度均值DataFrame monthly_means = df.groupby(['year', 'month']).transform('mean') # 填充NaN df_filled = df.fillna(monthly_means)
说明
transform('mean')会将每个分组的均值广播到该组的所有行,生成与原数据集行数、索引完全一致的DataFrame,这样fillna就能精准匹配到对应行的NaN值进行填充。- 对于全NaN的月份,分组计算的均值也是NaN,因此这些位置的NaN会被保留,符合需求。
- 最终的
df_filled会保留原数据集的所有结构(索引、日期列、传感器列),仅替换可填充的NaN值。
内容的提问来源于stack exchange,提问作者Kevin Thomas
相关产品推荐
相关产品推荐

