Pandas обновить сразу несколько столбцов
Я пытаюсь обновить пару полей одновременно - у меня есть два источника данных, и я пытаюсь их согласовать. Я знаю, что смогу сделать некоторое уродливое слияние, а затем удалить столбцы, но ожидал, что этот код будет работать ниже:
df = pd.DataFrame([['A','B','C',np.nan,np.nan,np.nan],
['D','E','F',np.nan,np.nan,np.nan],[np.nan,np.nan,np.nan,'a','b','d'],
[np.nan,np.nan,np.nan,'d','e','f']], columns = ['Col1','Col2','Col3','col1_v2','col2_v2','col3_v2'])
print df
Col1 Col2 Col3 col1_v2 col2_v2 col3_v2
0 A B C NaN NaN NaN
1 D E F NaN NaN NaN
2 NaN NaN NaN a b d
3 NaN NaN NaN d e f
#update
df.loc[df['Col1'].isnull(),['Col1','Col2', 'Col3']] = df[['col1_v2','col2_v2','col3_v2']]
print df
Col1 Col2 Col3 col1_v2 col2_v2 col3_v2
0 A B C NaN NaN NaN
1 D E F NaN NaN NaN
2 NaN NaN NaN a b d
3 NaN NaN NaN d e f
Мой желаемый результат:
Col1 Col2 Col3 col1_v2 col2_v2 col3_v2
0 A B C NaN NaN NaN
1 D E F NaN NaN NaN
2 a b c a b d
3 d e f d e f
Я уверен, что это связано с обновлением/настройкой на срезе, но я всегда использую .loc для обновления значений, а не только для нескольких столбцов одновременно.
Я чувствую, что есть простой способ сделать это, что я просто отсутствую, любые мысли/предложения будут приветствоваться!
Изменить, чтобы отразить решение ниже
Спасибо за комментарий к индексам. Однако у меня есть вопрос об этом, поскольку он относится к серии. Если бы я хотел обновить отдельную серию аналогичным образом, я мог бы сделать что-то вроде этого:
df.loc[df['Col1'].isnull(),['Col1']] = df['col1_v2']
print df
Col1 Col2 Col3 col1_v2 col2_v2 col3_v2
0 A B C NaN NaN NaN
1 D E F NaN NaN NaN
2 a NaN NaN a b d
3 d NaN NaN d e f
Обратите внимание, что здесь я не учитывал индексы, я отфильтровывался до серии 2x1 и устанавливал значение, равное серии 4x1, но он правильно его обрабатывал. Мысли? Я пытаюсь понять функциональность немного лучше того, что я использовал какое-то время, но, я думаю, не имеет полного понимания основного механизма/правила
Ответы
Ответ 1
вы хотите заменить
print df.loc[df['Col1'].isnull(),['Col1','Col2', 'Col3']]
Col1 Col2 Col3
2 NaN NaN NaN
3 NaN NaN NaN
С
replace_with_this = df.loc[df['Col1'].isnull(),['col1_v2','col2_v2', 'col3_v2']]
print replace_with_this
col1_v2 col2_v2 col3_v2
2 a b d
3 d e f
Кажется разумным. Однако, когда вы выполняете задание, вам необходимо учитывать выравнивание индекса, в которое входят столбцы.
Итак, это должно работать:
df.loc[df['Col1'].isnull(),['Col1','Col2', 'Col3']] = replace_with_this.values
print df
Col1 Col2 Col3 col1_v2 col2_v2 col3_v2
0 A B C NaN NaN NaN
1 D E F NaN NaN NaN
2 a b d a b d
3 d e f d e f
Я учитывал столбцы, используя .values
в конце. Это разделило информацию столбца из фрейма replace_with_this
и просто использовало значения в соответствующих позициях.
Ответ 2
В духе "взять холм" я предлагаю нижеприведенное решение, которое дает требуемый результат.
Я понимаю, что это не совсем то, что вам нужно, поскольку я не нарезаю df (разумным, но не функциональным способом, в котором вы предлагаете).
#Does not work when indexing on np.nan, so I fill with some arbitrary value.
df = df.fillna('AAA')
#mask to determine which rows to update
mask = df['Col1'] == 'AAA'
#dict with key value pairs for columns to be updated
mp = {'Col1':'col1_v2','Col2':'col2_v2','Col3':'col3_v2'}
#update
for k in mp:
df.loc[mask,k] = df[mp.get(k)]
#swap back np.nans for the arbitrary values
df = df.replace('AAA',np.nan)
Выход:
Col1 Col2 Col3 col1_v2 col2_v2 col3_v2
A B C NaN NaN NaN
D E F NaN NaN NaN
a b d a b d
d e f d e f
Ошибка, которую я получаю, если я не заменяю nans, ниже. Я собираюсь точно изучить, откуда эта ошибка.
ValueError: array is not broadcastable to correct shape