2017-06-15 12 views
2

I以下のデータフレーム持っている:私はbinaryTrueときの経過時間を合計したいパンダの尺度は、経過時間を

    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 

これを行うには良い方法がありますか?私はこのコードが実行可能だと思う、私の心配は読みやすさです。

答えて

2

私の意見では、あなたのソリューションは素晴らしいです。

別の解決策:

neshift ED値を比較cumsumことにより、グループを取得。

フィルタリングはilocを選択することにより、差の活用可能性apply後:だけall_timeが必要な場合はDataFrame新しいソリューションでは

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 

は必要ありません。

groupby = df.groupby('binary_grp') 

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

しかし、もし必要それを作成することが可能ですSeriessによってto_frame:あなたは時間の合計がbinaryTrueあるシリーズ全体にまたがる検索したい

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

IIUC。

はしかし、我々は乗算、diffを使用することができ、いくつかの選択肢や仮定これらの前提条件に

    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 

を行う必要があり、かつ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 
関連する問題