Pandas:pd.assign能否替代pd.apply?如何实现预期列值修改?
问题描述
我有一个宽DataFrame,其中包含units列,希望按如下方式更新满足条件的行:
df_historic.loc[df_historic.variable == 'Emissions Intensities'].assign(units = lambda x: f"t CO2/({x.units})")
但该写法无法生效,因为此处x.units被识别为完整的Series(带有索引标记),而非我需要的逐行迭代值。
使用pd.apply可以实现预期效果:
df_historic.loc[df_historic.variable == 'Emissions Intensities', 'units'] = df_historic.loc[df_historic.variable == 'Emissions Intensities'].apply(lambda x: f"t CO2/({x.units})", axis=1)
但该代码过于冗长!请问需要添加什么语法糖才能让pd.assign实现预期效果?
解决方案
方法1:结合assign与矢量化字符串操作
利用Pandas原生的矢量化字符串拼接能力,不需要逐行迭代。通过where方法对满足条件的行单独处理:
# 定义筛选掩码 mask = df_historic.variable == 'Emissions Intensities' # 使用assign更新列,非目标行保留原数值,目标行执行字符串拼接 df_historic = df_historic.assign( units=lambda x: x['units'].where( ~mask, "t CO2/(" + x['units'] + ")" ) )
方法2:更简洁的直接赋值写法
如果不需要链式调用assign,直接对筛选后的行做矢量化字符串拼接更高效:
mask = df_historic.variable == 'Emissions Intensities' df_historic.loc[mask, 'units'] = "t CO2/(" + df_historic.loc[mask, 'units'] + ")"
原写法失效原因
原代码中的f"t CO2/({x.units})"会将整个Series对象传入格式化字符串,导致输出包含Series的索引和结构信息,而非逐行的元素值。Pandas的矢量化操作会自动遍历每个元素完成拼接,无需显式使用apply或逐行lambda。
内容的提问来源于stack exchange,提问作者Michael Tiemann
相关产品推荐
相关产品推荐

