Добавить столбцы в DataFrame, используя apply, и вычислить новые столбцы на основе существующих значений, используя apply в строке. - PullRequest
0 голосов
/ 11 мая 2019

Учитывая DataFrame

  a b c d
1 5 5 5 5
2 5 5 5 5
3 5 5 5 5

Я хотел бы добавить больше столбцов в DataFrame на основе существующих, но используя некоторую логику, которая не может вписаться в лямбду.Желаемый результат должен выглядеть примерно так:

   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'

После просмотра этого ответа я предложил использовать DataFrame.apply() в каждой строке и после этого Series.apply() в каждом значении, ноЯ не знаю точно, как связать вызовы и что именно вернуть, чтобы я возвращал имя нового столбца из функции применения Series.После этого я думаю, что мне нужно объединить эти два 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'}
}

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

Поэтому для каждого значения в зависимости от имени столбца я должен применить соответствующий порог с карты.

1 Ответ

1 голос
/ 11 мая 2019

Использование:

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
...