如何用众数替换NaN值?Pandas实操遇错求助
解决用众数替换NaN的问题
问题分析
- Pandas
mode()未生效:Series.mode()返回的是包含众数的Series(可能有多个值),而fillna()需要传入标量值,直接传递整个Series无法正确替换NaN。 - 自定义函数报错:
day_of_week列混合了字符串(如'0')和float类型的NaN,执行nums.sort()时会尝试比较不同类型,触发TypeError。
解决方案
方法1:修复Pandas原生mode()用法
这是最简洁的方案,无需自定义函数:
# 转换pickup_datetime为datetime类型,无效值转为NaT x_train['pickup_datetime'] = pd.to_datetime(x_train['pickup_datetime'], format='%Y-%m-%d %H:%M:%S %Z', errors='coerce') # 生成星期几列(strftime('%w')返回'0'=周日到'6'=周六的字符串) x_train['day_of_week'] = x_train['pickup_datetime'].dt.strftime('%w') # 获取众数(取第一个,若存在多个众数),确保传递标量给fillna day_mode = x_train['day_of_week'].mode()[0] x_train['day_of_week'] = x_train['day_of_week'].fillna(day_mode)
注意点:
- 用
errors='coerce'替代手动replace('nan', pd.NA):pd.to_datetime会自动将无效的时间字符串转为NaT(时间类型的空值),无需处理字符串'nan'。 - 若列中全为NaN,
mode()会返回空Series,此时mode()[0]会报错,可添加判断:mode_series = x_train['day_of_week'].mode() day_mode = mode_series.iloc[0] if not mode_series.empty else '0' # 用'0'作为默认值
方法2:修复自定义众数函数
如果坚持使用自定义函数,需先过滤NaN值,避免混合类型排序:
def findmode(series): # 过滤掉所有NaN/NaT值 valid_vals = [val for val in series if pd.notna(val)] # 处理全空的情况 if not valid_vals: return '0' # 可自定义默认值 # 统计每个值的出现次数 count_dict = {} for val in valid_vals: count_dict[val] = count_dict.get(val, 0) + 1 # 按出现次数降序、值升序排序,取第一个众数 sorted_items = sorted(count_dict.items(), key=lambda x: (-x[1], x[0])) return sorted_items[0][0] # 转换datetime列 x_train['pickup_datetime'] = pd.to_datetime(x_train['pickup_datetime'], format='%Y-%m-%d %H:%M:%S %Z', errors='coerce') # 生成并填充星期几列 x_train['day_of_week'] = x_train['pickup_datetime'].dt.strftime('%w') x_train['day_of_week'] = x_train['day_of_week'].fillna(findmode(x_train['day_of_week']))
关键错误解释
- 原自定义函数的
nums.sort()报错:因为dt.strftime('%w')对NaT返回的是float类型的NaN,列中同时存在字符串和float,排序时无法跨类型比较,必须先过滤NaN。 - 原生
mode()无效:Series.mode()返回的是Series对象,而fillna()需要单个值,因此必须通过[0]或iloc[0]提取标量众数。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

