Python 当条件为真时,测量经过的时间

Python 当条件为真时,测量经过的时间,python,pandas,time-series,Python,Pandas,Time Series,我有以下数据帧: dt binary 2016-01-01 00:00:00 False 2016-01-01 00:00:01 False 2016-01-01 00:00:02 False 2016-01-01 00:00:03 False 2016-01-01 00:00:04 True 2016-01-01 00:00:05 True 2016-01-01 00:00:06 True 2016-01-01 00:00:07 Fals

我有以下数据帧:

                 dt binary
2016-01-01 00:00:00  False
2016-01-01 00:00:01  False
2016-01-01 00:00:02  False
2016-01-01 00:00:03  False
2016-01-01 00:00:04   True
2016-01-01 00:00:05   True
2016-01-01 00:00:06   True
2016-01-01 00:00:07  False
2016-01-01 00:00:08  False
2016-01-01 00:00:09   True
2016-01-01 00:00:10   True
二进制
时,我想对经过的时间求和。我正在分享我的解决方案,它实现了它,但有些东西告诉我应该有一个更简单的方法,因为它是时间序列数据的一个非常基本的功能。请注意,数据很可能是等距的,但我不能相信这一点

df['binary_grp'] = (df.binary.diff(1) != False).astype(int).cumsum()
# Throw away False values
df = df[df.binary]
groupby = df.groupby('binary_grp')
df = pd.DataFrame({'timespan': groupby.dt.last() - groupby.dt.first()})
return df.timespan.sum().seconds / 60.0
最棘手的部分可能是第一行。它所做的,基本上是为每个连续的块分配一个递增的数字。以下是之后数据的外观:

                 dt binary  binary_grp
2016-01-01 00:00:00  False           1
2016-01-01 00:00:01  False           1
2016-01-01 00:00:02  False           1
2016-01-01 00:00:03  False           1
2016-01-01 00:00:04   True           2
2016-01-01 00:00:05   True           2
2016-01-01 00:00:06   True           2
2016-01-01 00:00:07  False           3
2016-01-01 00:00:08  False           3
2016-01-01 00:00:09   True           4
2016-01-01 00:00:10   True           4

有没有更好的方法来实现这一点?我想这段代码性能很好,我担心的是可读性。

我认为您的解决方案很好

另一个解决方案:

将ed值与进行比较,然后按进行分组

过滤完成后,可通过选择以下选项,使用有差异的
apply


在您的解决方案中,如果始终只需要
,则不需要新的
数据帧

groupby = df.groupby('binary_grp')

s = groupby.dt.last() - groupby.dt.first()
all_time =  s.sum().seconds / 60.0
print (all_time)
0.05
但如果需要,可以通过以下方式从
系列
s
创建它:

IIUC:

您希望找到跨越整个序列的时间总和,其中
binary
True

然而,我们必须做出一些选择或假设

                    dt  binary
0  2016-01-01 00:00:00   False
1  2016-01-01 00:00:01   False
2  2016-01-01 00:00:02   False
3  2016-01-01 00:00:03   False
4  2016-01-01 00:00:04    True # <- This where time starts
5  2016-01-01 00:00:05    True
6  2016-01-01 00:00:06    True
7  2016-01-01 00:00:07   False # <- And ends here. So this would
8  2016-01-01 00:00:08   False # be 00:00:07 - 00:00:04 or 3 seconds
9  2016-01-01 00:00:09    True # <- Starts again
10 2016-01-01 00:00:10    True # <- But ends here because
                               # I don't have another Timestamp

然后,我们可以将此概念与
groupby

# Use xor and cumsum to identify change in True to False and False to True
grps = (df.binary ^ df.binary.shift()).cumsum()
mask = df.binary.groupby(grps).first()
df.dt.diff().shift(-1).groupby(grps).sum()[mask]

binary
1   00:00:03
3   00:00:01
Name: dt, dtype: timedelta64[ns]
还是不戴面具

pd.concat([df.dt.diff().shift(-1).groupby(grps).sum(), mask], axis=1)

             dt  binary
binary                 
0      00:00:04   False
1      00:00:03    True
2      00:00:02   False
3      00:00:01    True
df.dt.diff().shift(-1).mul(df.binary).sum()

Timedelta('0 days 00:00:04')
# Use xor and cumsum to identify change in True to False and False to True
grps = (df.binary ^ df.binary.shift()).cumsum()
mask = df.binary.groupby(grps).first()
df.dt.diff().shift(-1).groupby(grps).sum()[mask]

binary
1   00:00:03
3   00:00:01
Name: dt, dtype: timedelta64[ns]
pd.concat([df.dt.diff().shift(-1).groupby(grps).sum(), mask], axis=1)

             dt  binary
binary                 
0      00:00:04   False
1      00:00:03    True
2      00:00:02   False
3      00:00:01    True