问题
我正在尝试使给定数据框的所有组都具有相同的大小。在下面的起点中,我展示了一个我想要转换的数据框示例。在目标中,我尝试演示我想要实现的目标。我想按列分组group
,使所有组的大小为4
,并用填充“缺失”值null
- 我希望这很清楚。
我尝试过几种方法,但还是没能解决这个问题。
起点
dfa = pl.DataFrame(data={'group': ['a', 'a', 'a', 'b', 'b', 'c'],
'value': ['a1', 'a2', 'a3', 'b1', 'b2', 'c1']})
┌───────┬───────┐
│ group ┆ value │
│ --- ┆ --- │
│ str ┆ str │
╞═══════╪═══════╡
│ a ┆ a1 │
│ a ┆ a2 │
│ a ┆ a3 │
│ b ┆ b1 │
│ b ┆ b2 │
│ c ┆ c1 │
└───────┴───────┘
目标
>>> make_groups_uniform(dfa, group_by='group', group_size=4)
┌───────┬───────┐
│ group ┆ value │
│ --- ┆ --- │
│ str ┆ str │
╞═══════╪═══════╡
│ a ┆ a1 │
│ a ┆ a2 │
│ a ┆ a3 │
│ a ┆ null │
│ b ┆ b1 │
│ b ┆ b2 │
│ b ┆ null │
│ b ┆ null │
│ c ┆ c1 │
│ c ┆ null │
│ c ┆ null │
│ c ┆ null │
└───────┴───────┘
软件包版本
polars: 1.1.0
解决方案
我根据下面@jqurious 的回答得出了这个结论。
>>> import polars as pl
>>> dfa = pl.DataFrame(data={'group': ['a', 'a', 'a', 'b', 'b', 'c'],
... 'value': ['a1', 'a2', 'a3', 'b1', 'b2', 'c1']})
┌───────┬───────┐
│ group ┆ value │
│ --- ┆ --- │
│ str ┆ str │
╞═══════╪═══════╡
│ a ┆ a1 │
│ a ┆ a2 │
│ a ┆ a3 │
│ b ┆ b1 │
│ b ┆ b2 │
│ c ┆ c1 │
└───────┴───────┘
>>> (dfa
... .with_columns(group_size=pl.col('group')
... .count()
... .over('group')
... .max()
... .explode())
... .group_by('group', maintain_order=True)
... .agg(pl.all()
... .append(pl.repeat(None, pl.col('group_size') - pl.len())))
... .select(pl.exclude('group_size'))
... .explode(pl.exclude('group')))
┌───────┬───────┐
│ group ┆ value │
│ --- ┆ --- │
│ str ┆ str │
╞═══════╪═══════╡
│ a ┆ a1 │
│ a ┆ a2 │
│ a ┆ a3 │
│ b ┆ b1 │
│ b ┆ b2 │
│ b ┆ null │
│ c ┆ c1 │
│ c ┆ null │
│ c ┆ null │
└───────┴───────┘
您可以使用它
pl.repeat()
来生成空值和.append()
它们。☣ 警告 ☣
pl.len()
目前是一个无符号整数(将来可能会改变)我们转换为整数以避免潜在的溢出问题。
您可以使用 找到最大的组
.group_by().len().max()
,然后 groupby 并将组中的每个值转换为结构体,使用'max_width'
策略解除结构体的嵌套,然后融化宽数据。之后,您可以填补最大组和所需组大小之间的差异。运行代码:
你可以通过
groupby
按组列对 df 进行分组来解决这个问题。然后,NULL
如果组 <= 4 ,则用值填充每个组,然后我们在处理后连接所有组pl.concat.
这里有一个代码片段可以指导您。
打印(输出)
这种方法的优点是我们实际上不需要转换原始 DataFrame(除了如果您想重新排列组,可能需要排序),我们只需要创建额外的行并将它们附加到原始 DataFrame 中。
我对答案进行了一些调整,基于您希望组的大小为所有组大小的最大值的假设,但它对于固定的大小也有效
group_size
。group_by()
允许预先group
计算。len()
确定群体的大小。repeat_by()
根据先前计算的组大小和max()
组大小创建列表。explode()
列成列。concat()
返回现有的 DataFrame。sort()
如果您需要各组聚集在一起。如果您需要固定的组大小,那么
repeat()
性能可能会更高,但想法是一样的 - 只生成额外的行并将它们附加回原始 DataFrame。