np.where не защищает log от неверного аргумента: маска ufunc

Нужно логарифмировать положительные значения, а нули и отрицательные пометить NaN. Выражение np.where(x > 0, np.log(x), np.nan) выглядит как условный оператор. Но расчёт всё равно выдаёт предупреждение о неверном аргументе, а при строгом режиме ошибок падает.

Аргументы функции вычисляются до её вызова. np.log(x) получает весь массив, и только потом np.where выбирает элементы результата. Чтобы не вычислять функцию на запрещённых позициях, используйте параметр where самой ufunc и заранее заполненный out.

Как изменить решение

import numpy as np
x = np.array([-1., 0., 1., np.e])
out = np.full(x.shape, np.nan, dtype=float)
with np.errstate(divide='raise', invalid='raise'):
    np.log(x, out=out, where=x > 0)
assert np.isnan(out[:2]).all()
assert np.allclose(out[2:], [0., 1.])
print(out)

Результат содержит NaN на первых двух позициях и логарифмы положительных значений на остальных. Строгий режим не поднимает ошибку, потому что запрещённые элементы не участвуют в вычислении log.

Инициализация out — часть решения. Позиции, где where ложно, остаются прежними; без явно заданного массива их содержимое нельзя использовать как определённое значение. Выберите NaN, ноль или отдельную маску согласно смыслу показателя, а не ради отсутствия предупреждений.

Что проверить на своих данных

Установите NumPy и запустите пример. Затем замените x на целочисленный массив: out всё равно должен иметь вещественный dtype, ведь логарифм не обязан быть целым. Проверьте также бесконечность и NaN, если они возможны во входе; маска x > 0 пропустит положительную бесконечность, а её логарифм останется бесконечным.

Подавление предупреждений через errstate(ignore) не исправляет область определения. Оно может быть уместно, когда результат inf или NaN предусмотрен формулой, но здесь нам нужно именно избежать вычисления на части данных. Тот же подход работает с sqrt и другими ufunc. Когда операций несколько, сохраните общую маску допустимости, чтобы разные столбцы признаков строились на согласованном наборе строк.

Практика дальше

Маски встречаются далеко за пределами логарифма. В тренажёре «NumPy и pandas» вы практикуете выбор элементов, broadcasting и расчёты с массивами, затем очищаете таблицы и считаете показатели. В программе 124 задачи с кодом; решения проверяются в браузере.

Посмотреть программу и практику курса

Источник: np.where не защищает log от неверного аргумента — официальная документация.

Другие задачи по теме: Календарь, пропуски и точность вычислений.

Продолжить на практике

  • NumPy и pandas: практический тренажёр ↗

    Бесплатный тренажёр NumPy и pandas для тех, кто знает основы Python. Научитесь очищать таблицы, объединять данные и собирать отчёты: 31 урок и 124 задачи с кодом и автоматической проверкой.