pd.eval() 是一个强大的 Pandas 函数,用于高效地执行字符串表达式,可以用于对 DataFrame 或 Series 进行快速的操作和计算。它支持类似于 Python 中的表达式计算,但使用 eval() 可以避免频繁的迭代,提高效率,尤其在处理较大的数据集时。

1、基本用法

pd.eval() 主要用于执行字符串形式的表达式,并返回计算结果。它支持对 DataFrameSeries 进行列间的计算,条件筛选等操作。

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解析表达式字符串以生成语法树时,支持两种不同的解析器选项:pandaspython。两者之间的主要区别通过稍有不同的优先级规则突出显示。

使用默认的解析器pandas,重载位运算符&|它们实现矢量ANDOR与pandas对象的操作都会有相同的运算符优先级的andor

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',除非知道自己在做什么,否则通常不建议将此更改此选项。

相关文档Python pandas.DataFrame.eval函数方法的使用

推荐文档