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

问题描述 投票:1回答:2

我有一个未来预测值的数据框,我想要显示一个特定数量的时间减少。

我想离开这个:

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)
python pandas rolling-computation
2个回答
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. :)


0
投票

我想出了一个解决方案提醒我的Excel日子,当时我常常使用很多辅助列(仅在hehehe之后删除它们)。假设您知道起始位置,并且数据框的结构如您在问题中所述,则以下过程有效: 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已经发布了答案,但我只是想给出另一种选择,我认为这样做更简单但是可以做到这一点。我让你做性能比较。如果这有助于你,请告诉我。

© www.soinside.com 2019 - 2024. All rights reserved.