Pandas如何在列值为NaN时跨列计算填充并解决KeyError
Pandas列值为NaN时按其他列计算填充及KeyError修复
问题背景
DataFrame的tags列存储字典类型数据,需从中提取lanes(车道数,全量行有值)、width(道路宽度,仅部分行有值)两个字段,要求width为空值时,按车道数 * 2.4的规则计算填充,运行自定义apply函数时触发KeyError: 'width'报错。
复现代码
初始字段提取代码
import pandas as pd import numpy as np data = {'tags': [{'access': 'private', 'highway': 'service', 'is_in': 'Bellville Campus, Cape Peninsula University of Technology, Bellville, Western Cape, South Africa', 'lanes': '2', 'maxheight': '3.3', 'maxspeed': '30', 'name': 'Engineering Way'}]} df = pd.DataFrame(data) df['lanes'] = df['tags'].apply(lambda x: x.get('lanes')) df['width'] = df['tags'].apply(lambda x: x.get('width'))
类型转换与测试代码
# 原代码存在笔误:误将df写为rd df['lanes'] = pd.to_numeric(df['lanes']) df['width'] = pd.to_numeric(df['width']) print(df)
测试输出:
tags lanes width 0 {'access': 'private', 'highway': 'service', 'i... 2 NaN
报错的自定义填充代码
def calc_width(row): if np.isnan(row['width']): """空值时按车道数计算宽度""" return row['lanes'] * 2.4 df['width'] = df.apply(calc_width)
运行后报错栈:
Traceback (most recent call last): Input In [49] in <cell line: 11> df['width'] = df.apply(calc_width) File ~\miniconda3\envs\osm3D_vc-env\lib\site-packages\pandas\core\frame.py:8839 in apply return op.apply().__finalize__(self, method="apply") File ~\miniconda3\envs\osm3D_vc-env\lib\site-packages\pandas\core\apply.py:727 in apply return self.apply_standard() File ~\miniconda3\envs\osm3D_vc-env\lib\site-packages\pandas\core\apply.py:851 in apply_standard results, res_index = self.apply_series_generator() File ~\miniconda3\envs\osm3D_vc-env\lib\site-packages\pandas\core\apply.py:867 in apply_series_generator results[i] = self.f(v) Input In [47] in calc_width if np.isnan(row['width']): File ~\miniconda3\envs\osm3D_vc-env\lib\site-packages\pandas\core\series.py:958 in __getitem__ return self._get_value(key) File ~\miniconda3\envs\osm3D_vc-env\lib\site-packages\pandas\core\series.py:1069 in _get_value loc = self.index.get_loc(label) File ~\miniconda3\envs\osm3D_vc-env\lib\site-packages\pandas\core\indexes\range.py:389 in get_loc raise KeyError(key) KeyError: 'width'
报错原因
df.apply()默认参数axis=0,按列遍历DataFrame,传入自定义函数的参数是整列的Series对象,不是行数据。遍历到非width列时,Series索引中不存在width键,直接触发KeyError。- 自定义函数缺失非空值分支:就算修正遍历方向,原有
width非空的行也会因为没有返回值被填充为None。 - 类型转换代码存在笔误:误将DataFrame变量名
df写为rd,运行时会触发NameError。
修复方案
方案1:向量化填充(推荐,性能远高于apply)
不需要自定义遍历函数,直接用pandas内置方法实现,代码简洁运行效率高:
# 修正笔误完成类型转换 df['lanes'] = pd.to_numeric(df['lanes']) df['width'] = pd.to_numeric(df['width']) # 用lanes列计算值填充width的空值 df['width'] = df['width'].fillna(df['lanes'] * 2.4)
方案2:修正apply参数与函数逻辑
如果需要使用自定义函数处理更复杂的计算逻辑,需指定axis=1让apply按行遍历,同时补全非空值返回逻辑:
def calc_width(row): if pd.isna(row['width']): return row['lanes'] * 2.4 # 非空时直接返回原有宽度值 return row['width'] # 指定axis=1按行传入数据 df['width'] = df.apply(calc_width, axis=1)
内容的提问来源于stack exchange,提问作者arkriger
相关产品推荐
相关产品推荐

