如何用Pandas方法链实现单列/多列的修改操作?
如何用Pandas方法链优雅地修改指定列?
给定如下DataFrame:
import pandas as pd import numpy as np df = pd.DataFrame({ 'num_1': [np.nan, 2., 2., 3., 1.], 'num_2': [9., 6., np.nan, 5., 7.], 'str_1': ['a', 'b', 'c', 'a', 'd'], 'str_2': ['C', 'B', 'B', 'D', 'A'], })
需要执行的操作:
numeric_cols = ['num_1', 'num_2'] str_cols = ['str_1', 'str_2'] df[numeric_cols] = df[numeric_cols].fillna(0.).astype('int') df[numeric_cols] = df[numeric_cols] * 2 df['str_2'] = df['str_2'].str.lower() df[str_cols] = df[str_cols].replace({'a': 'z', 'b':'y', 'c': 'x'})
尝试用pipe、assign实现链式操作时遇到三个问题:
pipe仅隐藏数值列处理逻辑,内部实现无优化replace需手动逐个指定列,列多时不便- 无法将
str.lower作为可调用对象传入assign处理单列
规范的方法链实现
可以结合assign的字典式赋值、lambda包装和批量列推导,完美解决上述问题,同时保持代码简洁可读:
import pandas as pd import numpy as np numeric_cols = ['num_1', 'num_2'] str_cols = ['str_1', 'str_2'] replace_map = {'a': 'z', 'b':'y', 'c': 'x'} df_chain = ( df # 批量处理数值列:填充NaN→转int→乘2 .assign(**{col: lambda x, c=col: x[c].fillna(0.).astype('int') * 2 for col in numeric_cols}) # 单独处理str_2转小写:用lambda包装字符串方法 .assign(str_2=lambda x: x['str_2'].str.lower()) # 批量处理字符串列的replace .assign(**{col: lambda x, c=col: x[c].replace(replace_map) for col in str_cols}) )
问题解决说明:
优化数值列处理:
用字典推导式直接在assign中生成所有数值列的处理逻辑,避免重复索引DataFrame,逻辑清晰且无需额外pipe封装,效率更高。批量处理replace:
通过遍历str_cols生成批量赋值逻辑,列再多只需维护列名列表即可,无需逐个写列名。注意用c=col固定循环变量,避免lambda延迟绑定导致的错误。在assign中使用str.lower:
用lambda x: x['str_2'].str.lower()包装字符串方法,直接传入assign完成单列修改,解决了无法直接传入str.lower的问题。
更简洁的替代方案
如果想进一步简化代码,可以利用assign直接接收DataFrame键值对的特性,省去lambda推导:
df_chain = ( df # 数值列批量处理 .assign(**df[numeric_cols].fillna(0.).astype('int').mul(2)) # str_2转小写 .assign(str_2=lambda x: x['str_2'].str.lower()) # 字符串列批量replace .assign(**df[str_cols].replace(replace_map)) )
这种方式利用Pandas的列子集操作生成临时结果,直接传入assign完成赋值,代码更紧凑直观。
内容的提问来源于stack exchange,提问作者Jonah
相关产品推荐
相关产品推荐

