#python #pandas #numpy
Вопрос:
Представьте, что у вас есть следующий df:
d = {'taxrate#1': [1, 2], 'taxrate#2': [3, np.nan],'line amount#1': [10, 20], 'line amount #2': [50, 12]}
df = pd.DataFrame(data=d)
df
taxrate#1 taxrate#2 line amount#1 line amount #2
0 1 3.0 10 50.0
1 2 NaN 20 12
Теперь я хотел бы установить значение суммы строки № 2 равным nan, если ставка налога № 2 равна nan. Я хотел бы сделать это итеративно/динамически, потому что суммы строк/ ставки налогов могут достигать 10.
Таким образом, идеальным результатом было бы:
taxrate#1 taxrate#2 line amount#1 line amount #2
0 1 3.0 10 50.0
1 2 NaN 20 NaN
Как достичь вышеперечисленного?
Пожалуйста, помогите!
Ответ №1:
Использование Series.isna()
и цикл
d = {'taxrate#1': [np.nan, 2], 'taxrate#2': [3, np.nan],
'line amount#1': [10, 20], 'line amount#2': [50, 12]}
df = pd.DataFrame(data=d)
for taxrate_col in {x for x in df.columns if x.startswith("taxrate")}:
col_id = taxrate_col.split("#")[1]
df.loc[df[taxrate_col].isna(), f'line amount#{col_id}'] = np.nan
Которые делают
taxrate#1 taxrate#2 line amount#1 line amount#2
0 NaN 3.0 10 50
1 2.0 NaN 20 12
Становится
taxrate#1 taxrate#2 line amount#1 line amount#2
0 NaN 3.0 NaN 50.0
1 2.0 NaN 20.0 NaN
Комментарии:
1. Спасибо за ваш комментарий, однако я хотел бы сделать это динамически, потому что ставки налогов / суммы строк могут занимать до 10 строк
2. @Max вы имеете в виду несколько столбцов, а не несколько строк ? То есть вы имеете в виду lineamount1 на основе таксона1, lineamount2 на основе таксона2, … ?
3. Да, извините, несколько столбцов! Точно!
4. @Max, если вы можете добавить аналогичные примеры данных в вопрос, которые помогут вам быстро получить правильный ответ.
Ответ №2:
Вы можете использовать pandas.wide_to_long
:
>>> d = {
'taxrate#1': [1, 2], 'taxrate#2': [3, np.nan],
'line amount#1': [10, 20], 'line amount#2': [50, 12]
}
>>> df = pd.DataFrame(data=d)
>>> longdf = pd.wide_to_long(
df.reset_index(),
stubnames=['taxrate', 'line amount'],
i='index', sep='#', j='number'
)
>>> longdf
taxrate line amount
index number
0 1 1.0 10
1 1 2.0 20
0 2 3.0 50
1 2 NaN 12
>>> longdf.loc[longdf['taxrate'].isna(), 'line amount'] = np.nan
>>> widedf = longdf.reset_index().pivot(index=['index'], columns=['number'])
>>> widedf.columns = [f'{stub}#{num}' for stub, num in widedf.columns]
>>> widedf
taxrate#1 taxrate#2 line amount#1 line amount#2
index
0 1.0 3.0 10.0 50.0
1 2.0 NaN 20.0 NaN
Комментарии:
1. Кажется, я не могу перезаписать существующий df, знаете почему?
2. @Макс, что ты имеешь в виду?
df = widedf
не работает?3. Поэтому я хочу перезаписать существующий df с большим количеством значений, но с теми же именами столбцов: dftaxitems.update(widedf, перезапись = True). Однако он не обновляет значения..
4. @Max да, правильно, вы не можете обновлять существующие значения, отличные от na, значениями na с помощью
df.update
5. Спасибо тебе, Цитторак!