你可以使用scipy.ndimage.label
識別的True
S上的集羣:
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
這裏的主要想法是找到使用(ts.diff() == True).cumsum()
的True
的羣集的標籤。 ts.diff() == True
與ts.shift()^ts
的結果相同,但速度稍快。以累積和(即主叫cumsum
)對待True
爲等於1且如False
等於0,因此每次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
使用資源,而不是引入無關的依賴性的好處。 –
感謝您的回答!然而,你的代碼似乎並不知道第一個元素,它可以是True或False,所以你會以與你第一次想要的相反的方式結束。 一個簡單的修復方法是將第一行插入到結果中(如果它爲True)(最後一行也是如此) 感謝您的幫助! 編輯:其實我們可以只看結果的第一個(也是最後一個)元素的值,它告訴邊緣是上升還是下降,所以起初沒有問題。 –