【问题标题】:How to parse and evaluate a math expression with Pandas Dataframe columns?如何使用 Pandas Dataframe 列解析和评估数学表达式?
【发布时间】:2018-04-18 13:04:52
【问题描述】:

我想做的是解析这样一个表达式:

result = A + B + sqrt(B + 4)

其中 A 和 B 是数据框的列。所以我必须像这样解析表达式才能得到结果:

new_col = df.B + 4
result = df.A + df.B + new_col.apply(sqrt)

df 是数据框。

我尝试过使用re.sub,但最好只替换列变量(而不是函数),如下所示:

import re

def repl(match):
    inner_word = match.group(1)
    new_var = "df['{}']".format(inner_word)
    return new_var

eq = 'A + 3 / B'
new_eq = re.sub('([a-zA-Z_]+)', repl, eq)
result = eval(new_eq)

所以,我的问题是:

  • 是否有 python 库可以做到这一点?如果没有,我怎样才能以简单的方式实现这一目标?
  • 创建递归函数可能是解决方案?
  • 如果我使用“反向波兰符号”可以简化解析?
  • 我必须使用ast 模块吗?

【问题讨论】:

  • 你试过result = df["A"] + df["B"] + sqrt(df["B"] + 4) 吗?它应该工作
  • @DimuthTharakaMenikgama 阅读了完整的问题,它不仅是相同的表达方式。
  • 你能展示你的数据框吗?(至少几行)?
  • 如果我按照你说的那样使用sqrt 函数,我会收到此错误TypeError: cannot convert the series to <class 'float'>。所以函数必须和apply一起使用
  • 数据框可以有float64 值、int32 值,甚至numpy.nan 值。

标签: python python-3.x pandas dataframe text-parsing


【解决方案1】:

Pandas DataFrames 确实有一个eval 函数。使用您的示例方程式:

import pandas as pd
# create an example DataFrame to work with
df = pd.DataFrame({"A": [1, 2], "B": [3, 4]})
# define equation
eq = 'A + 3 / B'
# actual computation
df.eval(eq)

# more complicated equation
eq = "A + B + sqrt(B + 4)"
df.eval(eq)

警告

请记住,eval 允许运行任意代码,如果您将用户输入传递给此函数,这会使您容易受到代码注入的攻击。

【讨论】:

  • 非常感谢!它工作正常。我想使用其他函数,但我读过这个:“支持数学函数是 sin, cos, exp, log, expm1, log1p, sqrt, sinh, cosh, tanh, arcsin, arccos, arctan, arccosh, arcsinh, arctanh、abs 和 arctan2"。所以恐怕我只能使用那些功能。是否可以在表达式中添加外部函数?使用内置 python eval() 函数可以使用 local 字典将函数添加为对象,但我无法使其与 df.eval()
  • 我已经写信another question 来管理这个
  • 请注意这一点。 eval() 允许运行任意代码。如果在未清理的字符串上调用 eval ,这可能很危险! eval() 这允许 eval 运行任意代码,如果您将用户输入传递给此函数,这可能会使您容易受到代码注入的影响。
  • 你是对的@Tom。我会将警告添加到答案中。谢谢
【解决方案2】:

按照@uuazed 提供的示例,更快的方法是使用numexpr

import pandas as pd
import numpy as np
import numexpr as ne

df = pd.DataFrame(np.random.randn(int(1e6), 2), columns=['A', 'B'])
eq = "A + B + sqrt(B + 4)"
timeit df.eval(eq)
# 15.9 ms ± 177 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
timeit A=df.A; B=df.B; ne.evaluate(eq)
# 6.24 ms ± 396 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

numexpr 还可能有更多支持的操作

【讨论】:

  • 比较快,但是需要提前知道要使用的变量。如果没有,你必须在评估之前进行一些解析,这需要时间
  • 如果勾选eval documentation,则engine默认为numexpr
  • 是的,好点子!很好奇仅通过评估的长时间差异
猜你喜欢
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 2010-12-05
  • 1970-01-01
  • 2010-11-12
  • 1970-01-01
相关资源
最近更新 更多