Python Pandas:基于另一列上一行值的条件总和
我想对一列求和,但求和前每行的值必须与另一列的值进行检查,如果另一列的值较小,则该值相加,而不是第一列的前一行。考虑这个数据框:Python Pandas:基于另一列上一行值的条件总和,python,pandas,conditional-statements,cumsum,Python,Pandas,Conditional Statements,Cumsum,我想对一列求和,但求和前每行的值必须与另一列的值进行检查,如果另一列的值较小,则该值相加,而不是第一列的前一行。考虑这个数据框: df = pd.DataFrame({'X': [0,1,0,1,1,0,0,0,0,1,1,1,0,1], 'Y': [0, 0, 1, 1, 1, 2, 3, 4, 4, 4, 4, 4, 5, 5]}) X Y 0 0 0 1 1 0 2 0 1 3 1 1 4 1 1 5 0 2 6 0 3
df = pd.DataFrame({'X': [0,1,0,1,1,0,0,0,0,1,1,1,0,1], 'Y': [0, 0, 1, 1, 1, 2, 3, 4, 4, 4, 4, 4, 5, 5]})
X Y
0 0 0
1 1 0
2 0 1
3 1 1
4 1 1
5 0 2
6 0 3
7 0 4
8 0 4
9 1 4
10 1 4
11 1 4
12 0 5
13 1 5
现在,我想求和X,但是如果Y小于前一行中的X,它将相加而不是X。例如,X的第二行的和结果是1,但是因为Y的第二行中的0小于1,我们将替换它。那么第三行的总和将是0而不是1。
我使用“for loop”编写了如下代码,但对于大型数据集来说,它根本没有效率:
df['Z'] = 0
for index in range(1,len(df)):
df.loc[index, 'Z'] = min(df.loc[index, 'X']+df.loc[index-1, 'Z'], df.loc[index, 'Y'])
Z的预期结果是:
X Y Z
0 0 0 0
1 1 0 0
2 0 1 0
3 1 1 1
4 1 1 1
5 0 2 1
6 0 3 1
7 0 4 1
8 0 4 1
9 1 4 2
10 1 4 3
11 1 4 4
12 0 5 4
13 1 5 5
如果有人能建议一种更有效的方法,我将不胜感激。由于您的“专业化cumsum”的结果取决于之前的结果,
不能使用实际的累积和函数
相反,你应该使用一个“带记忆”的函数(记住
上一个返回值)并在下一次调用中使用它(对于
下一行)
第0行是一种特殊情况。因为对于第0行,没有以前的
Z列的值,即使在代码中,您也为
第一行为0,所以我在函数中也做了同样的操作(见下文)
其他行将根据您的算法进行计算
要计算“专用总和”,请定义以下函数:
def myCumSum(row):
if row.name == 0:
myCumSum.prev = 0
else:
myCumSum.prev = min(row.X + myCumSum.prev, row.Y)
return myCumSum.prev
关于row.name的一点解释:它实际上是
当前行和我的解决方案依赖于源数据帧
具有默认索引,即从0开始的连续数字
然后将其应用于每一行,并将结果保存在新列(Z)中:
结果是:
X Y Z
0 0 0 0
1 1 0 0
2 0 1 0
3 1 1 1
4 1 1 1
5 0 2 1
6 0 3 1
7 0 4 1
8 0 4 1
9 1 4 2
10 1 4 3
11 1 4 4
12 0 5 4
13 1 5 5
由于您的“专用累计”结果取决于之前的结果,
不能使用实际的累积和函数
相反,你应该使用一个“带记忆”的函数(记住
上一个返回值)并在下一次调用中使用它(对于
下一行)
第0行是一种特殊情况。因为对于第0行,没有以前的
Z列的值,即使在代码中,您也为
第一行为0,所以我在函数中也做了同样的操作(见下文)
其他行将根据您的算法进行计算
要计算“专用总和”,请定义以下函数:
def myCumSum(row):
if row.name == 0:
myCumSum.prev = 0
else:
myCumSum.prev = min(row.X + myCumSum.prev, row.Y)
return myCumSum.prev
关于row.name的一点解释:它实际上是
当前行和我的解决方案依赖于源数据帧
具有默认索引,即从0开始的连续数字
然后将其应用于每一行,并将结果保存在新列(Z)中:
结果是:
X Y Z
0 0 0 0
1 1 0 0
2 0 1 0
3 1 1 1
4 1 1 1
5 0 2 1
6 0 3 1
7 0 4 1
8 0 4 1
9 1 4 2
10 1 4 3
11 1 4 4
12 0 5 4
13 1 5 5