2016-06-06 4 views
4

У меня есть 2d-массив (или матрица, если вы предпочитаете) с некоторыми недостающими значениями, представленными как NaN. Недостающие значения, как правило, в полосе вдоль одной оси, например:Интерполировать отсутствующие значения 2d python

1 2 3 NaN 5 
2 3 4 Nan 6 
3 4 Nan Nan 7 
4 5 Nan Nan 8 
5 6 7 8 9 

, где я хотел бы заменить NaN «S на несколько разумных количествах.

Я искал триангуляцию треугольника, но нашел очень мало документации.

Я попытался использовать astropy's convolve, поскольку он поддерживает использование 2d-массивов и довольно прост. Проблема в том, что свертка не является интерполяцией, она перемещает все значения в среднее (что может быть смягчено с помощью узкого ядра).

Этот вопрос должен быть естественным 2-мерным расширением до this post. Есть ли способ интерполяции по NaN/отсутствующих значений в 2d-массиве?

+0

Существует много способов интерполировать это. Одна из трудностей состоит в том, что ваши данные больше не являются прямоугольными, и для этого требуются многие простые алгоритмы интерполяции 2d, но это все еще возможно. Есть ли у вас какие-либо особые требования к интерполяции? –

+0

Например, этот http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.interpolate.interp2d.html, вероятно, делает то, что вам нужно. Просто пройдите в точках данных, которые не являются NaN, а затем перепрограммируются на NaN после построения интерполяции. –

+0

Кроме того, этот вопрос: http://stackoverflow.com/questions/5146025/python-scipy-2d-interpolation-non-uniform-data представляется практически одинаковым. –

ответ

6

Да, вы можете использовать scipy.interpolate.griddata и замаскированный массив, и вы можете выбрать тип интерполяции, который вы предпочитаете использовать аргумент method обычно 'cubic' делает отличную работу:

import numpy as np 
from scipy import interpolate 


#Let's create some random data 
array = np.random.random_integers(0,10,(10,10)).astype(float) 
#values grater then 7 goes to np.nan 
array[array>7] = np.nan 

Это выглядит примерно так, используя plt.imshow(array,interpolation='nearest') :

enter image description here

x = np.arange(0, array.shape[1]) 
y = np.arange(0, array.shape[0]) 
#mask invalid values 
array = np.ma.masked_invalid(array) 
xx, yy = np.meshgrid(x, y) 
#get only the valid values 
x1 = xx[~array.mask] 
y1 = yy[~array.mask] 
newarr = array[~array.mask] 

GD1 = interpolate.griddata((x1, y1), newarr.ravel(), 
          (xx, yy), 
          method='cubic') 

Это конечный результат:

enter image description here

Посмотрите, что если значения нан в ребрах и окружены нан значения Тэй не могут быть интерполированы и сохраняются nan. Вы можете изменить его, используя аргумент fill_value.

Как это будет работать, если есть область значений NaN 3x3, вы получите разумные данные для средней точки?

Это зависит от ваших данных, вы должны выполнить некоторые испытания. Вы можете, например, маскировать некоторые хорошие данные, попробуйте различную интерполяцию, например. кубический, линейный и т. д. с массивом с замаскированными значениями и вычислять разницу между значениями интерполированных и исходными значениями, которые вы ранее маскировали, и посмотреть, какой метод возвращает вам незначительную разницу.

Вы можете использовать что-то вроде этого:

reference = array[3:6,3:6].copy() 
array[3:6,3:6] = np.nan 
method = ['linear', 'nearest', 'cubic'] 

for i in method: 
    GD1 = interpolate.griddata((x1, y1), newarr.ravel(), 
           (xx, yy), 
           method=i) 
    meandifference = np.mean(np.abs(reference - GD1[3:6,3:6])) 
    print ' %s interpolation difference: %s' %(i,meandifference) 

Это дает что-то вроде этого:

linear interpolation difference: 4.88888888889 
    nearest interpolation difference: 4.11111111111 
    cubic interpolation difference: 5.99400137377 

Конечно, это для случайных чисел, так что это нормально, что результат может меняться много. Поэтому лучше всего протестировать «на замаскированную» часть вашего набора данных и посмотреть, что произойдет.

+0

Как это будет работать, если есть область значений NaN 3x3, вы получите разумные данные для средней точки? –

+0

@ M.T Привет, я отредактировал ответ, чтобы ответить на этот вопрос. –

0

Я бы вручную просмотрел эту матрицу по строкам, и всякий раз, когда вы начинаете встречаться с списком Nans, следите за номером непосредственно перед Nans и сразу после этого, а также количеством Nans, которое вы видели перед возвратом к обычным числам. Как только эти числа будут найдены, можно будет перенести Nans с помощью интерполированных значений самостоятельно.

Смежные вопросы