我正在寻找一种有效的方法来获取测量值之间有NaNs
的数组的每个条目的最近邻居。我想做的是使用下一个邻居对每个值进行插值或外推,但是NaNs
通常搞砸了我为执行此类操作而发现的函数-所以我写了一个相当荒谬的复杂函数,虽然可以,但是当数组的值超过1k左右时,效率会变得太低。
因此,我将给函数提供要计算的值(newIs = [0,1,2,3,4])和测量值(Is = [np.nan,np.nan,0.1,0.7,1.2,np.nan,np.nan,2.6,3.8,4.2,6.3,np.nan,np.nan,np.nan]
)。我想要得到的是newIs
可视化:
INPUT:
newIs = [0,1,2,3,10]
Is = [np.nan,np.nan,0.1,0.7,1.2,np.nan,np.nan,2.6,3.8,4.2,6.3,np.nan,np.nan,np.nan]
[Input] [Index-1,Index-2]
In: [0] Out: [2,3] -- points to 0.1 and 0.7 as nearest neighbours
In: [1] Out: [3,4] -- points to 0.7 and 1.2
In: [2] Out: [4,7] -- points to 1.2 and 2.6
In: [3] Out: [7,8] -- points to 2.6 and 3.8
In: [10] Out: [9,10] -- points to 4.2 and 6.3
因此,对于0.1
以下的每个值,我将得到[2,3]
,对于6.3
以上的每个值,我将得到[9,10]
。当我只想插值时,只需检查我的“期望”值是否在计算的索引之间。
我使用的是以下功能(添加了一些注释以提高可读性):
def find_interpolation_indices(Is,newIs):# BaMa:: numpy arrays as inputs
maxx = len(Is)-1
arrayLeft = []
arrayRight = []
for curr in newIs:# BaMa:: 'safety first' -> lots of checks to make sure indices are correct
index = 0
right = 0
left = 0
for k in range(0,len(Is)):# BaMa:: instead write a search fct yourself like so...
if(np.isnan(Is[k])):
pass
elif(Is[k] > curr):
index = k
break
if(index > maxx):
index = maxx
direction = 0
while(np.isnan(Is[index]) and direction == 0):
index += 1
if(index >= maxx):
index = maxx
direction+=1
if(direction >= 1):
while(np.isnan(Is[index])):
index -= 1
if(index <= 0):
print('\x1b[1;31;43m' + 'ERROR: Interpolation fail 0 -> nothing found for ', Is[index], ' and ', curr, ' ! \x1b[0m')
if(Is[index] <= curr):# BaMa:: (1/2) current at index value is checked, should be the standard case
left = index
right = index+1
while(left < 0):
left+=1
right+=1
while(right > maxx):
left-=1
right-=1
direction = 0
while(np.isnan(Is[right]) and direction == 0):# BaMa:: move right index up until value is found
right+=1
if(right > len(Is)-1):# BaMa:: if no value is ever found...
direction+=1
right-=1
if(direction >=1):# BaMa::...set right index to value and move left index down
right = index
left = index-1
while(np.isnan(Is[left])):# BaMa:: if nothing is found again, print out an Error
left-=1
if(left <= 0):
print('\x1b[1;31;43m' + 'ERROR: Interpolation fail 1 -> nothing found for ', Is[index], ' and ', curr, ' ! \x1b[0m')
left+=1
break
elif(Is[index] > curr):# BaMa:: (2/2) current at index value is checked, should be the standard case
right = index
left = index-1
while(left < 0):
left+=1
right+=1
while(right > maxx):
right-=1
left-=1
direction = 0
while(np.isnan(Is[left]) and direction == 0):# BaMa:: move left index down until value is found
left-=1
if(left <= 0):# BaMa:: if no value is ever found...
direction+=1
left = 0
if(direction >= 1):# BaMa:: ...set left index to value and move right index up
left = index
right = index+1
while(np.isnan(Is[right])):# BaMa::
right+=1
if(right >= len(Is)-1):
print('\x1b[1;31;43m' + 'ERROR: Interpolation fail 2 -> nothing found for ', Is[index], ' and ', curr, ' ! \x1b[0m')
right-=1
break
if(right < left):# BaMa:: last check before relaying final values
print('\x1b[1;31;43m' + 'ERROR: Interpolation fail 3 -> RIGHT < LEFT! \x1b[0m')
print("left=", left, " right=", right)
elif(right == left):
print('\x1b[1;31;43m' + 'ERROR: Interpolation fail 4 -> RIGHT == LEFT! \x1b[0m')
print("left=", left, " right=", right)
elif(np.isnan(Is[right]) or np.isnan(Is[left])):
print('\x1b[1;31;43m' + 'ERROR: Interpolation fail 5 -> Is[left]=', Is[left], ' Is[right] =', Is[right], ' \x1b[0m')
print("left=", left, " right=", right)
elif(right > maxx or left > maxx or right < 0 or left < 0):
print('\x1b[1;31;43m' + 'ERROR: Interpolation fail 6 -> Is[left]=', Is[left], ' Is[right] =', Is[right], ' \x1b[0m')
print("left=", left, " right=", right)
else:
arrayLeft.append(left)
arrayRight.append(right)
return arrayLeft,arrayRight