Pandas方法链中如何正确引用上一步生成的DataFrame对象
Pandas方法链引用中间结果的规范写法
你遇到的问题本质是变量解析时机的问题:整个方法链表达式在执行前,你写的df/df2/df3就会被解析为当前环境中已经存在的变量,不会等到方法链执行到对应步骤才动态获取中间结果。第三个示例没有报错只是巧合:你原始df3的xx列数值和query后的中间结果xx列数值刚好适配你写的mask逻辑,但实际引用的还是原始df3的数据,逻辑上是错误的。
Pandas从0.23版本开始,assign、query、loc等所有支持链式调用的方法,都允许传入可调用对象作为参数,可调用对象的入参就是方法链走到当前步骤的中间DataFrame,这是官方推荐的链式操作引用中间结果的规范写法,和R、PySpark的链式逻辑对齐。
修正后的示例代码
1. 引用filter后的中间结果求和
df = pd.DataFrame( { 'xx':[1,2,3,4,5,6], 'xy':[1,2,3,4,5,6], 'z':[1,2,3,4,5,6], } ) df = ( df .filter(like='x') # lambda的入参x就是filter执行完成后的中间DataFrame .assign(n = lambda x: x.sum(axis=1)) ) df.head(6)
2. 引用链内生成的DataFrame
df2 = ( pd.DataFrame( { 'xx':[1,2,3,4,5,6], 'xy':[1,2,3,4,5,6], 'z':[1,2,3,4,5,6], } ) .assign( xx = lambda x: x['xx'].mask(x['xx']>2,0) ) ) df2.head(6)
3. 修正query后的列引用逻辑
df3 = pd.DataFrame( { 'xx':[1,2,3,4,5,6], 'xy':[1,2,3,4,5,6], 'z':[1,2,3,4,5,6], } ) df3 = ( df3 .query('xx > 3') # 用lambda获取query后的中间结果,保证逻辑正确 .assign( xx = lambda x: x['xx'].mask(x['xx']>4,0) ) ) df3.head(6)
如果需要做更复杂的多步中间结果操作,还可以用pipe方法承接中间DataFrame做自定义处理:
df = ( pd.read_csv("your_data.csv") .filter(like="x") .pipe(lambda x: x.assign( sum_val = x.sum(axis=1), avg_val = x.mean(axis=1) )) .query("sum_val > 10") )
内容的提问来源于stack exchange,提问作者Nikhil02
相关产品推荐
相关产品推荐

