Atualmente estou "convertendo" de pandas para polares porque gosto muito da API. Esta pergunta é uma pergunta mais geral para uma pergunta anterior minha (veja aqui )
Eu tenho o seguinte dataframe
# Dummy data
df = pl.DataFrame({
"Buy_Signal": [1, 0, 1, 0, 1, 0, 0],
"Returns": [0.01, 0.02, 0.03, 0.02, 0.01, 0.00, -0.01],
})
Em última análise, quero fazer agregações na coluna Returns
condicionais a intervalos diferentes - que são dados por column Buy_Signal
. No caso acima, o comprimento é de 1 até o final do dataframe. O dataframe resultante deve, portanto, ter a seguinte aparência
| group | Returns |
|------: |--------: |
| u32 | f64 |
| 1 | 0.01 |
| 1 | 0.02 |
| 1 | 0.03 |
| 1 | 0.02 |
| 1 | 0.01 |
| 1 | 0.0 |
| 1 | -0.01 |
| 2 | 0.03 |
| 2 | 0.02 |
| 2 | 0.01 |
| 2 | 0.0 |
| 2 | -0.01 |
| 3 | 0.01 |
| 3 | 0.0 |
| 3 | -0.01 |
Uma abordagem postada como resposta à minha pergunta anterior é a seguinte:
# Build overlapping group index
idx = df.select(index=
pl.when(pl.col("Buy_Signal") == 1)
.then(pl.int_ranges(pl.int_range(pl.len()), pl.len() ))
).explode(pl.col("index")).drop_nulls().cast(pl.UInt32)
# Join index with original data
df = (df.with_row_index()
.join(idx, on="index")
.with_columns(group = (pl.col("index") == pl.col("index").max())
.shift().cum_sum().backward_fill() + 1)
.select(["group", "Returns"])
)
df
Pergunta: existem outras boas soluções para este problema.
Com bom quero dizer (i) legível e/ou (ii) rápido.
Meu problema real contém conjuntos de dados muito maiores.
Obrigado
Para completar, aqui está uma solução alternativa que não depende de funcionalidade experimental.
Saída.
Eu acho que é um bom caso para uso de
cumulative_eval()
.À primeira vista, você precisa ter 2 passagens no seu DataFrame. Primeiro, você precisa calcular
cum_sum
para acertar o agrupamento:Observe que atualmente nosso DataFrame está classificado com
descending=True
, isso é importante, pois queremos que nossas listas sejam agregadas do maior grupo para o menor.E agora
cumulative_eval()
, junto comimplode()
:Você pode ver que o resultado corresponde ao que você esperaria. No entanto, você deve ter cuidado com o desempenho, pois há uma observação na
cumulative_eval
documentação:Apenas para adicionar mais algumas informações, pois acho que o título da pergunta é baseado na minha redação anterior:
Encontrei uma definição existente do problema (qual pode ser um título melhor para a pergunta?)
Um Polars equivalente ao
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
enquadramento de janela do SQL.por exemplo, usando DuckDB para demonstrar: