ゼロ次ホールドを使用してnumpy配列をリサンプリングする効率的な方法はありますか? 理想的には、 numpy.interpのような署名を持つものですか?
私はscipy.interpolate.interp1dを認識していますが、このようなケースに対処するためにベクトル化された代替手段が利用できると確信しています。
ゼロ次ホールドを使用してnumpy配列をリサンプリングする効率的な方法はありますか? 理想的には、 numpy.interpのような署名を持つものですか?
私はscipy.interpolate.interp1dを認識していますが、このようなケースに対処するためにベクトル化された代替手段が利用できると確信しています。
新しい値を補間することはないので、最も効率的な方法は、元の配列をそのままにして、floatでインデックスを付けることです。これは事実上ゼロ次ホールドです。
>>> import numpy as np
>>> A = np.array(range(10))
>>> [A[i] for i in np.linspace(0, 9, num=25)]
[0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 9]
floatを使用したインデックス作成は、numpy v1.11で非推奨になり、v1.12で削除されました(2017年1月)。上記のコードIndexError
は、現在のnumpyバージョンで例外を発生させます。
ラッパーを使用して配列にアクセスし、floatインデックスをその場で整数に変換することで、古いnumpyバージョンのfloatインデックスの動作を再現できます。numpy.interp
メモリ効率が懸念される場合、これにより、またはを使用して中間値を先制的に補間する必要がなくなりますscipy.interpolate.interp1d
。
これは、同じ署名を持つnumpyの無料バージョンです。データは昇順である必要があります-b / cネストされた関数のデフォルトとしてリストを「巧妙に」使用することでダンプされます(100倍のスピードアップ):
def interp0(x, xp, yp):
"""Zeroth order hold interpolation w/ same
(base) signature as numpy.interp."""
from collections import deque
def func(x0, xP=deque(xp), yP=deque(yp)):
if x0 <= xP[0]:
return yP[0]
if x0 >= xP[-1]:
return yP[-1]
while x0 > xP[0]:
xP.popleft() # get rid of default
y = yP.popleft() # data as we go.
return y
return map(func, x)
パーティーに少し遅れましたが、私が思いついたのは次のとおりです。
from numpy import zeros, array, sign
def signal_zoh(x,y,epsilon = 0.001):
"""
Fills in the data from a Zero-Order Hold (stair-step) signal
"""
deltaX = array(x[1:],dtype='float') - x[:-1]
fudge = min(deltaX) *epsilon
retX = zeros((len(x)*2-1,))
retY = zeros((len(y)*2-1,))
retX[0::2] = x
retX[1::2] = x[1:]+fudge*sign(deltaX)
retY[0::2] = y
retY[1::2] = y[:-1]
return retX,retY