-1

我正在使用 python 的数据

我有 2 个 csv 文件。

CSV 1

A,B
1,2
3,4
5,6

CSV 2

NAME,EXPR
A_GREATER_THAN_B, A>B
A_GREATER_THAN_10, A>10
B_GREATER_THAN_5, B>5

预期产出

A,B,A_GREATER_THAN_B,A_GREATER_THAN_10,B_GREATER_THAN_5
1,2,0,0,0
3,4,0,0,0
5,6,0,0,1

代码

exprdt = dt.fread("csv_2.csv")
exprdict = dict(exprdt.to_tuples())
dt1[:, dt.update(**exprdict)]
print(dt1)

电流输出

   |     A      B      C   A_G_B          A_G_1     B_G_4   
   | int32  int32  int32   str32          str32     str32   
-- + -----  -----  -----   -------------  --------  --------
 0 |     0      1      1   dt.f.A>dt.f.B  dt.f.A>1  dt.f.B>4
 1 |     1      5      6   dt.f.A>dt.f.B  dt.f.A>1  dt.f.B>4

我正在尝试使用扩展函数使用第二个数据表中的表达式来处理第一个数据表。当我使用 fread 读取 csv 文件时,表达式被处理为字符串而不是表达式。

如何使用第二个数据表 (csv) 使用 NAME 和 EXPR 列更新第一个数据表?

4

1 回答 1

0

可以做你想做的事,但你可以做某事并不意味着这是一个好主意。任何需要的解决方案eval()都可能比它需要的更复杂,并且如果您无法完全控制输入的数据,则会带来巨大的风险。

话虽如此,此脚本显示了一种天真的方法,没有表格中的花哨表达式,以及您建议的方法 - 我强烈建议您不要使用它并找出更好的方法来实现您的需求:

from io import StringIO
import re
import datatable as dt

csv1 = """A,B
1,2
3,4
5,6"""

csv2 = """NAME,EXPR
A_GREATER_THAN_B, A>B
A_GREATER_THAN_10, A>10
B_GREATER_THAN_5, B>5"""


def naive():
    # naive approach
    d = dt.fread(StringIO(csv1))
    d['A_GREATER_THAN_B'] = d[:, dt.f.A > dt.f.B]
    d['A_GREATER_THAN_10'] = d[:, dt.f.A > 10]
    d['B_GREATER_THAN_5'] = d[:, dt.f.B > 5]

    print(d)


def update_with_expressions(d, expressions):
    for n in range(expressions.nrows):
        col = expressions[n, :][0, 'NAME']
        expr = re.sub('([A-Za-z]+)', r'dt.f.\1', expressions[n, :][0, 'EXPR'])
        # here's hoping that expression is trustworthy...
        d[col] = d[:, eval(expr)]


def fancy():
    # fancy, risky approach
    d = dt.fread(StringIO(csv1))
    update_with_expressions(d, dt.fread(StringIO(csv2)))
    print(d)
    

if __name__ == '__main__':
    naive()
    fancy()

结果(表明您从任何一种方法都得到相同的结果):

   |     A      B  A_GREATER_THAN_B  A_GREATER_THAN_10  B_GREATER_THAN_5
   | int32  int32             bool8              bool8             bool8
-- + -----  -----  ----------------  -----------------  ----------------
 0 |     1      2                 0                  0                 0
 1 |     3      4                 0                  0                 0
 2 |     5      6                 0                  0                 1
[3 rows x 5 columns]

   |     A      B  A_GREATER_THAN_B  A_GREATER_THAN_10  B_GREATER_THAN_5
   | int32  int32             bool8              bool8             bool8
-- + -----  -----  ----------------  -----------------  ----------------
 0 |     1      2                 0                  0                 0
 1 |     3      4                 0                  0                 0
 2 |     5      6                 0                  0                 1
[3 rows x 5 columns]

注意:如果有人知道迭代 a 中行的更好方法datatable.Frame,请发表评论,因为我不喜欢这部分:

    for n in range(expressions.nrows):
        col = expressions[n, :][0, 'NAME']

请注意,StringIO仅导入以在代码中包含 .csv 文件,您不需要它们。

于 2022-01-28T01:33:48.930 回答