Извлечение значений столбца в зависимости от условий

1

У меня есть следующий фреймворк

df = pd.DataFrame({
    'Column_1': ['Position', 'Start', 'End', 'Position'], 
    'Original_1': ['Open', 'Barn', 'Grass', 'Bubble'], 
    'Latest_1': ['Shut', 'Horn', 'Date', 'Dinner'], 
    'Column_2': ['Start', 'Position', 'End', 'During'], 
    'Original_2': ['Sky', 'Hold', 'Car', 'House'], 
    'Latest_2': ['Pedal', 'Lap', 'Two', 'Force'], 
    'Column_3': ['Start', 'End', 'Position', 'During'], 
    'Original_3': ['Leave', 'Dog', 'Block', 'Hope'], 
    'Latest_3': ['Sear', 'Crawl', 'Enter', 'Night']
})

Для каждого экземпляра, где слово "Позиция" находится в столбце "Столбец_1", "Столбец_2" или "Столбец_3", я хочу зафиксировать связанные значения в "Оригинал_1", "Оригинал_2", "Оригинал_3" и назначить их новому столбцу с именем "Столбец_3", Original_Values.

Следующий код может выполнить это, но только для столбцов по столбцам.

df['Original_Value1'] = df.loc[df['Column_1'] == 'Position', 'Original_1']
df['Original_Value2'] = df.loc[df['Column_2'] == 'Position', 'Original_2']
df['Original_Value3'] = df.loc[df['Column_3'] == 'Position', 'Original_3']

Есть ли способ воссоздать вышеприведенный код, чтобы он выполнял итерацию по всему кадру данных (а не по указанным столбцам)?

Я надеюсь создать один столбец ("Original_values") со следующим результатом:

0      Open
1      Hold
2     Block
3    Bubble
Name: Original_Values, dtype: object
Теги:
pandas
dataframe
loc

3 ответа

2

Как насчет создания маски с первыми тремя столбцами (или указать их имя) и умножить ее на значения в столбцах с 6 по 9 (или указать их имена). Затем возьмите значение max(), чтобы удалить nan.

df['Original_Values'] = ((df.iloc[:,:3] == 'Position') * df.iloc[:,6:9].values).max(1)

print(df['Original_values'])

Возвращает:

0      Open
1      Hold
2     Block
3    Bubble
Name: Original_Value, dtype: object
2

Один из способов сделать это с помощью df.apply():

def choose_orig(row):
    if row['Column_1'] == 'Position':
        return row['Original_1']
    elif row['Column_2'] == 'Position':
        return row['Original_2']
    elif row['Column_3'] == 'Position':
        return row['Original_3']
    return ''

df['Original_Values'] = df.apply(choose_orig, axis=1)

Аргумент axis=1 для df.apply() вызывает choose_orig() которая будет вызываться один раз для каждой строки данных.

Обратите внимание, что это использует значение по умолчанию пустой строки, '', когда ни один из столбцов не соответствует слову 'Position'.

0

Вот своего рода глупый способ сделать это с помощью некоторой укладки, которая может работать лучше, если у вас очень большой df и вам нужно избегать axis=1.

  • Уложите первые три столбца, чтобы создать список индекса, а в столбце 'Original' значение соответствует
  • Уберите столбцы, из которых вы хотите получить значения. Используйте приведенный выше список, чтобы переиндексировать его, чтобы вы вернули соответствующее значение.
  • Верните эти значения в исходный df на основе исходного индекса строки.

Здесь код:

import re

mask_list = ['Column_1', 'Column_2', 'Column_3']
val_list = ['Original_1', 'Original_2', 'Original_3']

idx = df[mask_list].stack()[df[mask_list].stack() == 'Position'].index.tolist()
idx = [(x , re.sub('(.*_)', 'Original_', y)) for x, y in idx]

df['Original_Values'] = df[val_list].stack().reindex(idx).reset_index(level=1).drop(columns='level_1')

df теперь:

   Column_1  Column_2  Column_3 ... Original_Values
0  Position     Start     Start ...            Open
1     Start  Position       End ...            Hold
2       End       End  Position ...           Block
3  Position    During    During ...          Bubble

Если 'Position' не найден ни в одном из столбцов в mask_list, Original_Values становится NaN для этой строки. Если вам нужно масштабировать его до большего количества столбцов, просто добавьте их в mask_list и val_list.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню