Добавление нескольких условий при фильтрации столбца pandas

Неободимо преобразовать столбец "Итоговая цена" по условиям:

  1. Если df['Склад'] = Nan, то в df['Итоговая цена'] значение остается неизменным.
  2. Если в df['Склад'] = 1 и df['Цена склада'] = Nan, то в df['Итоговая цена'] ставим 1
  3. Если в df['Склад'] = 1 и df['Цена склада'] = len() > 0 (если поле не пустое), то в df['Итоговая цена'] ставим значение из df['Цена склада']
  4. Если в df['Склад'] = 2 и df['Итоговая цена'] != 0, то df['Итоговая цена'] = 1, Ну а если в df['Склад'] = 2 и df['Итоговая цена'] = 0, то в df['Итоговая цена'] ничего не меняем. Пусть ноль и остается.

В остальных случаях, поле df['Итоговая цена'] не меняется.

import pandas as pd
import numpy as np

df = pd.DataFrame({'Склад': [np.nan, np.nan, 1, 2, 2, 2, np.nan, 1, 1, np.nan],
           'Цена склада': [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, 100000, 30000, np.nan],
           'Итоговая цена': [0, 80600, np.nan, 55000, 13500, np.nan, 99200, np.nan, 135000, 120400]})
df['Итоговая цена'] = df['Итоговая цена'].fillna(0).astype(int)

Вот какой результат необходим:

введите сюда описание изображения

Сейчас у меня такой код:

df['Итоговая цена'] = np.where((df['Склад'] == 1) & (df['Цена склада'] == np.nan), 1, df['Итоговая цена']).astype(int)
df['Итоговая цена'] = np.where((df['Склад'] == 1) & (df['Цена склада'] != np.nan), df['Цена склада'], df['Итоговая цена']).astype(int)
df['Итоговая цена'] = np.where((df['Склад'] == 2) & (df['Итоговая цена'] != 0), 1, df['Итоговая цена']).astype(int)

Но почему то первый код выполняется не корректно. Я поставил условие если склад = 1 и Итоговая цена = пустому значению, но почему то он игнорирует это пустое значение и применяет ко всем полям.


Ответы (1 шт):

Автор решения: CrazyElf

Два замечания:

  • на NA надо проверять через метод isna, простые сравнения с NA не работают, это же не число ("Not a Number")
  • если альтернативой у вас является "оставить как есть", то лучше использовать не np.where, а присваивать через .loc по маске, так вы не будете переписывать в каждой строчке весь датасет какими-то значениями, а измените только строки, подходящие по условию

Примерно так должно получиться:

df.loc[(df['Склад'] == 1) & (df['Цена склада'].isna()), 'Итоговая цена'] = 1
df.loc[(df['Склад'] == 1) & (~df['Цена склада'].isna()), 'Итоговая цена'] = df['Цена склада']
df.loc[(df['Склад'] == 2) & (df['Итоговая цена'] != 0), 'Итоговая цена'] = 1
→ Ссылка