如何将熊猫列中的变量范围与另一列相加

Rod*_*igo 2 dataframe python-3.x pandas

我对熊猫比较陌生,我不知道解决我的问题的最佳方法。好吧,我有一个 df :一个索引,以及一个名为“Data”的列和一个名为“sum”的空列中的数据。

我需要帮助来创建一个函数,以在列“总和”中添加“数据”列的可变行组的总和。分组标准是组中不应有空行。

这里有一个例子:

index  Data Sum
0       1   
1       1   2
2       
3       
4       1   
5       1   
6       1   3
7       
8       1   
9       1   2
10      
11      1   
12      1   
13      1   
14      1   
15      1   5   
16  
17      1   1
18  
19      1   1
20  
Run Code Online (Sandbox Code Playgroud)

如您所见,'Data' 中每组数据的长度是可变的,可以是一行,也可以是任意数量的行。总和必须在组的末尾。例如:“数据”列的第 4、5、6 行组的总和应位于“总和”列的第 6 行。

任何见解将不胜感激。

更新

通过实施ansev建议的方法3解决了该问题。但是由于主程序的变化,每个块的总和,现在需要在每个块的开始处(如果块有多于一行)。然后我使用该df = df.iloc[::-1]指令两次以反转列并再次恢复正常。非常感谢!!!!!

df = df.iloc[::-1]
blocks = df['Data'].isnull().cumsum()
m = blocks.duplicated(keep='last')
df['Sum'] = df.groupby(blocks)['Data'].cumsum().mask(m)
df = df.iloc[::-1]

print(df)

Data  Sum
0    1.0  2.0
1    1.0  NaN
2    NaN  NaN
3    NaN  NaN
4    1.0  3.0
5    1.0  NaN
6    1.0  NaN
7    NaN  NaN
8    1.0  2.0
9    1.0  NaN
10   NaN  NaN
11   1.0  5.0
12   1.0  NaN
13   1.0  NaN
14   1.0  NaN
15   1.0  NaN
16   NaN  NaN
17   1.0  1.0
18   NaN  NaN
19   1.0  1.0
20   NaN  NaN
Run Code Online (Sandbox Code Playgroud)

ans*_*sev 5

我们可以使用GroupBy.cumsum

# if you need replace blanks
#df = df.replace(r'^\s*$', np.nan, regex=True)
s = df['Data'].isnull()
df['sum'] = df.groupby(s.cumsum())['Data'].cumsum().where((~s) & (s.shift(-1)))
print(df)
    index  Data  sum
0       0   1.0  NaN
1       1   1.0  2.0
2       2   NaN  NaN
3       3   NaN  NaN
4       4   1.0  NaN
5       5   1.0  NaN
6       6   1.0  3.0
7       7   NaN  NaN
8       8   1.0  NaN
9       9   1.0  2.0
10     10   NaN  NaN
11     11   1.0  NaN
12     12   1.0  NaN
13     13   1.0  NaN
14     14   1.0  NaN
15     15   1.0  5.0
16     16   NaN  NaN
17     17   1.0  1.0
18     18   NaN  NaN
19     19   1.0  1.0
20     20   NaN  NaN
Run Code Online (Sandbox Code Playgroud)

方法二

#df = df.drop(columns='index') #if neccesary
g = df.reset_index().groupby(df['Data'].isnull().cumsum())
df['sum'] = g['Data'].cumsum().where(lambda x: x.index == g['index'].transform('idxmax'))
Run Code Online (Sandbox Code Playgroud)

方法三

Series.duplicatedSeries.mask

blocks = df['Data'].isnull().cumsum()
m = blocks.duplicated(keep='last')
df['sum'] = df.groupby(blocks)['Data'].cumsum().mask(m)
Run Code Online (Sandbox Code Playgroud)

如您所见,这些方法仅在屏蔽值的方式上有所不同?我们不需要sum列中的值。

我们也可以使用.transform('sum'),而不是.cumsum()

示例数据帧的性能

%%timeit
s = df['Data'].isnull()
df['sum'] = df.groupby(s.cumsum())['Data'].cumsum().where((~s) & (s.shift(-1)))
4.52 ms ± 901 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%%timeit
g = df.reset_index().groupby(df['Data'].isnull().cumsum())
df['sum'] = g['Data'].cumsum().where(lambda x: x.index == g['index'].transform('idxmax'))
8.52 ms ± 1.45 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)

%%timeit
blocks = df['Data'].isnull().cumsum()
m = blocks.duplicated(keep='last')
df['sum'] = df.groupby(blocks)['Data'].cumsum().mask(m)
3.02 ms ± 172 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Run Code Online (Sandbox Code Playgroud)