Polars – неожиданное поведение при использовании drop_nans() для всех столбцов

У меня есть простой фрейм данных Polars с некоторыми нулями и некоторыми NaN, и я хочу удалить только последнее. Я пытаюсь использовать drop_nans(), применяя его ко всем столбцам, и по какой-то причине он заменяет NaN на литерал 1.0.

Я в замешательстве. Возможно, я неправильно использую метод, но в документации мало информации и определенно не описывается такое поведение:

ex = pl.DataFrame(
    {
        'a': [float('nan'), 1, float('nan')],
        'b': [None, 'a', 'b']
    }
)

ex.with_columns(pl.all().drop_nans())

Out:

a   b
1.0 null
1.0 "a"
1.0 "b"

Я использую последнюю версию Polars 1.5.

Каков правильный способ перетаскивания NaN по всем столбцам, учитывая, что в кадрах данных Polars 1.5, похоже, нет метода drop_nans(), есть только у Series?

Обновлено: Я ожидаю, что результат должен быть:

a    b
1.0  'a'

🤔 А знаете ли вы, что...
В Python есть инструменты для тестирования кода, такие как библиотека unittest.


3
55
1

Ответ:

Решено

В вашем примере происходит то, что drop_nans работает для каждого столбца. Сначала он преобразует серию [float('nan'), 1, float('nan')] в [1], а затем транслирует это значение на весь столбец в сочетании с ["a", "b"].

Это происходит потому, что в Polars пока нет концепции скалярного значения, и он будет рассматривать любой столбец с одним значением как таковой при принятии решения о том, когда транслировать. В будущем это изменится, но это большая работа. Итак, прямо сейчас вы можете увидеть подобные неправильные трансляции при использовании функций, фильтрующих столбцы, например drop_nan, если происходит фильтрация до столбца длиной 1.

Вместо того, чтобы делать pl.all().drop_nans(), вам следует фильтровать только те строки, в которых столбец a не имеет значения nan:

>>> df.filter(pl.col.a.is_not_nan())
shape: (1, 2)
┌─────┬─────┐
│ a   ┆ b   │
│ --- ┆ --- │
│ f64 ┆ str │
╞═════╪═════╡
│ 1.0 ┆ a   │
└─────┴─────┘

Или, в более общем смысле, если у вас есть несколько столбцов со значениями с плавающей запятой:

>>> import polars.selectors as cs
>>> df.filter(pl.all_horizontal(cs.float().is_not_nan()))
shape: (1, 2)
┌─────┬─────┐
│ a   ┆ b   │
│ --- ┆ --- │
│ f64 ┆ str │
╞═════╪═════╡
│ 1.0 ┆ a   │
└─────┴─────┘