1、基本用法
pd.eval()
主要用于执行字符串形式的表达式,并返回计算结果。它支持对 DataFrame
和 Series
进行列间的计算,条件筛选等操作。
1)进行算术运算
import pandas as pd import numpy as np # 设置随机种子以确保可重复性 np.random.seed(0) # 创建四个 DataFrame, # 每个 DataFrame 的形状为 5x4, # 值从 0 到 9 随机选择 df1 = pd.DataFrame(np.random.choice(10, (5, 4)), columns=list('ABCD')) df2 = pd.DataFrame(np.random.choice(10, (5, 4)), columns=list('ABCD')) # 输出四个 DataFrame print("df1:") print(df1) print("\ndf2:") print(df2) # 使用 pd.eval() 计算 df1 和 df2 中 'A' 列的和, # 返回 pd.Series 对象 result1 = pd.eval("df1.A + df2.A") print("\nResult of df1.A + df2.A:") print(result1) # 使用 pd.eval() 计算 df1 中所有元素的平方根, # 返回 pd.DataFrame 对象 result2 = pd.eval("abs(df1) ** .5") print("\nResult of abs(df1) ** .5:") print(result2)
2)进行比较
import pandas as pd import numpy as np # 设置随机数种子 np.random.seed(0) # 创建 4 个 DataFrame df1 = pd.DataFrame(np.random.choice(10, (5, 4)), columns=list('ABCD')) df2 = pd.DataFrame(np.random.choice(10, (5, 4)), columns=list('ABCD')) df3 = pd.DataFrame(np.random.choice(10, (5, 4)), columns=list('ABCD')) df4 = pd.DataFrame(np.random.choice(10, (5, 4)), columns=list('ABCD')) # 显示 DataFrame 内容 print("df1:") print(df1) print("\ndf2:") print(df2) print("\ndf3:") print(df3) print("\ndf4:") print(df4) # 比较 df1 和 df2 result_1 = pd.eval("df1 > df2") print("\ndf1 > df2:") print(result_1) # 比较 df1 中的每个元素是否大于 5 result_2 = pd.eval("df1 > 5") print("\ndf1 > 5:") print(result_2) # 使用多个条件进行逻辑运算 # 使用 & 进行按元素布尔比较,避免错误 result_3 = pd.eval("df1 < df2 & df3 < df4") print("\ndf1 < df2 & df3 < df4:") print(result_3) # 检查 df1 中的每个元素是否属于 [1, 2, 3] result_4 = pd.eval("df1 in [1, 2, 3]") print("\ndf1 in [1, 2, 3]:") print(result_4) # 使用链式比较 result_5 = pd.eval("1 < 2 < 3") print("\n1 < 2 < 3:") print(result_5)
3)复杂运算
import pandas as pd import numpy as np # 设置随机种子 np.random.seed(0) # 创建 DataFrame,包含 5 行 4 列,元素为 0 到 9 的随机整数 df1 = pd.DataFrame(np.random.choice(10, (5, 4)), columns=list('ABCD')) # 使用 pd.eval 执行表达式:对 df1.A 列乘以索引大于 1 的布尔条件 result = pd.eval('df1.A * (df1.index > 1)') # 打印结果 print("DataFrame df1:") print(df1) print("\nResult of pd.eval:") print(result)
2、解析器选择:parser=...参数
pd.eval
解析表达式字符串以生成语法树时,支持两种不同的解析器选项:pandas
和python
。两者之间的主要区别通过稍有不同的优先级规则突出显示。
使用默认的解析器pandas
,重载位运算符&
和|
它们实现矢量AND
和OR
与pandas对象的操作都会有相同的运算符优先级的and
和or
。
import pandas as pd import numpy as np # 设置随机种子 np.random.seed(0) # 创建四个 DataFrame df1 = pd.DataFrame(np.random.choice(10, (5, 4)), columns=list('ABCD')) df2 = pd.DataFrame(np.random.choice(10, (5, 4)), columns=list('ABCD')) df3 = pd.DataFrame(np.random.choice(10, (5, 4)), columns=list('ABCD')) df4 = pd.DataFrame(np.random.choice(10, (5, 4)), columns=list('ABCD')) # 显示 DataFrame 内容 print("df1:") print(df1) print("\ndf2:") print(df2) print("\ndf3:") print(df3) print("\ndf4:") print(df4) # 使用 pd.eval 进行条件判断 result1 = pd.eval("(df1 > df2) & (df3 < df4)") print("\nresult1 (df1 > df2) & (df3 < df4):") print(result1) # 使用 pd.eval 进行没有括号的表达式 result2 = pd.eval("df1 > df2 & df3 < df4") print("\nresult2 df1 > df2 & df3 < df4 (不加括号的表达式):") print(result2) # 使用 pd.eval 进行 pandas 解析器 # 这行代码默认是正确的格式,如果想使用 'pandas' 解析器,则需要确保表达式符合 pandas 语法。 # 如果发生解析错误,可以尝试不使用 parser='pandas'。 # result3 = pd.eval("df1 > df2 & df3 < df4", parser='pandas') # print("\nresult3 with 'pandas' parser:") # print(result3) # 使用 'and' 而不是 '&'(这会导致错误,因为 'and' 不能直接用于 pandas DataFrame) try: result4 = pd.eval("df1 > df2 and df3 < df4") except Exception as e: print("\nError when using 'and' instead of '&':") print(e)
括号是必须的,使用parens覆盖按位运算符的更高优先级:
(df1 > df2) & (df3 < df4)
parser='python'
评估字符串时保持与python实际运算符优先级规则的一致:
pd.eval("(df1 > df2) & (df3 < df4)", parser='python')
3、后端选择:engine=...参数
有两个选项numexpr
(默认)和python
。该numexpr选项使用为性能优化的numexpr
后端。
使用'python'
后端,您对表达式的求值类似于将表达式传递给python的eval函数。您可以灵活地执行更多内部表达式,例如字符串操作。
import pandas as pd # 创建一个示例 DataFrame df = pd.DataFrame({'A': ['abc', 'def', 'abacus']}) # 使用 pd.eval() 检查每个元素是否包含子字符串 "ab" result = pd.eval('df.A.str.contains("ab")', engine='python') # 输出结果 print(result)
注意:使用'python'
,除非知道自己在做什么,否则通常不建议将此更改此选项。