7

インデックスが次のような浮動小数点数である定期的なデータがあります。

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に等しいすべての補間点を含む時間の配列(インデックス)を返す関数を作成したいと思います。'rise'の場合、傾きが正の値のみが返されます。'fall'の場合、負の勾配を持つ値のみが返されます。'cross'の場合​​、両方が返されます。したがって、y_val =0およびdirection='cross'の場合​​、交差点のX値(最初の値は約0.025)を含む10個の値を持つ配列が返されます。

これはイテレータで実行できると思っていましたが、これを実行するためのより良い方法があるかどうか疑問に思いました。

ありがとう。私はパンダとパンダコミュニティが大好きです。

4

1 に答える 1

17

これを行うために、私は次のようになりました。これは、ループを使用するバージョンよりも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)

これがうまくいったときはとても満足でした。できる改善点はありますか?

于 2012-05-16T13:24:19.963 に答える