как заполнить коллонку dataframe по условию наличия значения в дугой колонке?
Я пытаюсь скопировать первую колонку данных по условию наличия значений в другой колонке, но проблема в том что заполнение происходит не по условию
код:
data = ({'A': [1, 2, 3, 4],
'B': [2, 4, 7, np.nan],
'C': [3, 5, np.nan, 4],
'D': [9, np.nan, 8, 6],
'E': [np.nan, 3, 2, 7]})
df = pd.DataFrame(data)
for i in df['A'].values:
df1 = df.loc[df['A'] == i]
if df1['B'] is not np.nan:
df1['a_b'] = df1['A']
else:
df1['a_b'] = np.nan
A B C D E a_b
0 1 2.0 3.0 9.0 NaN 1
A B C D E a_b
1 2 4.0 5.0 NaN 3.0 2
A B C D E a_b
2 3 7.0 NaN 8.0 2.0 3
A B C D E a_b
3 4 NaN 4.0 6.0 7.0 4
нужная колонка копируется полностью, без необходимого исключения данных.
Как можно сделать заполнение с условием? И если не трудно, подскажите, пожалуйста, еще как можно объединить расслоенные датафреймы?
Ответы (2 шт):
Если я правильно понял суть задачи:
mask = ~df['B'].isna()
df.loc[mask, 'a_b'] = df.loc[mask, 'A']
Нужно выбирать строки по булевой маске, причём одной и той же справа и слева от знака присваивания. Ну и копировать данные. А NA при этом можно и не копировать - всё, что не будет заполнено в новом столбце, и так будет иметь значение NA.
Ну и ещё могу пояснить, почему это if df1['B'] is not np.nan: не работает. Слева у вас pandas.series (хотя и из одного элемента), а справа скаляр. Естественно, они не могут быть одним и тем же объектом, что вы проверяете через is. Но даже если вы возьмёте один элемент, всё-равно будут проблемы с типом и is не сработает. Проверять такие вещи можно по-другому, через функцию isna: if not df1['B'].isna().all():. Но в любом случае лучше не работать с датафреймами через циклы, а делать всё векторно - сразу со всеми подходящими элементами столбца, без циклов.
вы хотите получить что-то вроде этого?
df['a_b'] = df['A'].mask(df['B'].isna())
>>> df
'''
A B C D E a_b
0 1 2.0 3.0 9.0 NaN 1.0
1 2 4.0 5.0 NaN 3.0 2.0
2 3 7.0 NaN 8.0 2.0 3.0
3 4 NaN 4.0 6.0 7.0 NaN