我有一个小的(ish)python脚本,使用matplotlib和pandas(将CSV读入pandas数据框)来绘制csv分隔的数据。基本上是重新设计了gnuplot的较差版本。
由进程makes_csv
绘制stdout发射的csv数据的典型调用如下:
makes_csv | plot.py --cols 1 3
这意味着“将输入的第1列和第3列作为单独的序列,相对于第0列(标题来自输入数据)”。
现在,我想添加绘制派生的列的功能,该列是引用一个或多个现有列的公式。例如,我可能会写类似的内容:
... | plot.py --formula-cols 'foo=col(1)/col(3)*100'
这将意味着:绘制将第1列中的值除以第3列中的对应值乘以100的(每个元素)结果,并将此系列称为“ foo”。
我不需要上面的确切语法-我想要的主要内容是基本的数学函数和引用列的功能。我不想重新发明Wheel解析公式或使用第三方公式解析:我想使用python原生方式。
我不在乎安全性-如果恶意公式可以删除我的硬盘驱动器或破坏我的信誉,我可以接受:我自己输入这些公式,而不必关心沙箱。
答案 0 :(得分:1)
答案可能涉及内置函数eval()
和/或exec()
。但是,如果不知道'plot.py'的工作原理,很难做出更具体的回答。例如,您的示例表达式将需要能够创建新列“ Foo”。它还需要访问当前列,但是我们不知道这些列如何存储在plot.py中?
这是一种实现方式的要点:
# csv data stored in a list of rows
data = [
[1, 2, 3],
[2, 4, 6],
[3, 6, 9]
]
# formula from the command line argument
formula = 'row[0]/row[2]*100'
source = f'''
for row in data:
row.append({formula})
'''
exec(src)
source
是用于循环的代码,该循环将公式的值附加到数据表中的每一行。 exec()
执行代码。如果没有其他参数,exec()
将使用当前范围。因此,data
引用全局列表data
,公式中的row[0]
引用循环变量row
的第一个元素。
修改示例代码以使用plot.py中的数据结构作为练习留给读者。
编辑:在github上查看代码后添加了此内容。
因为plot.py使用熊猫处理csv文件,所以这很容易。只需在命令行上输入熊猫公式,然后在脚本中使用exec()
即可执行。例如:
# example DataFrame
df = pd.DataFrame({
'A':[1, 2, 3, 4],
'B':[5, 6, 7, 8],
'C':[9, 0, 1, 2]
})
# formula from the command line
formula = "df['D'] = (df['A'] + df['C']) / df['B']"
# apply the formula
exec(formula)
# result
A B C e
0 1 5 9 2.000000
1 2 6 0 0.333333
2 3 7 1 0.571429
3 4 8 2 0.750000
注意:“公式”可以是任何有效的python / pandas代码。