2012-05-07 85 views
5

的(截距)點I具有與索引是象這樣一個浮點數週期性數據:計算穿越系列或數據幀

time = [0, 0.1, 0.21, 0.31, 0.40, 0.49, 0.51, 0.6, 0.71, 0.82, 0.93] 
voltage = [1, -1, 1.1, -0.9, 1, -1, 0.9,-1.2, 0.95, -1.1, 1.11] 
df = DataFrame(data=voltage, index=time, columns=['voltage']) 
df.plot(marker='o') 

我想創建一個cross(df, y_val, direction='rise' | 'fall' | 'cross')函數,返回的數組時間(索引),其中所有插值點的電壓值等於y_val。對於'上升'只返回斜率爲正的值;對於'下降'只有具有負斜率的值會變得複雜;爲'十字'都返回。因此,如果y_val = 0direction ='cross'那麼一個具有10個值的數組將返回交點的X值(第一個值約爲0.025)。

我在想這可以用迭代器完成,但想知道是否有更好的方法來做到這一點。

謝謝。我愛熊貓和熊貓社區。

+0

順便說一句,你可能已經偶然發現了熊貓陰謀的一個錯誤。根據數據,我認爲第一個交叉點應該在0.05左右,但標籤並不一致,因此交叉點爲0.025。 (熊貓0.7.3) – Garrett

回答

13

爲此,我結束了以下。它是一個矢量化版本,比使用循環的版本快150倍。

def cross(series, cross=0, direction='cross'): 
    """ 
    Given a Series returns all the index values where the data values equal 
    the 'cross' value. 

    Direction can be 'rising' (for rising edge), 'falling' (for only falling 
    edge), or 'cross' for both edges 
    """ 
    # Find if values are above or bellow yvalue crossing: 
    above=series.values > cross 
    below=np.logical_not(above) 
    left_shifted_above = above[1:] 
    left_shifted_below = below[1:] 
    x_crossings = [] 
    # Find indexes on left side of crossing point 
    if direction == 'rising': 
     idxs = (left_shifted_above & below[0:-1]).nonzero()[0] 
    elif direction == 'falling': 
     idxs = (left_shifted_below & above[0:-1]).nonzero()[0] 
    else: 
     rising = left_shifted_above & below[0:-1] 
     falling = left_shifted_below & above[0:-1] 
     idxs = (rising | falling).nonzero()[0] 

    # Calculate x crossings with interpolation using formula for a line: 
    x1 = series.index.values[idxs] 
    x2 = series.index.values[idxs+1] 
    y1 = series.values[idxs] 
    y2 = series.values[idxs+1] 
    x_crossings = (cross-y1)*(x2-x1)/(y2-y1) + x1 

    return x_crossings 

# Test it out: 
time = [0, 0.1, 0.21, 0.31, 0.40, 0.49, 0.51, 0.6, 0.71, 0.82, 0.93] 
voltage = [1, -1, 1.1, -0.9, 1, -1, 0.9,-1.2, 0.95, -1.1, 1.11] 
df = DataFrame(data=voltage, index=time, columns=['voltage']) 
x_crossings = cross(df['voltage']) 
y_crossings = np.zeros(x_crossings.shape) 
plt.plot(time, voltage, '-ob', x_crossings, y_crossings, 'or') 
plt.grid(True) 

當它工作時,這是相當令人滿意的。任何可以改進的地方?

+0

很酷。我在這裏創建了一個關於這個問題:https://github.com/pydata/pandas/issues/1256。我將不得不在未來的某個時間仔細研究它 –

+0

任何其他插值技術都可以用於提取交點的更高精度? – Chetan