2016-08-12 1 views
0

일부 특징을 기반으로 커트 비디오를 시도하고 있습니다. 현재 전략은 타임 스탬프로 인덱싱 된 각 프레임에 대해 pandas 일련의 불리언 수를 기록합니다. True, 보관하려면 False으로 지정하십시오.파이썬 팬더는 일련의 부울로부터 인덱스 경계를 ​​얻습니다.

동영상을자를 계획이므로이 목록에서 경계를 추출해야합니다. 그러면 기본 동영상에서 추출하려는 부분의 시작과 끝을 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 방금 df이 인 상태 (하나 순서를 이동하고, (가) True가 경계

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

에 대한 인 상태 부울의 목록을 얻을 사이에 XOR을 할 수 있습니다 사실 매우 간단 보인다 pandas Series) 첫 번째 요소가 상승 에지인지 또는 하강 에지인지 파악하는 것과 같이 수행해야 할 작업이 아직 있지만이 해킹이 작동합니다.

그러나 매우 파이썬 스하지는 않습니다. 사실, 문제는 너무 단순해서 위와 같은 해킹 대신에 단일 함수 호출에 적합하도록 미리 빌드 된 함수 인 pandas, numpy 또는 심지어 python에 있어야한다고 생각합니다. groupby 기능은 유망한 것으로 보이지만 전에는 사용하지 못했습니다.

어떻게하면 좋을까요?

답변

1

Series가 아닌 Dataframe을 사용합니다 (시리즈와 실제로 작동합니다).

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이 거짓임을 알고 그 때마다 인덱스 전환 (5,7,8 , 11)

groupby 함수는 True/False 값의 순서가 느슨해지기 때문에 (생각하면 도움이되지 않을 것입니다. 예를 들어 5 개 대신 2 개의 그룹이 있습니다).

+0

불필요한 종속성을 제공하는 대신 원하는대로 리소스를 사용하십시오. –

+0

답해 주셔서 감사합니다! 그러나 코드가 첫 번째 요소에 대해 불가지론스러워 보이지는 않습니다.이 요소는 True 또는 False 일 수 있으므로 먼저 원하는 것과 반대 방향으로 끝냅니다. 쉬운 수정 프로그램은 첫 번째 행이 참이면 결과에 첫 번째 행을 삽입하는 것입니다 (마지막 행과 동일합니다) 어쨌든 도움을 주셔서 감사합니다! 편집 : 실제로 가장자리의 상승 또는 하강을 알리는 결과의 첫 번째 (및 마지막) 요소의 값을 볼 수 있으므로 처음에는 문제가 실제로 발생하지 않았습니다. –

0

당신은 True의의 클러스터를 식별하는 scipy.ndimage.label을 사용할 수 있습니다 : 당신이 groups 배열이 있으면

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) 

, 당신은 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) 
In [125]: result.values.tolist() 
Out[125]: 
[[0.24264034406127022, 0.24264034406127022], 
[0.5799564094638113, 0.5887908182432907], 
[0.747126, 0.9428288694956402]] 

ndimage.label 편리 사용하지만,이 계산하는 것도 가능 참고 :은

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

당신이 사용할 수있는 목록의 목록으로 시작 시간과 종료 시간을 구하려면 산출 without 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 동등한 1 False에 동등한 True 취급하므로마다 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