需要在行级别对数据帧进行评估

2024-04-25 01:54:10 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个场景,在这个场景中,我的pandas数据帧有一个存储为字符串的条件,我需要执行该条件并将结果存储为不同的列。下面的例子将帮助您更好地理解

现有数据帧:

ID   Val    Cond
1     5      >10
1     15     >10

预期数据帧:

ID   Val    Cond    Result
1     5      >10     False
1     15     >10     True

如您所见,我需要连接Val和Cond,并在行级别执行eval


Tags: 数据字符串idfalsetruepandaseval场景
2条回答

您也可以这样做:

df["Result"] = [eval(x + y) for x, y in zip(df["Val"].astype(str), df["Cond"]]

通过连接字符串df[“Val”]和df[“Cond”],然后对其应用eval,生成“Result”列

如果您的条件是由基本操作(<;、<;=、=、!=、>;、>;=)形成的,那么我们可以使用getattr更有效地实现这一点。我们使用.str.extract来解析条件,并将比较和值分开。使用我们的字典,我们将比较映射到系列属性,然后我们可以在一个简单的groupby中分别调用每个唯一的比较

import pandas as pd

print(df)
   ID  Val  Cond
0   1    5   >10
1   1   15   >10
2   1   20  ==20
3   1   25  <=25
4   1   26  <=25

# All operations we might have. 
d = {'>': 'gt', '<': 'lt', '>=': 'ge', '<=': 'le', '==': 'eq', '!=': 'ne'}

# Create a DataFrame with the LHS value, comparator, RHS value
tmp = pd.concat([df['Val'], 
                 df['Cond'].str.extract('(.*?)(\d+)').rename(columns={0: 'cond', 1: 'comp'})], 
                axis=1)
tmp[['Val', 'comp']] = tmp[['Val', 'comp']].apply(pd.to_numeric)
#   Val cond  comp
#0    5    >    10
#1   15    >    10
#2   20   ==    20
#3   25   <=    25
#4   26   <=    25
#5   10   !=    10

# Aligns on row Index
df['Result'] = pd.concat([getattr(gp['Val'], d[idx])(gp['comp']) 
                          for idx, gp in tmp.groupby('cond')])
#   ID  Val  Cond  Result
#0   1    5   >10   False
#1   1   15   >10    True
#2   1   20  ==20    True
#3   1   25  <=25    True
#4   1   26  <=25   False
#5   1   10  !=10   False

简单但低效且危险的方法是在每一行上eval,创建一个条件字符串eval是危险的,因为它可以计算任何代码,所以只有在您真正信任并了解数据的情况下才使用

df['Result'] = df.apply(lambda x: eval(str(x.Val) + x.Cond), axis=1)
#    ID  Val  Cond  Result
#0   1    5   >10   False
#1   1   15   >10    True
#2   1   20  ==20    True
#3   1   25  <=25    True
#4   1   26  <=25   False
#5   1   10  !=10   False

相关问题 更多 >