Преобразование или изменение значений столбцов на основе значений других столбцов

avatar
Marc
8 августа 2021 в 20:09
159
1
1

У меня есть кадр данных, содержащий 5 столбцов. Что я хотел бы сделать, так это изменить последние 4 столбца на первый столбец.

В основном, если значение первого столбца ниже определенного порога, следующие столбцы изменяются, а если это значение выше порога, изменений не происходит.

Итак, я попробовал это:

import pandas as pd
df = pd.DataFrame({
  'col1' : [0.1, 0.3, 0.1, 0.2],
  'col2' : [2,4,3,7],
  'col3' : [3,4,4,9],
  'col4' : [4,2,2,6],
  'col5' : [0.3, 2.1, 1.0, .9],
})

def motif(col1, col2, col3, col4, col5):
  col2 = col2
  col3 = col3
  col4 = col4
  col5 = col5
  if col1 <=.15:
    col2 = col2 * .15
    col3 = col3 * .15
    col4 = col4 * .15
    col5 = col5 * .15
    return col2, col3, col4, col5
  else:
    return col2, col3, col4, col5

df.apply(lambda x: modify(x[col1], x[col2], x[col3], x[col4], x[col5]), axis=1)


Но это не работает. Если есть идеи буду очень признателен

Источник

Ответы (1)

avatar
Henry Ecker
8 августа 2021 в 20:12
3

Мы можем использовать loc для выбора строк, где col1 меньше или равно .15, а затем умножить остальные столбцы на <col18>2:<col18>2:

df.loc[df['col1'] <= 0.15, 'col2':] *= 0.15

df:

   col1  col2  col3  col4   col5
0   0.1  0.30  0.45   0.6  0.045
1   0.3  4.00  4.00   2.0  2.100
2   0.1  0.45  0.60   0.3  0.150
3   0.2  7.00  9.00   6.0  0.900

Естественно другие варианты столбцов работают, если все столбцы после col2 слишком широкие:

df.loc[df['col1'] <= 0.15, ['col2', 'col3', 'col4', 'col5']] *= 0.15
df.loc[df['col1'] <= 0.15, 'col2':'col5'] *= 0.15

Маску также можно сохранить и использовать повторно, если для разных столбцов нужны разные модификации:

m = df['col1'] <= 0.15
df.loc[m, 'col2':'col4'] *= 0.15
df.loc[m, 'col5'] *= 0.5  # col5 is different than col2-4

df:

   col1  col2  col3  col4  col5
0   0.1  0.30  0.45   0.6  0.15
1   0.3  4.00  4.00   2.0  2.10
2   0.1  0.45  0.60   0.3  0.50
3   0.2  7.00  9.00   6.0  0.90

Может работать apply (хотя он медленнее и намного больше кода), но так как требуется переопределить результаты, то неагрегированные результаты и столбцы могут быть перезаписаны. явно определено, и результат должен быть Series, а не tuple:

def modify(col1, col2, col3, col4, col5):
    if col1 <= .15:
        col2 = col2 * .15
        col3 = col3 * .15
        col4 = col4 * .15
        col5 = col5 * .15
    return pd.Series([col2, col3, col4, col5])


df[['col2', 'col3', 'col4', 'col5']] = df.apply(lambda x: modify(
    x['col1'], x['col2'], x['col3'], x['col4'], x['col5']
), axis=1)

df:

   col1  col2  col3  col4   col5
0   0.1  0.30  0.45   0.6  0.045
1   0.3  4.00  4.00   2.0  2.100
2   0.1  0.45  0.60   0.3  0.150
3   0.2  7.00  9.00   6.0  0.900