2017-04-18 59 views
2

我用熊貓實現了一些腳本,但我不確定它是否是最優雅/快速的實現。 (我使用一個for循環...)熊貓發現最大穩定間隔

假設你有AY變量(浮動)隨時間

我需要做的就是創建一個新的列(0或1)對數據幀指示間隔,其中Y值是允許的變化範圍內穩定/噪聲

abs(Y_start - Y_end) < noise_allowed 

如果有一個以上的間隔,僅其中Y是最大的時間間隔應該被標記

enter image description here

什麼將是最優雅的方式來做到這一點?也許使用滾動窗口?

回答

3

這裏的一個矢量NumPy的方法 -

def max_stable_mask(a, thresh): # thresh controls noise 
    mask = np.r_[ False, np.abs(a - a.max()) < thresh, False] 
    idx = np.flatnonzero(mask[1:] != mask[:-1]) 
    s0 = (idx[1::2] - idx[::2]).argmax() 
    valid_mask = np.zeros(a.size, dtype=int) #Use dtype=bool for mask o/p 
    valid_mask[idx[2*s0]:idx[2*s0+1]] = 1 
    return valid_mask 

樣品運行 -

In [193]: a = np.array([0, 2, 4, 9.2, 6, 6, 9, 9 , 9.2, 9.1, 9.2, 5, 0]) 

In [194]: max_stable_mask(a, thresh = 0.5) 
Out[194]: array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0]) 

In [195]: max_stable_mask(a, thresh = 0.1) 
Out[195]: array([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0]) 

In [196]: max_stable_mask(a, thresh = 0.01) 
Out[196]: array([0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]) 

在具有的0.01閾值的最後一個樣本的情況下有每兩個間隔與每一個元件和用於這樣的它會選擇第一個間隔。

1

不完全是優雅的,但不涉及任何明確的for循環:

import pandas as pd 

threshold = 0.015 

# construct a test DataFrame 
df = pd.DataFrame({'y': [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.5, 0.5, 0.5, 
         0.6, 0.7, 0.8, 0.9, 1, 1.01, 1.02, 1.03, 1.04, 
         0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0]}) 
# calculate a shifted series for differencing 
df['y_diff'] = df.y.shift(1) - df.y 
# find flat areas 
df['y_flat'] = abs(df['y_diff']) < threshold 
# index blocks 
df['y_flat_index'] = (df.y_flat.shift(1) != df.y_flat).astype(int).cumsum() 
# calculate mean y for flat areas 
df['y_flat_mean'] = df[['y', 'y_flat_index']].groupby('y_flat_index').transform(lambda x: x.mean()) 
# mark the flat area with the highest mean y 
df['y_marked'] = ((df['y_flat'] == True) & (df['y_flat_mean'] == max(df['y_flat_mean']))).astype(int) 
# take into account that we shifted the series, i.e. add one more True value at the beginning, 
# unless there's only one maximum value, in which case assign mark to that index 
if sum(df['y_marked']) == 0: 
    df['y_marked'].loc[df['y'] == max(df['y'])] = 1 
else: 
    df['y_marked'].iloc[df[df['y_marked'] == 1].index - 1] = 1 
print(df) 

結果:

 y y_diff y_flat y_flat_index y_flat_mean y_marked 
0 0.00  NaN False    1  0.250 0 
1 0.10 -0.10 False    1  0.250 0 
2 0.20 -0.10 False    1  0.250 0 
3 0.30 -0.10 False    1  0.250 0 
4 0.40 -0.10 False    1  0.250 0 
5 0.50 -0.10 False    1  0.250 0 
6 0.50 0.00 True    2  0.500 0 
7 0.50 0.00 True    2  0.500 0 
8 0.50 0.00 True    2  0.500 0 
9 0.60 -0.10 False    3  0.800 0 
10 0.70 -0.10 False    3  0.800 0 
11 0.80 -0.10 False    3  0.800 0 
12 0.90 -0.10 False    3  0.800 0 
13 1.00 -0.10 False    3  0.800 1 
14 1.01 -0.01 True    4  1.025 1 
15 1.02 -0.01 True    4  1.025 1 
16 1.03 -0.01 True    4  1.025 1 
17 1.04 -0.01 True    4  1.025 1 
18 0.90 0.14 False    5  0.450 0 
19 0.80 0.10 False    5  0.450 0 
20 0.70 0.10 False    5  0.450 0 
21 0.60 0.10 False    5  0.450 0 
22 0.50 0.10 False    5  0.450 0 
23 0.40 0.10 False    5  0.450 0 
24 0.30 0.10 False    5  0.450 0 
25 0.20 0.10 False    5  0.450 0 
26 0.10 0.10 False    5  0.450 0 
27 0.00 0.10 False    5  0.450 0 

注意,這將標誌着所有最大y的平坦區域,如果有除[0,2,0,0,2,2]之外的情況除外。