Я хотел бы одновременно заменить значения нескольких столбцов соответствующими значениями в других столбцах на основе значений в первой группе столбцов (в частности, где один из первые столбцы пустые). Вот пример того, что я пытаюсь сделать:Условная замена нескольких столбцов на основе значений столбцов в pandas DataFrame
import pandas as pd
df = pd.DataFrame({'a1':['m', 'n', 'o', 'p'],
'a2':['q', 'r', 's', 't'],
'b1':['', '', 'a', '' ],
'b2':['', '', 'b', '']})
df
# a1 a2 b1 b2
# 0 m q
# 1 n r
# 2 o s a b
# 3 p t
Я хотел бы заменить «» значения b1 и b2 с соответствующими значениями a1 и a2, где b1 является пустым:
# a1 a2 b1 b2
# 0 m q m q
# 1 n r n r
# 2 o s a b
# 3 p t p t
Вот мой мыслительный процесс (я относительно новым для панд, так что я, вероятно, говоря с сильным акцентом R здесь):
missing = (df.b1 == '')
# First thought:
df[missing, ['b1', 'b2']] = df[missing, ['a1', 'a2']]
# TypeError: 'Series' objects are mutable, thus they cannot be hashed
# Fair enough
df[tuple(missing), ('b1', 'b2')] = df[tuple(missing), ('a1', 'a2')]
# KeyError: ((True, True, False, True), ('a1', 'a2'))
# Obviously I'm going about this wrong. Maybe I need to use indexing?
df[['b1', 'b2']].ix[missing,:]
# b1 b2
# 0
# 1
# 3
# That looks right
df[['b1', 'b2']][missing, :] = df[['a1', 'a2']].ix[missing, :]
# TypeError: 'Series' objects are mutable, thus they cannot be hashed
# Deja vu
df[['b1', 'b2']].ix[tuple(missing), :] = df[['a1', 'a2']].ix[tuple(missing), :]
# ValueError: could not convert string to float:
# Uhh...
Я мог бы сделать это столбец за столбцом:
df['b1'].ix[missing] = df['a1'].ix[missing]
df['b2'].ix[missing] = df['a2'].ix[missing]
... но я подозреваю, что существует более идиоматический способ сделать это. Мысли?
Обновление: Чтобы уточнить, я задаюсь вопросом, можно ли одновременно обновлять все столбцы. Например, гипотетический модификация ответа Primer (это не работает, и результаты в NaNs, хотя я не уверен, почему):
df.loc[missing, ['b1', 'b2']] = f.loc[missing, ['a1', 'a2']]
# a1 a2 b1 b2
# 0 m q NaN NaN
# 1 n r NaN NaN
# 2 o s a b
# 3 p t NaN NaN
Этот метод является на самом деле медленнее, чем ОП, это было так же, как мой ответ, который я удалил, потому что он медленнее – EdChum
Спасибо за ответ. Я надеялся сделать это за один шаг для всех столбцов, вместо того, чтобы делать это по столбцу (все еще не уверен, что это возможно). Например: 'df.loc [missing, ['b1', 'b2']] = df.loc [missing, ['a1', 'a2']] ' – danpelota
Мой плохой, как-то неправильно понял вопрос ... Во всяком случае, Алекс предложил другой подход с' .where', который является хорошим однострочным словом, который вы ищете. Вы также можете использовать '.ix' вместо' .loc', который иногда дает несколько лучшие результаты с точки зрения скорости (если это проблема). – Primer