2017-06-15 23 views
2

我有以下數據框:大熊貓測量經過時間條件爲真時

    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 

我想總結逝去的時候binaryTrue。我分享了我的解決方案,它實現了它,但有些東西告訴我應該有一種更簡單的方法,因爲它是時間序列數據的一個非常基本的特性。請注意,數據很可能是等距的,但我不能依賴這些數據。

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 

有沒有更好的方式來做到這一點?我猜這個代碼是高性能的,我的擔心是可讀性。

回答

2

在我看來你的解決方案很好。

另一種解決方案:

比較shift ED值與ne,由cumsum獲得團體。

過濾後,可以使用apply與差異與iloc選擇:

groupby = df.groupby('binary_grp') 

s = groupby.dt.last() - groupby.dt.first() 
all_time = s.sum().seconds/60.0 
print (all_time) 
0.05 

但如果需要:

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_timeDataFrame是沒有必要的有可能從Seriess通過to_frame

df1 = s.to_frame('timestamp') 
print (df1) 
      timestamp 
binary_grp   
2   00:00:02 
4   00:00:01 
2

IIUC:

你想找到的時間總和在整個系列賽裏binaryTrue跨越。

然而,我們必須做出一些選擇或假設

    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 

有了這些假設,我們可以使用diff,乘,sum

df.dt.diff().shift(-1).mul(df.binary).sum() 

Timedelta('0 days 00:00:04') 

然後我們就可以使用這個概念以及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