如何使用 Pandas Rolling 显示列值随着时间的推移而降低?

How do you show a column value degrading over time with Pandas Rolling?

我有一个未来预测值的数据框,我想显示它随着时间的推移减少了指定的数量。

我想从这里开始:

Group   Period  Value

A   1/1/2020    4.3

A   2/1/2020

A   3/1/2020

A   4/1/2020

A   5/1/2020

A   6/1/2020

A   7/1/2020

A   8/1/2020

A   9/1/2020

B   1/1/2020    6.5

B   2/1/2020

B   3/1/2020

B   4/1/2020

B   5/1/2020

B   6/1/2020

B   7/1/2020

B   8/1/2020

B   9/1/2020    

为此:

Group   Period  Value

A   1/1/2020    4.3

A   2/1/2020    3.3

A   3/1/2020    2.3

A   4/1/2020    1.3

A   5/1/2020    0.3

A   6/1/2020    0

A   7/1/2020    0

A   8/1/2020    0

A   9/1/2020    0

B   1/1/2020    6.5

B   2/1/2020    5.5

B   3/1/2020    4.5

B   4/1/2020    3.5

B   5/1/2020    2.5

B   6/1/2020    1.5

B   7/1/2020    0.5

B   8/1/2020    0

B   9/1/2020    0

我已经使用起始位置的值创建了数据框(在本例中为 1/1/2020)。

有一次尝试。见下文。

group = df2.groupby(['region', 'site', 'product_ID'], as_index=False)

df2['Projected_S'] = group['Projected_S'].rolling(window=1).apply(lambda x: x.shift(1)-1)

IIUC,使用类似的东西:

f=lambda x: np.where(x.ffill()-x.ffill().expanding().count()<0
                 ,0,x.ffill()-x.ffill().expanding().count())
df.Value=df.groupby(df.Value.notna().cumsum())['Value'].transform(f)
print(df)

   Group    Period  Value
0      A  1/1/2020    3.3
1      A  2/1/2020    2.3
2      A  3/1/2020    1.3
3      A  4/1/2020    0.3
4      A  5/1/2020    0.0
5      A  6/1/2020    0.0
6      A  7/1/2020    0.0
7      A  8/1/2020    0.0
8      A  9/1/2020    0.0
9      B  1/1/2020    5.5
10     B  2/1/2020    4.5
11     B  3/1/2020    3.5
12     B  4/1/2020    2.5
13     B  5/1/2020    1.5
14     B  6/1/2020    0.5
15     B  7/1/2020    0.0
16     B  8/1/2020    0.0
17     B  9/1/2020    0.0

说明df.Value.notna().cumsum() 从具有下一个有效值条目的行开始创建组。然后我们使用 .ffill() 向下填充值。然后使用 expanding() 我们计算计数,所以基本上它用扩展计数减去该值。

最后使用 np.where() 检查哪里是负值并将它们替换为 0。:)

我想出了一个解决方案来提醒我 Excel 的日子,那时候我曾经使用过很多辅助列(只是在 hehehe 之后删除它们)。 假设您知道起始位置,并且数据框的结构如您在问题中所述,则以下过程有效:

  1. 确保日期信息正确转换为日期对象

  2. 在由组名称和日期组成的数据框中设置多索引

  3. 计算每组的元素个数

  4. 创建一个辅助数组,其中包含您希望减少的重复值,重复次数与每组中元素的数量一样多,称之为 A

  5. 用要减去的数量创建另一个数组,命名为 B

  6. C = A - B

  7. 将负值替换为 0

  8. 为相关列分配新值
    这是代码:

    将 numpy 导入为 np 将 pandas 导入为 pd 将日期时间导入为 dt

    强制转换为日期对象

    def date_converter(x): returndt.datetime.strptime(x, "%m/%d/%Y")

    测试[“期间”] = 测试[“期间”].apply(date_converter) test.set_index(["组", "期间"], inplace=True) starting_pos = "01-01-2020" forecast_col = "值"

    获取群组名称

    u = test.index.unique(0).tolist()

    获取所有组的所有实例

    f = test.index.get_level_values(0).tolist() 一个= [] B = [] 对于你中的元素: # 查询要减的值 value = float(test.loc[(element, starting_pos), forecast_col]) # 计算每组有多少个元素 x = f.count(元素) # 重复值 x 次 y = [值]*x # 将重复添加到全局结果 A = A + 是 # 创建要用 len(x) 减去的数组 B = B + [n for n in range(x)] to_zero = λ x: np.where(x < 0, 0, x) C = pd.Series(np.array(A) - np.array(B)).应用(to_zero) test.loc[:,"价值"] = C.values 测试
    虽然 已经发布了答案,但我只是想提供另一个选项,我认为更简单但可以完成工作。我让你做性能比较。