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