pandas填充timestamp64类型列缺失值报TypeError问题咨询
报错原因
math.isnan() 仅支持判断实数类型的空值,你的year_of_release列是timestamp64类型,非空行存储的是pandas的Timestamp对象,传入math.isnan()时就会触发TypeError: must be real number, not Timestamp错误。
另外你写的get_year函数存在笔误:循环内定义的变量是小写i,返回时写成了大写I,运行时会触发NameError,需要一并修正。
最优解决方法
不需要写逐行apply的判断函数,pandas原生的fillna()方法专门用于缺失值填充,是向量化实现,性能远高于逐行apply,也不会出现类型判断错误。
首先修正年份提取函数的笔误:
import re import pandas as pd def get_year(row): regex = r"\d{4}" match = re.findall(regex, row) for i in match: year = int(i) if 1970 < year < 2017: return year gaming['years_from_titles'] = gaming['name'].apply(lambda x: get_year(str(x)))
再做类型统一后直接填充缺失值:
# 将提取到的年份转换为和原列一致的时间戳类型,避免列类型混乱 gaming['years_from_titles'] = pd.to_datetime(gaming['years_from_titles'], format='%Y') # 用提取到的年份填充原列的缺失值 gaming['year_of_release'] = gaming['year_of_release'].fillna(gaming['years_from_titles'])
若要保留逐行apply写法的修正方案
如果坚持用自定义逐行函数的逻辑,需要把空值判断方法替换为pandas自带的pd.isna(),该方法兼容所有pandas支持的数据类型,不会触发类型错误:
def year_row(row): if pd.isna(row['year_of_release']): return row['years_from_titles'] else: return row['year_of_release'] gaming['year_of_release'] = gaming.apply(year_row, axis=1) # 最后统一转换列类型为时间戳 gaming['year_of_release'] = pd.to_datetime(gaming['year_of_release'])
注意事项
- 判断pandas数据的空值时,优先使用
pd.isna()/pd.notna(),不要用math.isnan()或np.isnan(),后两者仅支持数值类型,传入时间、字符串等类型值时会触发类型错误。 - 所有能用pandas原生向量化方法实现的操作,都不要用
apply(axis=1)逐行处理,前者性能是后者的几十到上百倍,数据量越大差距越明显。
内容的提问来源于stack exchange,提问作者Maor Ohayon
相关产品推荐
相关产品推荐

