Tenho um conjunto de dados com um esquema como:
df = pl.DataFrame(
{
"target": [
[1.0, 1.0, 0.0],
[1.0, 1.0, 0.1],
[1.0, 1.0, 0.2],
[1.0, 1.0, 0.8],
[1.0, 1.0, 0.9],
[1.0, 1.0, 1.0],
],
"feature": ["a", "b", "c", "d", "e", "f"],
},
schema={
"target": pl.Array(pl.Float32, 3),
"feature": pl.String,
},
)
Se eu fizer um histograma dos valores alvo-z, ele ficará assim:
Quero reamostrar os dados para que fiquem planos ao longo de z.
Consegui fazer isso de uma forma hacky-multi-steps (também muito lenta). Gostaria de saber se as pessoas poderiam sugerir uma forma mais limpa (e mais eficiente)?
O que estou fazendo é:
- Encontre as arestas do compartimento do referido histograma:
bins = 2 # Use e.g. 100 or larger in reality
z = df.select(z=pl.col("target").arr.get(2))
z_min = z.min()
z_max = z.max()
breaks = np.linspace(z_min, z_max, num=bins+1)
- Descubra quantas contagens estão no compartimento com o menor número de contagens:
counts = (
df.with_columns(bin=pl.col("target").arr.get(2).cut(breaks))
.with_columns(counter=pl.int_range(pl.len()).over("bin"))
.group_by("bin")
.agg(pl.col("counter").max())
.filter(pl.col("counter") > 0) # <- Nasty way of filtering the (-inf, min] bin
.select(pl.col("counter").min())
).item()
- Selecione apenas os elementos "count" em cada bin:
df = (
df.with_columns(bin=pl.col("target").arr.get(2).cut(breaks))
.with_columns(counter=pl.int_range(pl.len()).over("bin"))
.filter(pl.col("counter") <= counts)
.select("target", "feature")
)
As pessoas têm alguma sugestão?
Não acho que você possa evitar essas três etapas para reamostragem (embora, dependendo do seu caso de uso, você possa tentar transformar os dados)
Você pode otimizar um pouco esse código,