2016-08-12 7 views
0

私はいくつかの特徴をもとにカットビデオを試しています。 私の現在の戦略は、フレームごとにpandas一連のブーリアンをタイムスタンプでインデックス付けしています。 True、それを保存するにはFalseをダンプします。python pandasは一連のブール値からインデックス境界を取得します

私はビデオをカットする予定ですので、私はこのリストから境界線を抽出する必要があります。そのため、メインビデオから抽出したい部分の最初と最後をfmpegに伝えることができます。

火総括:

を、私はこのようになりますpandasシリーズを持っている:

acquisitionTs 
0.577331  False 
0.611298  False 
0.645255  False 
0.679218  False 
0.716538  False 
0.784453  True 
0.784453  True 
0.818417  True 
0.852379  True 
0.886336  True 
0.920301  True 
0.954259  False 
      ... 
83.393376 False 
83.427345 False 
dtype: bool 

(その理由を提示するために切り捨てられますが、タイムスタンプは、通常は0から始まる)

と私が必要Trueの境界線を得るために、この例ではt_0 = 0.784453t_1 = 0.920301となるべく[[t_0,t_1],[t_2,t_3]n, ... [t_2n-1,t_2n]]が得られるはずですnの異なる配列私のパンダのシリーズ。

今でproblemeが実際にあなただけの1でシーケンスをシフトし、Truedfビーイングとの境界

e = df.shift(periods=1, freq=None, axis=0)^df 
print(e[e].index) 

(するためのもので、ブールのリストを取得するとの排他的論理和を作ることができ、非常に単純なようですパンダシリーズ) 最初の要素が立ち上がりか立ち下がりかを判断するような作業はまだありますが、このハックは機能します。

しかし、それは非常にpythonicと思われません。実際問題は非常に単純なので、pandasnumpy、またはpythonのどこかに、上記のようなハックの代わりに単一の関数呼び出しにうまく収まるように予めビルドされた関数がなければならないと信じています。 groupbyの機能は有望だと思われますが、私はこれまで使用していません。

これを行うにはどうすればよいでしょうか?

答えて

1

私はシリーズではなくデータフレームを使用します(実際にシリーズでも動作します)。

df 
    acquisitionTs Value 
0  0.577331 False 
1  0.611298 False 
2  0.645255 False 
3  0.679218 False 
4  0.716538 False 
5  0.784453 True 
6  0.784453 True 
7  0.818417 False 
8  0.852379 True 
9  0.886336 True 
10  0.920301 True 
11  0.954259 False 

と私はどうなる:

df[df.Value.diff().fillna(False)] 
    acquisitionTs Value 
5  0.784453 True 
7  0.818417 False 
8  0.852379 True 
11  0.954259 False 

をあなたがここに虚偽最初の値を知っているように、あなたは0-4がFalseであることを知っているし、それはすべての指標で切り替える(5,7,8 、11)

groupby関数はTrue/Falseの値の順序が緩くなるので(私の例では5つではなく2つのグループがあります)、私が考えると助けにならないでしょう。

+0

無関係の依存関係を導入するのではなく、自由にリソースを使用することができます。 –

+0

答えに感謝します!しかし、あなたのコードは最初の要素に無関心ではないように見えますが、これは真または偽である可能性があります。 簡単な修正は、真であれば最初の行を結果に挿入することです(最後の行についても同様です) 助けてくれてありがとうございます! EDIT:実際には、エッジが上昇または下降しているかどうかを示す結果の最初の(最後の)要素の値を見ることができます。したがって、最初は実際には問題はありませんでした。 –

0

あなたはTrue秒のクラスタを識別するためにscipy.ndimage.labelを使用することができます。

In [102]: ts 
Out[102]: 
0.069347 False 
0.131956 False 
0.143948 False 
0.224864 False 
0.242640  True 
0.372599 False 
0.451989 False 
0.462090 False 
0.579956  True 
0.588791  True 
0.603638 False 
0.625107 False 
0.642565 False 
0.708547 False 
0.730239 False 
0.741652 False 
0.747126  True 
0.783276  True 
0.896705  True 
0.942829  True 
Name: keep, dtype: bool 

In [103]: groups, nobs = ndimage.label(ts); groups 
Out[103]: array([0, 0, 0, 0, 1, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3], dtype=int32) 

あなたがgroups配列を持っていたら、あなたはgroupby/aggを使用して、関連する時間を見つけることができます:

result = (df.loc[df['group'] != 0] 
       .groupby('group')['times'] 
       .agg({'start':'first','end':'last'})) 

例えば、

import numpy as np 
import pandas as pd 
import scipy.ndimage as ndimage 
np.random.seed(2016) 

def make_ts(N, ngroups): 
    times = np.random.random(N) 
    times = np.sort(times) 
    idx = np.sort(np.random.randint(N, size=(ngroups,))) 
    arr = np.zeros(N) 
    arr[idx] = 1 
    arr = arr.cumsum() 
    arr = (arr % 2).astype(bool) 
    ts = pd.Series(arr, index=times, name='keep') 
    return ts 

def find_groups(ts): 
    groups, nobs = ndimage.label(ts) 
    df = pd.DataFrame({'times': ts.index, 'group': groups}) 
    result = (df.loc[df['group'] != 0] 
       .groupby('group')['times'] 
       .agg({'start':'first','end':'last'})) 
    return result 

ts = make_ts(20, 5) 
result = find_groups(ts) 

は、あなたが使用できるリストのリストとして開始時刻と終了時刻を取得するには

  start  end 
group      
1  0.242640 0.242640 
2  0.579956 0.588791 
3  0.747126 0.942829 

が得られます。

In [125]: result.values.tolist() 
Out[125]: 
[[0.24264034406127022, 0.24264034406127022], 
[0.5799564094638113, 0.5887908182432907], 
[0.747126, 0.9428288694956402]] 

ndimage.labelを使用すると便利ですが、これを計算することも可能であることに注意してくださいなしscipy

def find_groups_without_scipy(ts): 
    df = pd.DataFrame({'times': ts.index, 'group': (ts.diff() == True).cumsum()}) 
    result = (df.loc[df['group'] % 2 == 1] 
       .groupby('group')['times'] 
       .agg({'start':'first','end':'last'})) 
    return result 

ここでの主なアイデアは、 Trueのクラスタのラベルは(ts.diff() == True).cumsum()を使用します。 ts.diff() == Truets.shift()^tsと同じ結果を示しますが、少し速いです。 (すなわち、cumsumを呼び出す)の累積和をとると、0と同等Trueなどの1に等しいとFalse扱い、そうTrueは、したがって、各クラスタが異なる数で標識されます1によって累積和増加に遭遇するたび:

In [111]: (ts.diff() == True).cumsum() 
Out[111]: 
0.069347 0 
0.131956 0 
0.143948 0 
0.224864 0 
0.242640 1 
0.372599 2 
0.451989 2 
0.462090 2 
0.579956 3 
0.588791 3 
0.603638 4 
0.625107 4 
0.642565 4 
0.708547 4 
0.730239 4 
0.741652 4 
0.747126 5 
0.783276 5 
0.896705 5 
0.942829 5 
Name: keep, dtype: int64 
関連する問題