Почему фильтрация на основе условия приводит к пустому DataFrame в пандах?

Я работаю с DataFrame в Python, используя pandas, и пытаюсь применить несколько условий для фильтрации строк на основе значений температуры из нескольких столбцов. Однако после применения моих условий и использования dropna() я получаю ноль строк, хотя ожидаю, что некоторые данные будут соответствовать этим условиям.

Цель — сравнить с температурой окружающей среды +40 C, и если значение превышает это значение, заменить его на NaN. В противном случае сохраните исходное значение.

Вот образец моего DataFrame и условий, которые я применяю:

data = {
    'Datetime': ['2022-08-04 15:06:00', '2022-08-04 15:07:00', '2022-08-04 15:08:00', 
                 '2022-08-04 15:09:00', '2022-08-04 15:10:00'],
    'Temp1': [53.4, 54.3, 53.7, 54.3, 55.4],
    'Temp2': [57.8, 57.0, 87.0, 57.2, 57.5],
    'Temp3': [59.0, 58.8, 58.7, 59.1, 59.7],
    'Temp4': [46.7, 47.1, 80, 46.9, 47.3],
    'Temp5': [52.8, 53.1, 53.0, 53.1, 53.4],
    'Temp6': [50.1, 69, 50.3, 50.3, 50.6],
    'AmbientTemp': [29.0, 28.8, 28.6, 28.7, 28.9]
}
df1 = pd.DataFrame(data)
df1['Datetime'] = pd.to_datetime(df1['Datetime'])
df1.set_index('Datetime', inplace=True)

Код:

temp_cols = ['Temp1', 'Temp2', 'Temp3', 'Temp4', 'Temp5', 'Temp6']
ambient_col = 'AmbientTemp'

condition = (df1[temp_cols].lt(df1[ambient_col] + 40, axis=0))

filtered_df = df1[condition].dropna()
print(filtered_df.shape)

Ответ:

(0, 99)

Проблема:

Несмотря на то, что ожидаются действительные данные, соответствующие условиям, результирующий DataFrame оказывается пустым после применения фильтра и удаления значений NaN. Что может быть причиной этой проблемы и как ее исправить?

Пожалуйста, жестко закодируйте данные в виде кода, чтобы у вас был минимальный воспроизводимый пример, который можно запустить.

Elerium115 06.05.2024 07:38

Как выглядит condition?

jared 06.05.2024 07:39

@Mainland, какова твоя конечная цель? Если вы объедините маску и dropna, было бы гораздо эффективнее использовать напрямую df[(df1[temp_cols].lt(df1[ambient_col] + 40, axis=0)).all(axis=1)], как показано в моем ответе.

mozway 06.05.2024 08:07
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
3
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ваше условие — DataFrame, если вы хотите выбрать по строке, вам следует агрегировать с любым / всем:

condition = (df1[temp_cols].lt(df1[ambient_col] + 40, axis=0)).all(axis=1)

Выход:

                     Temp1  Temp2  Temp3  Temp4  Temp5  Temp6  AmbientTemp
Datetime                                                                  
2022-08-04 15:06:00   53.4   57.8   59.0   46.7   52.8   50.1         29.0
2022-08-04 15:09:00   54.3   57.2   59.1   46.9   53.1   50.3         28.7
2022-08-04 15:10:00   55.4   57.5   59.7   47.3   53.4   50.6         28.9

Если вы хотите замаскировать значения, используйте где после переиндексации:

df1.where(condition.reindex(columns=df1.columns, fill_value=True))

Выход:

                     Temp1  Temp2  Temp3  Temp4  Temp5  Temp6  AmbientTemp
Datetime                                                                  
2022-08-04 15:06:00   53.4   57.8   59.0   46.7   52.8   50.1         29.0
2022-08-04 15:07:00   54.3   57.0   58.8   47.1   53.1    NaN         28.8
2022-08-04 15:08:00   53.7    NaN   58.7    NaN   53.0   50.3         28.6
2022-08-04 15:09:00   54.3   57.2   59.1   46.9   53.1   50.3         28.7
2022-08-04 15:10:00   55.4   57.5   59.7   47.3   53.4   50.6         28.9
Ответ принят как подходящий

Используйте DataFrame.where:

condition = (df1[temp_cols].lt(df1[ambient_col] + 40, axis=0))

df1[temp_cols] = df1[temp_cols].where(condition)

Если нужен новый DataFrame, добавьте DataFrame.reindex:

temp_cols = ['Temp1', 'Temp2', 'Temp3', 'Temp4', 'Temp5', 'Temp6']
ambient_col = 'AmbientTemp'

condition = (df1[temp_cols].lt(df1[ambient_col] + 40, axis=0))

filtered_df = df1.where(condition.reindex(df1.columns, fill_value=True, axis=1))
print(filtered_df)
                     Temp1  Temp2  Temp3  Temp4  Temp5  Temp6  AmbientTemp
Datetime                                                                  
2022-08-04 15:06:00   53.4   57.8   59.0   46.7   52.8   50.1         29.0
2022-08-04 15:07:00   54.3   57.0   58.8   47.1   53.1    NaN         28.8
2022-08-04 15:08:00   53.7    NaN   58.7    NaN   53.0   50.3         28.6
2022-08-04 15:09:00   54.3   57.2   59.1   46.9   53.1   50.3         28.7
2022-08-04 15:10:00   55.4   57.5   59.7   47.3   53.4   50.6         28.9

Как это работает:

#mask
print(condition)
                     Temp1  Temp2  Temp3  Temp4  Temp5  Temp6
Datetime                                                     
2022-08-04 15:06:00   True   True   True   True   True   True
2022-08-04 15:07:00   True   True   True   True   True  False
2022-08-04 15:08:00   True  False   True  False   True   True
2022-08-04 15:09:00   True   True   True   True   True   True
2022-08-04 15:10:00   True   True   True   True   True   True

#added Trues values in mask for missing columns - here `AmbientTemp`
print (condition.reindex(df1.columns, fill_value=True, axis=1))
                     Temp1  Temp2  Temp3  Temp4  Temp5  Temp6  AmbientTemp
Datetime                                                                  
2022-08-04 15:06:00   True   True   True   True   True   True         True
2022-08-04 15:07:00   True   True   True   True   True  False         True
2022-08-04 15:08:00   True  False   True  False   True   True         True
2022-08-04 15:09:00   True   True   True   True   True   True         True
2022-08-04 15:10:00   True   True   True   True   True   True         True

Другие вопросы по теме