如何为这个在每个阶段都有移动平均线的 df 创建一个 while 循环?

How do I create a while loop for this df that has moving average in every stage?

所以我想通过查看平均销售额来确定给谁发货。

这是我的数据框:

ID   STOREID    BAL       SALES   SHIP
1     STR1      50        5       18
1     STR2      6         7       18
1     STR3      74        4       18
2     STR1      35        3       500
2     STR2      5         4       500
2     STR3      54        7       500

当 SHIP(按 ID 分组)大于 0 时,计算 AVG (BAL/SALES),每组的最低 AVG 为其 BAL 列 +1,最终列 +1。然后重复这个过程,直到 SHIP 为 0。每个阶段的 AVG 都会不同,这就是为什么我希望它是一个 while 循环。

第一轮的示例输出如下。所以这样做直到 SHIP 为 0 并且每个 ID 的最终总和为 = 到 SHIP:

ID   STOREID   BAL   SALES  SHIP   AVG        Final
1    STR1      50    5      18     10         0
1    STR2      6     4      18     1.5        1
1    STR3      8     4      18     2          0
2    STR1      35    3      500    11.67      0
2    STR2      5     4      500    1.25       1
2    STR3      54    7      500    7.71       0

我在 SQL 中尝试了几种方法,我认为在 python 中这样做会更好,但我的循环做得不好。到目前为止,这是我尝试过的:

df['AVG'] = 0
df['FINAL'] = 0

for i in df.groupby(["ID"])['SHIP']:
    if i > 0:
          df['AVG'] = df['BAL'] / df['SALES']
          df['SHIP'] = df.groupby(["ID"])['SHIP']-1
          total = df.groupby(["ID"])["FINAL"].transform("cumsum")
          df['FINAL'] = + 1
          df['A'] = + 1
    else:
         df['FINAL'] = 0

这很有挑战性,因为组中不止一行可以有相同的平均计算。然后它抛出分配。

如果我理解正确的话,这适用于示例数据框。

d = {'ID': [1, 1, 1, 2,2,2], 'STOREID': ['str1', 'str2', 'str3','str1', 'str2', 'str3'],'BAL':[50, 6, 74, 35,5,54], 'SALES': [5, 7, 4, 3,4,7], 'SHIP': [18, 18, 18, 500,500,500]} 
df = pd.DataFrame(data=d)
df['AVG'] = 0
df['FINAL'] = 0

def calc_something(x):
    # print(x.iloc[0]['SHIP'])
    for i in range(x.iloc[0]['SHIP'])[0:500]:
          x['AVG'] = x['BAL'] / x['SALES']
          x['SHIP'] = x['SHIP']-1
          x = x.sort_values('AVG').reset_index(drop=True)
          # print(x.iloc[0, 2])
          x.iloc[0, 2] = x['BAL'][0] + 1
          x.iloc[0, 6] = x['FINAL'][0] + 1
    return x

df_final = df.groupby('ID').apply(calc_something).reset_index(drop=True).sort_values(['ID', 'STOREID'])
df_final

   ID STOREID  BAL  SALES  SHIP    AVG  FINAL
1   1    STR1   50      5     0 10.000      0
0   1    STR2   24      7     0  3.286     18
2   1    STR3   74      4     0 18.500      0
4   2    STR1  127      3     0 42.333     92
5   2    STR2  170      4     0 42.500    165
3   2    STR3  297      7     0 42.286    243