Python 3.x 如何通过每日重置有条件地累积一行

Python 3.x 如何通过每日重置有条件地累积一行,python-3.x,pandas,Python 3.x,Pandas,我有一只熊猫df看起来像这样: price quantity initiator time 2016-07-13 16:19:31 6.20 8000 B 2016-07-13 16:19:45 6.19 5176 S 2016-07-13 16:25:08 6.24 15000 Na

我有一只熊猫
df
看起来像这样:

                    price  quantity initiator
time                                          
2016-07-13 16:19:31   6.20      8000         B
2016-07-13 16:19:45   6.19      5176         S
2016-07-13 16:25:08   6.24     15000         NaN
2016-07-13 16:25:08   6.24      2847         S
2016-07-13 16:25:08   6.24     39829         B
2016-07-13 16:25:08   6.24      2398         B
2016-07-13 16:25:08   6.24      1844         NaN
2016-07-13 16:25:08   6.24      9538         S
2016-07-13 16:25:08   6.24       459         B
2016-07-13 16:25:08   6.24      1082         B
我想添加一个包含累计数量的列,它每天从零开始。条件是,如果启动器为B,则数量为正;如果为S,则数量为负;如果为NaN,则数量不计算

因此,根据上述数据,我的新专栏将如下所示:

acc_quantity
8000
2824
2824
337
40166
42564
42564
33026
33485
34567

您在概念上是如何做到这一点的?

使用
np.where
notnull
创建
[-1,0,1]
系列。将此系列乘以
df.quantity
并使用
cumsum

我们将构建一个函数来执行上述操作,并将其应用于按天分组的
groupby

import pandas as pd
import numpy as np
from StringIO import StringIO

text = """time       price  quantity  initiator
2016-07-13 16:19:31   6.20      8000         B
2016-07-13 16:19:45   6.19      5176         S
2016-07-13 16:25:08   6.24     15000         NaN
2016-07-13 16:25:08   6.24      2847         S
2016-07-13 16:25:08   6.24     39829         B
2016-07-13 16:25:08   6.24      2398         B
2016-07-13 16:25:08   6.24      1844         NaN
2016-07-13 16:25:08   6.24      9538         S
2016-07-13 16:25:08   6.24       459         B
2016-07-13 16:25:08   6.24      1082         B
2016-07-14 16:19:31   6.20      8000         B
2016-07-14 16:19:45   6.19      5176         S
2016-07-14 16:25:08   6.24     15000         NaN
2016-07-14 16:25:08   6.24      2847         S
2016-07-14 16:25:08   6.24     39829         B
2016-07-14 16:25:08   6.24      2398         B
2016-07-14 16:25:08   6.24      1844         NaN
2016-07-14 16:25:08   6.24      9538         S
2016-07-14 16:25:08   6.24       459         B
2016-07-14 16:25:08   6.24      1082         B"""

df = pd.read_csv(StringIO(text), sep='\s{2,}', engine='python', index_col=0, parse_dates=[0])

def accumulator(df):
    initiator = np.where(df.initiator == 'B', 1, -1) * df.initiator.notnull()
    return pd.DataFrame((df.quantity * initiator).cumsum(), df.index, ['acc_quantity'])

pd.concat([df, df.groupby(df.index.strftime('%Y-%m-%d')).apply(accumulator)], axis=1)
请注意这些值在新的一天开始时重置


太好了,干杯。每天将acc_数量重置为零怎么样?有什么想法吗?@cJc更新帖子。做得好!我忘了提到我的数据是以pandas数据框的形式出现的,首先使用pandas导入文件。我不熟悉StringIO,当我在df上运行代码而不是像您在示例中使用的文本字符串时,会收到一条错误消息。我该如何解决这个问题?@cJc
StringIO
模拟文件。当我阅读课文时,我会使用
pd.read\u csv
功能做出很多决定
sep='\s{2,}'
表示将2个或更多空白字符视为列分隔符
index\u col=0
表示第一列是索引
parse_dates=[0]
说第一列也应该被解析为datetime/timestamp。您看到的错误很可能是由于文件格式不同,以及未能以我所做的方式进行解析。或者您没有复制我使用过的相同参数。我猜文件格式不同。我可以将StringIO与数据帧一起使用,还是必须以不同的方式解决它?