如何用对应月份和小时的均值替换DataFrame中的NaN值
批量替换DataFrame中NaN为对应月份和小时的均值
问题背景
有一个包含小时级datetime记录的DataFrame,数值列(A-J)存在随机缺失值,需要将每个NaN替换为该值所在月份+小时分组下的对应列均值。目前仅能实现单列替换,需批量处理所有列的方案。
模拟数据生成代码
import pandas as pd import numpy as np p = 0.1 columns = ['A','B','C','D','E','F','G','H','I','J'] size = 1000 df = pd.DataFrame(np.random.randint(0,100,size=(size,len(columns))), columns= columns) mask = np.random.choice([True,False] , size= df.shape, p=[p,1-p]) df = df.mask(mask) df.insert(0, 'date' ,pd.date_range('2000-01-01 00:00' , periods= size, freq = 'H'))
解决方案
方法1:用groupby.transform一键批量填充(推荐)
无需提前生成均值DataFrame,直接利用pandas分组转换功能,生成与原DataFrame同维度的分组均值,再批量替换NaN:
# 定义分组键:月份+小时 group_keys = [df['date'].dt.month, df['date'].dt.hour] # 对所有数值列按分组计算均值,并用该均值填充对应分组的NaN df[columns] = df[columns].fillna(df.groupby(group_keys)[columns].transform('mean'))
transform('mean')会为每一行返回其所在分组的列均值,fillna自动匹配位置替换所有NaN,全程无需循环,效率最高。
方法2:基于已生成的mean_df填充
如果已经提前生成了均值DataFrame(如下):
mean_df = df.groupby([df.date.dt.month , df.date.dt.hour]).mean() mean_df.index.set_names(['month' , 'hour'],inplace=True) mean_df.reset_index(inplace=True)
可以通过添加分组键列、合并均值数据后批量填充:
# 给原df添加month和hour列用于匹配 df['month'] = df['date'].dt.month df['hour'] = df['date'].dt.hour # 合并均值数据到原df merged_df = df.merge(mean_df, on=['month', 'hour'], suffixes=['', '_mean']) # 遍历所有数值列,用对应的均值列填充NaN for col in columns: df[col] = df[col].fillna(merged_df[f'{col}_mean']) # 清理临时添加的分组列 df.drop(['month', 'hour'], axis=1, inplace=True)
内容的提问来源于stack exchange,提问作者Endo
相关产品推荐
相关产品推荐

