如何在字典推导式中传入lambda引用Pandas DataFrame以操作新建列?
解决方案
你之前的写法报错是因为直接在列表中传入的lambda函数未被调用,也无法直接获取col.name属性。Pandas的assign方法传入lambda时,lambda接收的参数是当前已完成部分列更新的DataFrame对象,天然支持引用同一assign调用中先定义的新列,无需生成显式的中间DataFrame。
实现方式1:单assign调用合并字典推导式
注意通过默认参数绑定循环变量,避免Python闭包陷阱:
df1 = df.assign( # 批量生成对数列 **{f'l{col}': np.log(df[col]) for col in ['jam_cpi_eop', 'bah_cpi_eop']}, # 批量生成对数差分列,lambda直接引用上一步生成的对数列 **{f'dl{col}': lambda x, c=col: x[f'l{c}'] - x[f'l{c}'].shift(1) for col in ['jam_cpi_eop', 'bah_cpi_eop']} )
实现方式2:链式pipe调用(更易读,推荐)
通过链式调用分层实现逻辑,不需要处理闭包问题,使用习惯更接近R的mutate连续调用:
df1 = ( df # 第一步:计算指定列的对数 .assign(**{f'l{col}': lambda x, c=col: np.log(x[c]) for col in ['jam_cpi_eop', 'bah_cpi_eop']}) # 第二步:基于上一步输出计算对数差分 .assign(**{f'dl{col}': lambda x, c=col: x[f'l{c}'] - x[f'l{c}'].shift(1) for col in ['jam_cpi_eop', 'bah_cpi_eop']}) )
通用封装(可选)
如果需要高频使用类似mutate(across())的能力,可以封装为工具函数简化调用:
def mutate_across(df, cols, transform_func, name_prefix=''): return df.assign(**{f'{name_prefix}{col}': transform_func(df[col]) for col in cols}) # 调用示例 df1 = ( df .pipe(mutate_across, ['jam_cpi_eop', 'bah_cpi_eop'], np.log, name_prefix='l') .pipe(mutate_across, ['jam_cpi_eop', 'bah_cpi_eop'], lambda x: x.diff(), name_prefix='dl') )
内容的提问来源于stack exchange,提问作者Joao Pedro Macalos
相关产品推荐
相关产品推荐

