0

0

Pandas管道操作中合并后创建新列:eval与assign的正确姿势

霞舞

霞舞

发布时间:2025-11-25 12:26:02

|

819人浏览过

|

来源于php中文网

原创

pandas管道操作中合并后创建新列:eval与assign的正确姿势

在Pandas数据处理管道中,当合并两个DataFrame后需要基于现有列计算生成新列时,直接使用assign()或transform()可能因类型错误而失败。本文将介绍两种高效且正确的解决方案:利用DataFrame.eval()进行简洁的字符串表达式求值,以及通过assign()结合lambda函数实现灵活的列计算,从而优化数据处理流程并提升代码可读性

在Pandas的数据分析工作中,我们经常需要将多个DataFrame合并,并在合并后立即根据现有列执行计算以生成新的数据列。将这些操作封装在链式管道(pipeline)中,可以显著提高代码的可读性和维护性。然而,在尝试通过assign()或transform()方法在管道中创建新列时,初学者可能会遇到TypeError,尤其是在直接引用列名进行数学运算时。

理解问题:管道中新列计算的挑战

假设我们有两个DataFrame,solar_part和solar_aod,它们通过pool列进行合并:

import pandas as pd

solar_part = pd.DataFrame(
     {'pool': 1,
     'orig': 635.1}, index = [0]
     )

solar_aod = pd.DataFrame(
     {'pool': [1,1,1,1],
      'MoP': [1,2,3,4],
     'prin': [113.1, 115.3, 456.6, 234.1]}
     )

我们的目标是在合并后,基于prin和orig两列计算一个新的列remn(例如,remn = prin / orig)。一个常见的尝试是直接在assign()中使用列名字符串:

# 错误示范
# solar_p = (
#     solar_aod
#     .merge(solar_part, on = ['pool'], how = 'left')
#     .assign(remn = ['prin'] / ['orig']) # 或 assign(remn = 'prin' / 'orig')
#     )

这种写法会导致TypeError: unsupported operand type(s) for /: 'list' and 'list'(或'str' and 'str'),因为assign()在默认情况下会将'prin'或['prin']解释为字符串字面量或字符串列表,而不是DataFrame中的列引用。因此,不能直接对这些字面量执行数学运算。

为了在管道中高效且正确地完成这类操作,Pandas提供了几种解决方案。

解决方案一:利用 DataFrame.eval() 简化表达式计算

DataFrame.eval()方法允许我们以字符串形式定义表达式,并在DataFrame的上下文中执行它们。这使得它非常适合在管道中创建新列,特别是当表达式涉及多个现有列的简单数学运算时。

使用eval()的优点在于其简洁性和效率,Pandas会在底层优化这些字符串表达式的计算。

solar_p_eval = (
    solar_aod
    .merge(solar_part, on='pool', how='left')
    .eval('remn = prin / orig')
)

print(solar_p_eval)

输出结果:

   pool  MoP   prin   orig      remn
0     1    1  113.1  635.1  0.178082
1     1    2  115.3  635.1  0.181546
2     1    3  456.6  635.1  0.718942
3     1    4  234.1  635.1  0.368603

eval()方法直接将字符串'remn = prin / orig'解析为在当前DataFrame上执行的操作,其中prin和orig被正确识别为列名。

AdsGo AI
AdsGo AI

全自动 AI 广告专家,助您在数分钟内完成广告搭建、优化及扩量

下载

解决方案二:assign() 结合 lambda 函数的灵活性

虽然eval()在处理简单表达式时非常强大,但assign()方法通过结合lambda函数提供了更大的灵活性,尤其是在需要执行更复杂的逻辑或调用自定义函数时。

当assign()接收一个可调用对象(如lambda函数)作为参数时,它会将当前的DataFrame作为输入传递给这个函数。这样,我们就可以在lambda函数内部安全地引用DataFrame的列。

solar_p_assign_lambda = (
    solar_aod
    .merge(solar_part, on='pool', how='left')
    .assign(remn = lambda df: df['prin'] / df['orig'])
)

print(solar_p_assign_lambda)

输出结果:

   pool  MoP   prin   orig      remn
0     1    1  113.1  635.1  0.178082
1     1    2  115.3  635.1  0.181546
2     1    3  456.6  635.1  0.718942
3     1    4  234.1  635.1  0.368603

在这个例子中,lambda df: df['prin'] / df['orig']接收合并后的DataFrame df,然后通过df['prin']和df['orig']正确访问到相应的列Series,并执行逐元素的除法运算。

注意事项与最佳实践

  1. 选择方法:

    • eval(): 适用于涉及简单数学运算符(+, -, *, /, **等)和比较运算符的列间计算。它的语法更简洁,对于大型数据集可能具有性能优势,因为它通常会利用NumPy进行优化。
    • assign() + lambda: 提供更高的灵活性。当你需要执行更复杂的逻辑,例如条件判断、调用自定义函数、或者链式应用多个Pandas方法来生成新列时,lambda函数是更好的选择。
  2. 可读性: 管道操作(pipe、链式调用)本身就旨在提高代码的可读性。选择最能清晰表达意图的方法至关重要。对于简单的列计算,eval()通常更直观。

  3. 性能: 对于大规模数据,eval()在某些情况下可能会比assign与lambda的组合更快,因为它能够利用numexpr库进行优化。然而,对于大多数常见场景,两者的性能差异可能不明显。

  4. 避免直接字符串运算: 记住,在assign()中直接使用字符串字面量进行运算是无效的。必须通过可调用对象(如lambda)来访问DataFrame的列。

总结

在Pandas的数据处理管道中,合并数据后创建新列是一个常见需求。为了避免TypeError并保持代码的简洁性,我们推荐使用DataFrame.eval()进行简单的列间数学运算,或者使用assign()结合lambda函数来处理更复杂的计算逻辑。这两种方法都能优雅地融入Pandas的链式操作,显著提升数据处理代码的效率和可维护性。理解它们的适用场景和工作原理,将帮助你更高效地利用Pandas进行数据分析。

相关专题

更多
Python 时间序列分析与预测
Python 时间序列分析与预测

本专题专注讲解 Python 在时间序列数据处理与预测建模中的实战技巧,涵盖时间索引处理、周期性与趋势分解、平稳性检测、ARIMA/SARIMA 模型构建、预测误差评估,以及基于实际业务场景的时间序列项目实操,帮助学习者掌握从数据预处理到模型预测的完整时序分析能力。

51

2025.12.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1465

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

228

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

85

2025.10.17

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

257

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

208

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1465

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

619

2023.11.24

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

9

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Git 教程
Git 教程

共21课时 | 2.7万人学习

Django 教程
Django 教程

共28课时 | 3.1万人学习

Kotlin 教程
Kotlin 教程

共23课时 | 2.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号