基于Buy和Sell列条件的pandas累计求和实现求助
解决方案
首先,我们不需要用循环,用pandas的向量操作就能高效实现需求。以下是具体步骤:
1. 构造并预处理数据
先把你提供的示例数据转换成pandas DataFrame,同时将空值替换为0(因为空单元格代表没有Buy/Sell信号):
import pandas as pd # 构造示例数据 data = { 'Date': ['01/01/2023', '01/02/2023', '01/03/23', '01/04/23', '01/05/23', '01/06/23'], 'Buy': ['', 1, '', '', '', ''], 'Sell': ['', '', '', '', 1, ''], 'Value': [1, 5, 1, 1, 1, 5] } df = pd.DataFrame(data) # 把空值转为0,统一数据类型 df[['Buy', 'Sell']] = df[['Buy', 'Sell']].fillna(0).astype(int)
2. 标记Buy到Sell的区间
通过累计求和生成一个状态列,标记哪些行处于「Buy信号后到Sell信号」的区间内(包含首尾两行):
# 生成区间状态:True表示在目标区间内 df['in_range'] = (df['Buy'].cumsum() - df['Sell'].shift().fillna(0).cumsum()) > 0
解释:
df['Buy'].cumsum():累计Buy信号的次数,出现1时加1,标记区间开始。df['Sell'].shift().fillna(0).cumsum():将Sell信号下移一行后累计,这样Sell所在的当前行仍会被标记在区间内,满足包含Sell行的要求。- 两者的差值大于0时,说明正处于Buy和Sell之间的区间。
3. 计算区间内的累计求和
基于标记的区间,对Value列进行分组累计求和,非区间的行留空:
# 仅在区间内计算累计和,非区间显示空值 df['Cumulative Sum'] = df.groupby((~df['in_range']).cumsum())['Value'].cumsum().where(df['in_range'], '')
解释:
(~df['in_range']).cumsum():将非区间的行作为分组分隔符,把每个连续的区间分成独立的组。groupby(...).cumsum():在每个区间组内计算累计和。where(df['in_range'], ''):只保留区间内的累计和,非区间行转为空字符串,和你的示例输出一致。
最终结果
执行完上述代码后,输出df[['Date', 'Buy', 'Sell', 'Value', 'Cumulative Sum']]会得到和你示例完全一致的结果:
| Date | Buy | Sell | Value | Cumulative Sum |
|---|---|---|---|---|
| 01/01/2023 | 0 | 0 | 1 | |
| 01/02/2023 | 1 | 0 | 5 | 5 |
| 01/03/23 | 0 | 0 | 1 | 6 |
| 01/04/23 | 0 | 0 | 1 | 7 |
| 01/05/23 | 0 | 1 | 1 | 8 |
| 01/06/23 | 0 | 0 | 5 |
新手技巧与建议
- 避免循环:pandas的向量操作(如
cumsum、groupby)比Python循环效率高得多,尤其是处理大数据量时。 - 巧用cumsum标记状态:累计求和是处理「区间开始/结束」类问题的常用技巧,能快速生成分组或状态标记。
- 先处理空值:明确空值的含义后(比如这里空值代表无信号),先转换为合适的值(如0)再操作,能避免很多逻辑错误。
- 灵活使用where函数:
where可以根据条件选择性保留数据,非常适合这种需要在特定范围内计算的场景。
内容的提问来源于stack exchange,提问作者aaaahhhhhh
相关产品推荐
相关产品推荐

