Фильтрация Pandas с использованием np.where в качестве фильтра не работает так, как ожидалось.

Вопрос или проблема

Я работал с набором данных SpaceShip Titanic от Kaggle и проводил анализ данных. Обозначим tt как pd.DataFrame, содержащий данные. Я суммировал все денежные переменные, а затем попытался отфильтровать, чтобы получить только те строки, где TotalExp==0 и CryoSleep.isna(), но в результатах я получаю как людей с CryoSleep не nan, так и людей с TotalExp не 0

monetary = ['RoomService', 'FoodCourt', 'ShoppingMall', 'Spa', 'VRDeck']
tt.loc[:,'TotalExp'] = tt.loc[:,monetary].sum(axis=1)
tt.loc[np.where((tt.TotalExp == 0.0) & (tt.CryoSleep.isna()))][['CryoSleep','TotalExp']]

Пример текущего вывода:

индекс CryoSleep TotalExp
1405 NaN 977.0
1417 False 0.0
1454 NaN 3862.0
1531 NaN 0.0
1565 NaN 906.0

Я пробовал оба фильтра отдельно, и поведение в каждом случае одинаковое (принося случаи, которые не должны быть).

Ожидаемое поведение заключается в том, что отображаются только строки, где CryoSleep является NaN и TotalExp = 0, оба одновременно.

Что я упускаю?

Чтобы исправить код для выбора строк, где CryoSleep является NaN и TotalExp равен 0, вы можете изменить последнюю строку кода следующим образом: Я работаю с образцом DataFrame

import pandas as pd
import numpy as np

# создаем образец dataframe
tt = pd.DataFrame({
    'RoomService': [10, 0, 20, 0, 30],
    'FoodCourt': [20, 0, 30, 0, 40],
    'ShoppingMall': [30, 0, 40, 0, 50],
    'Spa': [40, 0, 50, 0, 60],
    'VRDeck': [50, 0, 60, 0, 70],
    'CryoSleep': [np.NaN, 1, 0, 1, np.NaN]
})

# суммируем денежные столбцы и присваиваем в столбец TotalExp
monetary = ['RoomService', 'FoodCourt', 'ShoppingMall', 'Spa', 'VRDeck']
tt.loc[:, 'TotalExp'] = tt.loc[:, monetary].sum(axis=1)

# выбираем строки, где CryoSleep является NaN и TotalExp равен 0
selected_data = tt.loc[(tt['CryoSleep'].isna()) & (tt['TotalExp'] == 0), ['CryoSleep', 'TotalExp']]

# печатаем выбранные данные
print(selected_data)

Вам не нужно использовать np.where, чтобы получить результат, но если вы все же хотите использовать эту функцию, попробуйте следующий код;

selected_data = tt.loc[np.where((tt['CryoSleep'].isna()) & (tt['TotalExp'] == 0)), ['CryoSleep', 'TotalExp']]
```

Ответ или решение

Применение фильтрации в Pandas с использованием np.where в наборе данных SpaceShip Titanic

При работе с библиотекой Pandas для анализа данных в Kaggle’s SpaceShip Titanic dataset, у вас возникла проблема с фильтрацией, когда результат не соответствует ожидаемому. Конкретно, вы хотите отфильтровать строки, где TotalExp == 0 и CryoSleep.isna() одновременно, но в выводе оказывается много лишних данных.

Причина проблемы

На первый взгляд, использование np.where в вашем коде выглядит корректным, однако основная проблема кроется в том, как выполняется операция логического "И" (&). В вашем коде:

tt.loc[np.where((tt.TotalExp == 0.0) & (tt.CryoSleep.isna()))][['CryoSleep','TotalExp']]

По сути, использование np.where в этом контексте избыточно и может привести к путанице, так как функция np.where возвращает индексы, а не логические массивы, что может быть не совсем ясно в вашем случае.

Решение проблемы

Для фильтрации данных в DataFrame, использование прямого логического условия будет более эффективным и понятным. Вы можете переписать ваш код следующим образом:

import pandas as pd
import numpy as np

# Создаем пример DataFrame
tt = pd.DataFrame({
    'RoomService': [10, 0, 20, 0, 30],
    'FoodCourt': [20, 0, 30, 0, 40],
    'ShoppingMall': [30, 0, 40, 0, 50],
    'Spa': [40, 0, 50, 0, 60],
    'VRDeck': [50, 0, 60, 0, 70],
    'CryoSleep': [np.NaN, 1, 0, 1, np.NaN]
})

# Суммируем денежные столбцы и присваиваем результат в столбец TotalExp
monetary = ['RoomService', 'FoodCourt', 'ShoppingMall', 'Spa', 'VRDeck']
tt['TotalExp'] = tt[monetary].sum(axis=1)

# Отбираем строки, где CryoSleep равен NaN и TotalExp равен 0
selected_data = tt[(tt['CryoSleep'].isna()) & (tt['TotalExp'] == 0)][['CryoSleep', 'TotalExp']]

# Печатаем отобранные данные
print(selected_data)

Альтернативный подход с использованием np.where

Если вы все же хотите использовать np.where, следует это делать так:

selected_data = tt.loc[np.where((tt['CryoSleep'].isna()) & (tt['TotalExp'] == 0)), ['CryoSleep', 'TotalExp']]

Однако, как упоминалось ранее, данный подход не является лучшим в данном случае.

Заключение

Использование логической фильтрации напрямую через логические условия в Pandas является более понятным и предпочтительным методом для решения вашей задачи. Таким образом, вы сможете избежать путаницы с использованием np.where и сразу извлекать нужные вам данные. Главное – обращайте внимание на то, что возвращают ваши методы, чтобы не попасть в ловушку неправильной интерпретации возвращаемых значений. Надеюсь, это поможет вам в ваших дальнейших анализах!

Оцените материал
Добавить комментарий

Капча загружается...