我有以下数据框:
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
我想对binary
为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
最棘手的部分可能是第一行。它的作用是,它基本上为每个连续的 block 分配一个递增的数字。之后的数据如下所示:
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
有没有更好的方法来实现这一点?我猜这段代码是高性能的,我担心的是可读性。
最佳答案
在我看来,你的解决方案很好。
另一个解决方案:
过滤后可以通过使用iloc
进行选择来使用不同的apply
:
df['binary_grp'] = (df.binary.ne(df.binary.shift())).cumsum()
df = df[df.binary]
s = df.groupby('binary_grp')['dt'].apply(lambda x: x.iloc[-1] - x.iloc[0])
print (s)
binary_grp
2 00:00:02
4 00:00:01
Name: dt, dtype: timedelta64[ns]
all_time = s.sum().seconds / 60.0
print (all_time)
0.05
在您的解决方案中,如果只需要all_time
,则不需要新的DataFrame
:
groupby = df.groupby('binary_grp')
s = groupby.dt.last() - groupby.dt.first()
all_time = s.sum().seconds / 60.0
print (all_time)
0.05
但如果需要,可以通过 to_frame
从 Series
s
创建它:
df1 = s.to_frame('timestamp')
print (df1)
timestamp
binary_grp
2 00:00:02
4 00:00:01
关于python - Pandas 测量条件为真时耗时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44559562/