Numpy 数组组合的语法

问题描述 投票:0回答:1

对于特定的应用程序,我做了一个 GUI 来操作一些数据(内部:numpy 1D 数组),并绘制它们。

最终用户可以在 UI 中选择绘制各种系列

a
b
c

现在我还需要允许 a

b
c
“自定义组合”。更准确地说,用户(不懂 Python/Numpy,但可以学习一些关键字)应该在 GUI 文本框中输入一个“公式”,然后我的程序应该将其转录为真正的 numpy 代码(可能使用
eval(...)
,这里很少有安全问题,因为最终用户是唯一的用户),并绘制数据。

最终用户输入示例:

a * 3 + 1.234 * c - d

a + b.roll(2)

a + b / b.max() * a.max()

例如,允许的语法是:基本算术(+ * - / 和括号)、浮点数、

a.max()
a.roll(3)
来移位数组。

问题:Numpy 或 Scipy 中是否有函数提供这样一种方法来用基本算术语法解释数组组合?

python numpy eval grammar
1个回答
0
投票

对于代数部分,您可以使用 numexpr 库可以利用它。例如,以下代码片段将起作用:

import numpy as np
import numexpr as ne

a = np.random.rand(10)
b = np.random.rand(10)
c = np.random.rand(10)
d = np.random.rand(10)

ne.evaluate("a * 3 + 1.234 * c - d")

遗憾的是,该库并没有立即涵盖其他两种情况,但这可以通过一些字符串解析轻松实现。包含所有功能的最终版本可能如下所示:

import numpy as np
import numexpr as ne
import re

a = np.random.rand(10)
b = np.random.rand(10)
c = np.random.rand(10)
d = np.random.rand(10)

def expression_eval(
    expression:str, a:np.array, b: np.array, c:np.array, d:np.array
) -> np.array:

    #Snippet to manage max values:
    a_max = a.max()
    b_max = b.max()
    c_max = c.max()
    d_max = d.max()

    for label in ["a", "b", "c", "d"]:
        expression = expression.replace(f"{label}.max()", f"{label}_max")

    #Snippet to manage rolling windows:
    pattern = r'(\w)\.roll\((\d+)\)'

    matches = re.findall(pattern, expression)
    if matches: roll_results = [(match[0], int(match[1])) for match in matches]
    else: roll_results = []

    rolls = {}

    for arr, window in roll_results:
        expression = expression.replace(f"{arr}.roll({window})", f"{arr}_roll_{window}")
        rolls[f"{arr}_roll_{window}"] = np.concatenate([
            vars()[arr][window:],
            np.zeros(window)
        ])

    return ne.evaluate(expression, global_dict=rolls)

#Evaluation:

expression_1 = "a * 3 + 1.234 * c - d"
expression_2 = "a + b / b.max() * a.max()"
expression_3 = "a + b.roll(3) + c.roll(2) + d.roll(4)"

print(f"{expression_1}\n{expression_eval(expression_1, a, b, c, d)}\n")
print(f"{expression_2}\n{expression_eval(expression_2, a, b, c, d)}\n")
print(f"{expression_3}\n{expression_eval(expression_3, a, b, c, d)}\n")

本质上,我们在评估代数表达式之前将变量的每个函数替换为其计算值。请注意,对于滚动窗口,我们可以使用具有更动态方法的字典来适应滚动窗口的多种可能性。

© www.soinside.com 2019 - 2024. All rights reserved.