Python 如何通过滚动显示随时间而降低的列值?
我有一个未来预测值的数据框,我想显示随着时间的推移,该值会减少指定的数量 我想从这里开始:Python 如何通过滚动显示随时间而降低的列值?,python,pandas,rolling-computation,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
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)
说明:
df.Value.notna().cumsum()
创建从具有下一个有效值的条目的行开始的组。然后我们使用.ffill()
向下填充值。然后使用expansing()
我们计算计数,因此基本上它用扩展计数减去值
最后使用
np.where()
检查何处为负值,并将其替换为0.:) 我想出了一个解决方案来提醒我的Excel时代,当时我使用了很多helper列(只在呵呵之后删除它们)。
假设您知道起始位置,并且数据帧的结构如您在问题中所述,则以下过程有效: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
将numpy导入为np
作为pd进口熊猫
将日期时间导入为dt
#强制转换为日期对象
def date_转换器(x):
返回dt.datetime.strtime(x,“%m/%d/%Y”)
测试[“期间”]=测试[“期间”]。应用(日期)
test.set_索引([“组”、“期间”],inplace=True)
启动\u pos=“01-01-2020”
预测值
#获取组的名称
u=test.index.unique(0.tolist())
#获取所有组的所有实例
f=test.index.get_level_值(0).tolist()
A=[]
B=[]
对于u中的元素:
#查询要减少的值
值=浮动(test.loc[(元素、起始位置、预测列])
#计算每个组有多少个元素
x=f.计数(元素)
#重复值x次
y=[值]*x
#将重复添加到全局结果
A=A+y
#创建要用len(x)减去的数组
B=B+[n表示范围(x)内的n]
to_zero=λx:np.式中(x<0,0,x)
C=pd.系列(np.数组(A)-np.数组(B))。适用于(零)
test.loc[:,“Value”]=C.values
测试
虽然AcKYY91已经发布了一个答案,我只是想给出另一个选择,我认为更简单,但可以做这项工作。我让你做性能比较。如果这对您有帮助,请告诉我。您事先知道起始位置吗?我知道。我的代码让我在投影中填充了第一个条目。这是什么样的黑魔法?完全有效,但我不能说我理解你在这里做了什么。谢谢大家!@问号(我添加了一些解释):干杯
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