给出一个数据框
a b c d
1 5 5 5 5
2 5 5 5 5
3 5 5 5 5
我想基于现有列在DataFrame上添加更多列,但要使用一些lambda无法容纳的逻辑。所需的结果应如下所示:
a a_added c c_added d d_added
1 5 'good' 5 'good' 5 'bad'
2 5 'bad' 5 'good' 5 'bad'
3 5 'good' 5 'good' 5 'bad'
看到this的答案后,我的想法是在每行上使用DataFrame.apply()
,然后在每个值上使用Series.apply()
,但我不知道如何准确地链接调用以及什么恰好返回,以便我从Series的apply函数返回新的列名。之后,我认为我需要将这两个DataFrame与DataFrame.join()
结合在一起。我真的需要使用Series.apply()
,因为我必须使用一些自定义逻辑来计算每个值。
编辑: 我有一个阈值图,其中的键与我的DataFrame中的列名相对应,并且值是警告/关键阈值以及一个操作,该操作说明应如何将当前值与阈值进行比较:
thresholds = {
'a': {'warning': 90, 'critical': 98, operation: 'lt'},
'b': {'warning': 10, 'critical': 15, operation: 'gt'},
'c': {'warning': 5, 'critical': 9, operation: 'le'}
}
EDIT2: 将以下输入与上述阈值一起使用:
a b c
1 89 0 4
2 91 9 10
3 99 17 5
将得到结果:
a a_r b b_r c c_r
1 89 good 0 good 4 good
2 91 warn 9 warn 10 crit
3 99 crit 17 good 5 warn
因此,对于每个值(取决于列名称),我必须应用映射中的相应阈值。
答案 0 :(得分:1)
使用:
print (df)
a b c
1 89 11 4
2 91 9 10
3 99 17 5
thresholds = {
'a': {'warning': 90, 'critical': 98, 'operation': 'lt'},
'b': {'warning': 10, 'critical': 15, 'operation': 'gt'},
'c': {'warning': 5, 'critical': 9, 'operation': 'le'}
}
import operator
ops = {'gt': operator.gt,
'lt': operator.lt,
'ge': operator.ge,
'le': operator.le,
'eq': operator.eq,
'ne': operator.ne}
for k, v in thresholds.items():
op1 = v.pop('operation')
if op1 in ('lt','le'):
sorted_v = sorted(v.items(), key=operator.itemgetter(1))
else:
sorted_v = sorted(v.items(), key=operator.itemgetter(1), reverse=True)
for k1, v1 in sorted_v:
#https://stackoverflow.com/q/46421521/2901002
m = ops[op1](v1, df[k])
df.loc[m, f'{k}_added'] = k1
df = df.sort_index(axis=1).fillna('good')
print (df)
a a_added b b_added c c_added
1 89 good 11 critical 4 good
2 91 warning 9 warning 10 critical
3 99 critical 17 good 5 warning