在创建新计算时基于从另一列获取第一个值的总和



我希望得到一些帮助与计算我有点挣扎。我正在处理一些数据(下面复制),我需要创建一个计算,需要第一个值>从另一列中取出0,并基于该值计算一个新的序列,然后将这些数字聚合起来,得到一个累积和。我的原始数据如下所示:

d = {'Final Account': ['A', 'A', 'A' ,'A' , 'A', 'A', 'A','A' ,'A' ,'A', 'A', 'A', 'A'], 
'Date': ['Jun-21','Jul-21','Aug-21','Sep-21','Oct-21','Nov-21','Dec-21','Jan-22','Feb-22','Mar-22','Apr-22','May-22','Jun-22'],
'Units':[0, 0, 0, 0, 10, 0, 20, 0, 0, 7, 12, 35, 0]}
df = pd.DataFrame(data=d)
Account Date    Units
A       Jun-21  0
A       Jul-21  0
A       Aug-21  0
A       Sep-21  0
A       Oct-21  10
A       Nov-21  0
A       Dec-21  20
A       Jan-22  0
A       Feb-22  0
A       Mar-22  7
A       Apr-22  12
A       May-22  35
A       Jun-22  0

对于表,我对我的数据进行初始转换,这是:

df['Conv'] = df['Units'].apply(x/5)

在表中添加一个新列,如下所示:

Account  Date    Units   Conv
A        Jun-21  0       0
A        Jul-21  0       0
A        Aug-21  0       0
A        Sep-21  0       0
A        Oct-21  10      2
A        Nov-21  0       0 
A        Dec-21  20      4 
A        Jan-22  0       0
A        Feb-22  0       0
A        Mar-22  7       1
A        Apr-22  12      2
A        May-22  35      7
A        Jun-22  0       0

在这之后的步骤我开始遇到问题。我需要计算新字段,它取conv字段的第一个值>0,在相同的索引位置,并根据前一行的总和开始新的计算,然后在计算之后将其添加回总和。在python之外,这是通过创建两个列来完成的。一个计算新单位:

(Units - (previous row cumsum of existing units * 2))/5

则现有单位,即已算出的新单位的值的总和。期望的输出应该像这样:

Account  Date    Units   Conv  New Units  Existing Units (cumsum of new units)
A        Jun-21  0       0     0          0
A        Jul-21  0       0     0          0
A        Aug-21  0       0     0          0
A        Sep-21  0       0     0          0 
A        Oct-21  10      2     2          2 
A        Nov-21  0       0     0          2
A        Dec-21  20      4     3          5
A        Jan-22  0       0     0          5
A        Feb-22  0       0     0          5
A        Mar-22  7       1     0          5
A        Apr-22  12      2     0          5
A        May-22  35      7     5          10
A        Jun-22  0       0     0          10

我正在努力解决的主要问题是从"Conv"中抓取第一个值>0。列,并能够基于可应用于"新单位"的初始值创建新的总和。计算。任何指导都是非常感激的,尽管阅读了很多,我还是碰到了一点砖墙!如果你需要我更好地解释,请问!:)

提前感谢!

我不确定我是否完全理解你想要达到的目的。尽管如此,这里还是尝试重现您的预期结果。对于您的示例框架

groups = (df['Units'].eq(0) & df['Units'].shift().ne(0)).cumsum()
df['New Units'] = 0
last = 0
for _, group in df['Units'].groupby(groups):
i, unit = group.index[-1], group.iloc[-1]
if unit != 0:
new_unit = (unit - last * 2) // 5
last = df.at[i, 'New Units'] = new_unit

确实导致

Final Account    Date  Units  New Units
0              A  Jun-21      0          0
1              A  Jul-21      0          0
2              A  Aug-21      0          0
3              A  Sep-21      0          0
4              A  Oct-21     10          2
5              A  Nov-21      0          0
6              A  Dec-21     20          3
7              A  Jan-22      0          0
8              A  Feb-22      0          0
9              A  Mar-22      7          0
10             A  Apr-22     12          0
11             A  May-22     35          5
12             A  Jun-22      0          0

第一步确定Units列中最后一项与构建新单元相关的块:连续的零,然后是非零,直到第一个零。这个

groups = (df['Units'].eq(0) & df['Units'].shift().ne(0)).cumsum()

在搜索结果

0     1
1     1
2     1
3     1
4     1
5     2
6     2
7     3
8     3
9     3
10    3
11    3
12    4

然后将列Units沿着这些块分组,如果每个块是非零(零只能发生在最后一个块中),抓住最后一个项目,构建新单元(根据给定的公式)并将其存储在新列New Units中。

(如果您确实需要Existing Units列,那么只需在New Units列上使用.cumsum()。)


如果有多个帐户(在评论中指出),那么将过程分别应用于每个帐户的一种方法是将其打包到函数中(这里是new_units),.groupby()Final Account列上,.apply()将函数打包到组中:

def new_units(sdf):
groups = (sdf['Units'].eq(0) & sdf['Units'].shift().ne(0)).cumsum()
last = 0
for _, group in sdf['Units'].groupby(groups):
i, unit = group.index[-1], group.iloc[-1]
if unit != 0:
new_unit = (unit - last * 2) // 5
last = sdf.at[i, 'New Units'] = new_unit
return sdf
df['New Units'] = 0
df = df.groupby('Final Account').apply(new_units)

尝试使用for循环来执行您提供的示例计算

# initialize new rows to zero
df['new u'] = 0
df['ext u'] = 0
# set first row cumsum
df['ext u'][0] = df['units'][0]//5
# loop through the data frame to perform the calculations
for i in range(1, len(df)):
# calculate new units
df['new u'][i] = (df['units'][i]-2*df['ext u'][i-1])//5
# calculate existing units
df['ext u'][i] = df['ext u'][i-1] + df['new u']

我不确定这些是你正在寻找的确切的表达式,但希望这能让你找到解决方案。值得注意的是,这并没有处理整个"第一值"。0";事情是因为(请随意纠正我,但是)似乎之前你只是在加零,这不会影响任何事情。希望这对你有帮助!