如何显示“熊猫滚动”随时间推移而降低的列值?

时间:2019-04-18 14:24:55

标签: python pandas rolling-computation

我有一个未来值的数据框,该值希望随时间减少指定数量。

我想从这里出发:

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)

2 个答案:

答案 0 :(得分: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。:)

答案 1 :(得分:0)

当我曾经使用很多帮助器列(只是在删除之后删除它们)时,我想出了一种解决方案,可以提醒我Excel的日子。 假设您知道起始位置,并且数据帧的结构如您在问题中所述,那么以下过程将起作用:
1)确保日期信息已正确转换为日期对象
2)在由组名称和日期组成的数据框中设置多索引
3)计算每个组的元素数
4)创建一个由重复的值组成的帮助器数组,该重复值与每个组中元素的数量一样多,称为A
5)使用您要减去的数量创建另一个数组,将其称为B
6)C = A-B
7)将负值替换为0
8)为相关列分配新值
这是代码:

import numpy as np
import pandas as pd
import datetime as dt

# Enforce conversion to date object
def date_converter(x):
    return dt.datetime.strptime(x, "%m/%d/%Y")


test["Period"] = test["Period"].apply(date_converter)
test.set_index(["Group", "Period"], inplace=True)
starting_pos = "01-01-2020"
forecast_col = "Value"
# Get the names of the groups
u = test.index.unique(0).tolist()
# Get all the instances of all groups
f = test.index.get_level_values(0).tolist()
A = []
B = []
for element in u:
    # Query the value you want to decrease
    value = float(test.loc[(element, starting_pos), forecast_col])
    # Count how many elements there are for each group
    x = f.count(element)
    # Repeat value x times
    y = [value]*x
    # Append repetitions to global result
    A = A + y
    # Create array you want to subtract with len(x)
    B = B + [n for n in range(x)]
to_zero = lambda x: np.where(x < 0, 0, x)
C = pd.Series(np.array(A) - np.array(B)).apply(to_zero)
test.loc[:,"Value"] = C.values
test


尽管anky_91已经发布了答案,但我只想提供另一个选择,我认为它更简单,但可以完成任务。我让你做性能比较。让我知道这是否对您有帮助。