Polars noob, dado um m x n
dataframe Polars df
e um 1 x n
dataframe Polars de escalares, quero dividir cada coluna df
pelo escalar correspondente no outro quadro.
import numpy as np
import polars as pl
cols = list('abc')
df = pl.DataFrame(np.linspace(1, 9, 9).reshape(3, 3),
schema=cols)
scalars = pl.DataFrame(np.linspace(1, 3, 3)[:, None],
schema=cols)
In [13]: df
Out[13]:
shape: (3, 3)
┌─────┬─────┬─────┐
│ a ┆ b ┆ c │
│ --- ┆ --- ┆ --- │
│ f64 ┆ f64 ┆ f64 │
╞═════╪═════╪═════╡
│ 1.0 ┆ 2.0 ┆ 3.0 │
│ 4.0 ┆ 5.0 ┆ 6.0 │
│ 7.0 ┆ 8.0 ┆ 9.0 │
└─────┴─────┴─────┘
In [14]: scalars
Out[14]:
shape: (1, 3)
┌─────┬─────┬─────┐
│ a ┆ b ┆ c │
│ --- ┆ --- ┆ --- │
│ f64 ┆ f64 ┆ f64 │
╞═════╪═════╪═════╡
│ 1.0 ┆ 2.0 ┆ 3.0 │
└─────┴─────┴─────┘
Posso fazer isso facilmente no Pandas, conforme mostrado abaixo, delegando à transmissão NumPy, mas queria saber qual a melhor maneira de fazer isso sem ir e voltar entre as representações Polars/Pandas.
In [16]: df.to_pandas() / scalars.to_numpy()
Out[16]:
a b c
0 1.0 1.0 1.0
1 4.0 2.5 2.0
2 7.0 4.0 3.0
Encontrei esta pergunta semelhante em que a constante escalar já é uma linha no quadro original, mas não vejo como aproveitar uma linha de outro quadro.
O melhor que consegui até agora foi combinar as molduras e fazer algumas... coisas horríveis :D
In [31]: (pl.concat([df, scalars])
...: .with_columns(pl.all() / pl.all().tail(1))
...: .head(-1))
Out[31]:
shape: (3, 3)
┌─────┬─────┬─────┐
│ a ┆ b ┆ c │
│ --- ┆ --- ┆ --- │
│ f64 ┆ f64 ┆ f64 │
╞═════╪═════╪═════╡
│ 1.0 ┆ 1.0 ┆ 1.0 │
│ 4.0 ┆ 2.5 ┆ 2.0 │
│ 7.0 ┆ 4.0 ┆ 3.0 │
└─────┴─────┴─────┘
Acho que você descobriu uma solução única/interessante e inteligente. Considere também apenas iterar nas colunas:
ou
ou
Eu não tinha certeza se isso não seria possível, mas tentei e a aritmética simples realmente funciona, se você colocar os quadros no mesmo formato. Primeiro, use
Expr.repeat_by()
e depoisExpr.list.explode()
liste em linhas:Além disso, aparentemente você pode usar operações aritméticas entre
DataFrame()
eSeries()
, mas parece que você precisatranspose()
antesDataFrame
de fazer isso, porque é feito por colunas (a primeira coluna deDataFrame
é dividida pelo primeiro valor deSeries
e assim por diante):Testei rapidamente o desempenho em DataFrames um pouco maiores e todas as soluções propostas parecem ter velocidade semelhante (na minha máquina):