【问题标题】:Append columns to a DataFrame using apply and compute new columns based on existing values using apply on the row使用 apply 将列附加到 DataFrame,并使用行上的 apply 根据现有值计算新列
【发布时间】:2019-09-29 00:04:12
【问题描述】:

给定一个数据框

  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 函数返回一个新的列名。在那之后,我认为我需要将这两个 DataFrames 与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'}
}

编辑2: 使用具有上述阈值的以下输入:

  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

因此,对于取决于列名的每个值,我必须从地图中应用相应的阈值。

【问题讨论】:

  • 我想你必须告诉我们这些列是通过什么逻辑创建的,否则很难提供帮助。
  • @Cleb 你说得对,我已经更新了我的问题。

标签: python pandas dataframe series


【解决方案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

【讨论】:

  • 感谢您的回答,由于信息不足,我已经更新了我的问题。
  • 感谢您的回答!您的方法的唯一问题是,生成的 DataFrame 将只是应用的最后一个操作的结果。例如,阈值{ 'warning': 30, 'critical': 35, 'operation': lt } 将始终对介于 30 和 35 之间的值显示为关键...因此它显示应用的最新阈值
  • @CosminM。 - 不容易测试,是否可以添加一些具有预期输出的示例数据?
  • 我已经添加了预期的输出。
  • @CosminM。 - 答案已更改,第二列的第一个值也更改为 11
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-18
  • 2020-02-20
  • 2020-10-31
  • 2019-12-29
  • 2019-07-22
  • 1970-01-01
相关资源
最近更新 更多