【发布时间】:2019-06-06 04:08:30
【问题描述】:
我想在每组 DataFrame 上分配一些“单元”,看起来像这样:
limit allocation spaceLeft
Group
A 5.0 0.0 5.0
A 3.0 0.0 3.0
A 7.0 0.0 7.0
B 1.0 0.0 1.0
B 2.0 0.0 2.0
B 4.0 0.0 4.0
B 6.0 0.0 6.0
... 可以通过以下方式创建:
df = pd.DataFrame(data=[('A', 5.0, 0.0),
('A', 3.0, 0.0),
('A', 7.0, 0.0),
('B', 1.0, 0.0),
('B', 2.0, 0.0),
('B', 4.0, 0.0),
('B', 6.0, 0.0)],
columns=('Group', 'limit', 'allocation')).set_index('Group')
df['spaceLeft'] = df['limit'] - df['allocation']
限制是每个组的行内的单元分配必须尽可能统一,但不能超过每行的limit。因此,例如,如果我们有 10 个单元,那么最终正确分配到组 A 将是:
limit allocation spaceLeft
Group
A 5.0 3.5 1.5
A 3.0 3.0 0.0
A 7.0 3.5 3.5
为此我写了一个递归函数:
unitsToAllocate = 10.0
def f(g):
allocated = g['allocation'].sum()
unitsLeft = unitsToAllocate - allocated
if unitsLeft > 0:
g['spaceLeft'] = g['limit'] - g['allocation']
# "Quantum" is the space left in the smallest bin with space remaining
quantum = g[g['spaceLeft'] > 0]['spaceLeft'].min()
# Distribute only as much as will fill next bin to its limit
alloc = min(unitsLeft / g[g['spaceLeft'] > 0]['spaceLeft'].count(), quantum)
g.loc[g['spaceLeft'] > 0, 'allocation'] = g[g['spaceLeft'] > 0]['allocation'] + alloc
f(g)
else:
return g
如果我手动迭代地在单个组上运行内部 f 逻辑,例如 group = df.groupby('Group').get_group('A'),那么它就可以工作。 (即,它会为上面显示的A 生成正确的结果。)
但如果我按照df.groupby('Group').apply(f) 的设计调用f,它会失败:
ValueError: cannot reindex from a duplicate axis.
怎么了?
还有没有更流行的方法来处理这个算法?
【问题讨论】:
标签: python pandas dataframe recursion pandas-groupby