В Pandas можно выполнять логические операции над логическими DataFrames с помощью методов all и any, предоставляя аргумент axis. Например:
import pandas as pd
data = dict(A=["a","b","?"], B=["d","?","f"])
pd_df = pd.DataFrame(data)
Например, чтобы получить логическую маску для столбцов, содержащих элемент "?":
(pd_df == "?").any(axis=0)
и получить маску для строк:
(pd_df == "?").any(axis=1)
Кроме того, чтобы получить одно логическое значение:
(pd_df == "?").any().any()
Для сравнения, в polars лучшее, что я смог придумать, это следующее:
import polars as pl
pl_df = pl.DataFrame(data)
Чтобы получить маску для столбцов:
(pl_df == "?").select(pl.all().any())
Чтобы получить маску для строк:
pl_df.select(
pl.concat_list(pl.all() == "?").alias("mask")
).select(
pl.col("mask").arr.eval(pl.element().any()).arr.first()
)
И чтобы получить одно логическое значение:
pl_df.select(
pl.concat_list(pl.all() == "?").alias("mask")
).select(
pl.col("mask").arr.eval(pl.element().any()).arr.first()
)["mask"].any()
Последние два случая кажутся особенно многословными и запутанными для такой простой задачи, поэтому мне интересно, есть ли более короткие/быстрые эквиваленты?






>>> df.select(pl.all() == "?")
shape: (3, 2)
┌───────┬───────┐
│ A ┆ B │
│ --- ┆ --- │
│ bool ┆ bool │
╞═══════╪═══════╡
│ false ┆ false │
│ false ┆ true │
│ true ┆ false │
└───────┴───────┘
>>> df.select((pl.all() == "?").any())
shape: (1, 2)
┌──────┬──────┐
│ A ┆ B │
│ --- ┆ --- │
│ bool ┆ bool │
╞══════╪══════╡
│ true ┆ true │
└──────┴──────┘
>>> df.select(pl.any(pl.all() == "?"))
shape: (3, 1)
┌───────┐
│ any │
│ --- │
│ bool │
╞═══════╡
│ false │
│ true │
│ true │
└───────┘
>>> df.select(pl.any(pl.all() == "?").any())
shape: (1, 1)
┌──────┐
│ any │
│ --- │
│ bool │
╞══════╡
│ true │
└──────┘
Я думаю, что одна вещь, которая может сделать это более запутанным, заключается в том, что вы не делаете все в контексте выбора. Другими словами, не делайте этого: (pl_df == "?")
Первое, что мы можем сделать, это
pl_df.select(pl.all()= = "?")
shape: (3, 2)
┌───────┬───────┐
│ A ┆ B │
│ --- ┆ --- │
│ bool ┆ bool │
╞═══════╪═══════╡
│ false ┆ false │
│ false ┆ true │
│ true ┆ false │
└───────┴───────┘
Когда мы называем pl.all(), это означает все столбцы. Для каждого столбца мы преобразовываем его исходное значение в логическое значение того, равно ли оно ?
Теперь давайте сделаем это:
pl_df.select((pl.all()= = "?").any())
shape: (1, 2)
┌──────┬──────┐
│ A ┆ B │
│ --- ┆ --- │
│ bool ┆ bool │
╞══════╪══════╡
│ true ┆ true │
└──────┴──────┘
Это дает вам значение для каждого столбца. Все, что мы сделали, это добавили .any, что говорит о том, что если что-то в скобках, предшествующих этому, истинно, то вернуть True.
Теперь давайте сделаем
pl_df.select(pl.any(pl.all()= = "?"))
shape: (3, 1)
┌───────┐
│ any │
│ --- │
│ bool │
╞═══════╡
│ false │
│ true │
│ true │
└───────┘
Когда мы вызываем pl.any(...), он будет делать это построчно для любого ....
В конце концов, если мы сложим их вместе...
pl_df.select((pl.any(pl.all()= = "?")).any())
shape: (1, 1)
┌──────┐
│ any │
│ --- │
│ bool │
╞══════╡
│ true │
└──────┘
затем мы получаем единственное значение, указывающее, что где-то в фрейме данных есть элемент, равный "?"
Мы должны добавить это в документацию.
Большое спасибо! Думаю, меня сбил с толку раздел руководства пользователя о построчных вычислениях (pola-rs.github.io/polars-book/user-guide/dsl/list_context.html). Так что я тоже согласен с Игорем :)
Мы должны добавить это в документацию.