Python 熊猫:根据条件计算从特定日期开始的时间序列的百分比变化

Python 熊猫:根据条件计算从特定日期开始的时间序列的百分比变化,python,pandas,numpy,Python,Pandas,Numpy,我正在努力用高效后处理的方法来完成以下任务。我有一个时间框架。 基于某种条件,我设置了一个布尔列。之后,我想生成另一列,它是该条件最后一次出现的百分比。例如,在下表中, 行的2、4和5是行1中值的百分比。第6、7和7行是第5行的百分比变化 row date value condition pct_change_from_condition 1 04-27-2010 100 TRUE 2 04-28-2010 200

我正在努力用高效后处理的方法来完成以下任务。我有一个时间框架。 基于某种条件,我设置了一个布尔列。之后,我想生成另一列,它是该条件最后一次出现的百分比。例如,在下表中, 行的2、4和5是行1中值的百分比。第6、7和7行是第5行的百分比变化

row date        value  condition    pct_change_from_condition
1   04-27-2010  100    TRUE             
2   04-28-2010  200                 1.0
4   04-29-2010  300                 2.0
5   04-30-2010  400    TRUE         3.0
6   05-01-2010  500                 0.25
7   05-02-2010  600                 0.5
8   05-03-2010  700                 0.75
我知道我可以重复这些行,然后这样做……但由于这是熊猫,我希望有一种更“流行”和更有效的方式来做……我只是不确定在这里如何做。 感觉上我需要一些条件转换:

df['pct_change_from_condition'] = (df.value - df.shift(df.condition).value)/df.value
或者使用loc:

df['pct_change_from_condition'] = df.value - df.loc[df.condition].value 
当然这些都不起作用,所以我在这里问。。。
感谢您的帮助

一种方法是使用
.groupby()
将运行总和保持为
condition==True
(移位1),并使用该运行总和计算每组的百分比w.r.t相应的参考值。

您可以尝试以下方法:

import numpy as np
import pandas as pd

mask = (df['condition'] == True)
df['group'] = mask.cumsum()
df['first'] = df.groupby(['group'])['value'].transform('first')
df['first'] = np.where(mask, df['first'].shift(), df['first'])
df['pct_change'] = (df['value']-df['first'])/df['first']

# Out[52]: 
# 0     NaN
# 1    1.00
# 2    2.00
# 3    3.00
# 4    0.25
# 5    0.50
# 6    0.75
# Name: pct_change, dtype: float64

我们可以将
条件
列与
进行比较,以创建一个布尔掩码,然后
掩码
列中与该布尔掩码对应的
中的值,然后是
移位
ffill
,以创建一个系列
s
,现在用
s
减去并除以
value
,以计算百分比变化

m = df['condition'].eq('TRUE')
s = df['value'].mask(~m).shift().ffill()
df['% change'] = df['value'].sub(s).div(s)


优雅的解决方案+1,如果您使用:
df['condition'].isna()
并将其插入
.mask
您只有两行,可读性类似。感谢@Andreas的好建议,但我认为只有在
TRUE
之外的
列中没有其他值时,这才有效。例如,如果存在
FALSE
值,则我们必须显式检查
TRUE
值以创建mask@Andreas您的解决方案也很好(+1;)非常简洁!谢谢你跟进这件事,因为我知道:1。面具的用途是什么?在此之前,我不熟悉该功能。它读起来像是我的要求——基于条件的“转移”。2.如果条件列是布尔型的,我假设它也可以工作:df['value'].mask(df.condition).shift().ffill()
         date  value condition  % change
1  04-27-2010    100      TRUE       NaN
2  04-28-2010    200       NaN      1.00
4  04-29-2010    300       NaN      2.00
5  04-30-2010    400      TRUE      3.00
6  05-01-2010    500       NaN      0.25
7  05-02-2010    600       NaN      0.50
8  05-03-2010    700       NaN      0.75