Dado um dataframe polar, quero extrair todas as linhas duplicadas e também aplicar uma condição de filtro adicional, por exemplo:
import polars as pl
df = pl.DataFrame({
"name": ["Alice", "Bob", "Alice", "David", "Eve", "Bob", "Frank"],
"city": ["NY", "LA", "NY", "SF", "LA", "LA", "NY"],
"age": [25, 30, 25, 35, 28, 30, 40]
})
# Trying this:
df.filter((df.is_duplicated()) & (pl.col("city") == "NY")) # error
Entretanto, isso resulta em um erro:
SchemaError: não é possível descompactar séries de tipos
object
embool
O que faz alusão que df.is_duplicated()
retorna uma série do tipo object
, mas na realidade, é uma Boolean
Series.
Surpreendentemente, reordenar os predicados colocando a expressão primeiro faz com que funcione ( mas por quê? ):
df.filter((pl.col("city") == "NY") & (df.is_duplicated())) # works!
gera corretamente:
shape: (2, 3)
┌───────┬──────┬─────┐
│ name ┆ city ┆ age │
│ --- ┆ --- ┆ --- │
│ str ┆ str ┆ i64 │
╞═══════╪══════╪═════╡
│ Alice ┆ NY ┆ 25 │
│ Alice ┆ NY ┆ 25 │
└───────┴──────┴─────┘
Entendo que a abordagem ideal ao filtrar duplicatas com base em um subconjunto de colunas é usar pl.struct
, como:
df.filter((pl.struct(df.columns).is_duplicated()) & (pl.col("city") == "NY")) # works
O que funciona bem com a condição de filtro adicional.
No entanto, não estou usando intencionalmente pl.struct
porque meu dataframe real tem 40 colunas e quero verificar se há linhas duplicadas com base em todas as colunas, exceto três, então fiz o seguinte:
df.filter(df.drop("col1", "col2", "col3").is_duplicated())
O que funciona bem e é muito mais conveniente do que escrever todas as 37 colunas em um arquivo pl.struct
. No entanto, isso falha ao adicionar uma condição de filtro adicional à direita, mas não à esquerda :
df.filter(
(df.drop("col1", "col2", "col3").is_duplicated()) & (pl.col("col5") == "something")
) # breaks!
df.filter(
(pl.col("col5") == "something") & (df.drop("col1", "col2", "col3").is_duplicated())
) # works!
Por que a ordem dos predicados (Série e Expressão vs. Expressão e Série) importa.filter()
neste caso? Esse é um comportamento intencional em Polars ou um bug?