【问题标题】:Recursive apply over DataFrame Groups causing reindex error递归应用于 DataFrame Groups 导致重新索引错误
【发布时间】: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


    【解决方案1】:

    递归逻辑中的愚蠢错误:两个 f(g) 的分支都必须返回一个组。

    以下代码有效:

    def f(g):
        allocated = g['allocation'].sum()
        unitsLeft = unitsToAllocate - allocated
        if unitsLeft > 0:
            g['spaceLeft'] = g['limit'] - g['allocation']
            quantum = g[g['spaceLeft'] > 0]['spaceLeft'].min()
            alloc = min(unitsLeft / g[g['spaceLeft'] > 0]['spaceLeft'].count(), quantum)
            g.loc[g['spaceLeft'] > 0, 'allocation'] = g[g['spaceLeft'] > 0]['allocation'] + alloc
            return f(g)  # <-- FIXED THIS LINE
        else:
            return g
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-15
      • 1970-01-01
      • 1970-01-01
      • 2022-12-14
      • 1970-01-01
      • 1970-01-01
      • 2017-08-31
      • 1970-01-01
      相关资源
      最近更新 更多