为何Pandas执行apply时将整数列转为浮点数?如何解决?
为什么Pandas中
apply(axis=1)会把整数列转为浮点数?怎么阻止? 原因分析
问题核心在于Pandas的原生整数类型(如int64)不支持存储NaN值,而你的DataFrame中Age列存在NaN。当调用df.apply(func=translate_age, axis=1)时:
- 每一行会被打包成一个
Series对象,这个Series同时包含IntegerColumn(int64类型)和Age(float64类型,因为NaN属于浮点数范畴)。 - 由于Pandas的Series只能有单一数据类型,为了兼容
Age列的NaN,整个行Series会被统一提升为浮点数类型。 - 当所有行的处理结果重新组合成新DataFrame时,
IntegerColumn自然就从int64变成了float64。
解决方法
方法1:用矢量化操作替代apply(axis=1)(推荐,性能更优)
apply(axis=1)是逐行循环,效率低且易引发类型问题,用矢量化函数可以完全规避这个问题:
import pandas as pd import numpy as np df = pd.DataFrame( [["Fred", 1, 44], ["Wilma", 0, 39], ["Barney", 1, None]], columns=["Name", "IntegerColumn", "Age" ]) df = df.drop('Name', axis=1) # 用np.where实现年龄判断逻辑 df['AgeText'] = np.where( df['Age'].isna(), "Unknown", np.where(df['Age'] > 40, "Over 40", "Under 40") ) print('@ after', df['IntegerColumn'].dtypes) # 输出:int64
也可以用pd.cut实现更简洁的区间判断:
df['AgeText'] = pd.cut( df['Age'], bins=[-np.inf, 40, np.inf], labels=["Under 40", "Over 40"], include_lowest=True ).fillna("Unknown")
方法2:处理后强制转回整数类型
如果IntegerColumn本身没有缺失值,执行完apply后可以直接强制转回int64:
# 先执行你的apply逻辑 df = df.apply(func=translate_age, axis=1) # 转回整数类型 df['IntegerColumn'] = df['IntegerColumn'].astype('int64') print('@ after', df['IntegerColumn'].dtypes) # 输出:int64
如果未来IntegerColumn可能出现NaN,可以使用Pandas的Nullable Integer类型(注意大写I的Int64):
df['IntegerColumn'] = df['IntegerColumn'].astype('Int64')
方法3:修改apply逻辑,仅处理目标列
如果一定要用apply,可以只对Age列单独处理,避免影响整行的类型:
def translate_age(age): if pd.isna(age): return "Unknown" return "Over 40" if age > 40 else "Under 40" df['AgeText'] = df['Age'].apply(translate_age)
内容的提问来源于stack exchange,提问作者antun
相关产品推荐
相关产品推荐

