MATLAB: использование интерполяции для замены отсутствующих значений (NaN)

у меня есть массив ячеек, каждая из которых содержит последовательность значений в вектор-строку. Последовательности содержат некоторые отсутствующие значения, представленные NaN.

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

рассмотрим этот пример данных, чтобы проиллюстрировать проблему:

seq = {randn(1,10); randn(1,7); randn(1,8)};
for i=1:numel(seq)
    %# simulate some missing values
    ind = rand( size(seq{i}) ) < 0.2;
    seq{i}(ind) = nan;
end

В результате последовательности:

seq{1}
ans =
     -0.50782     -0.32058          NaN      -3.0292     -0.45701       1.2424          NaN      0.93373          NaN    -0.029006
seq{2}
ans =
      0.18245      -1.5651    -0.084539       1.6039     0.098348     0.041374     -0.73417
seq{3}
ans =
          NaN          NaN      0.42639     -0.37281     -0.23645       2.0237      -2.2584       2.2294

Edit:

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

фактические данные-это некоторая форма обработки сигналов. Проблема в том, что во время анализа мое решение потерпит неудачу, если последовательности содержат отсутствующие значения, следовательно, необходимость фильтрации / интерполяции (я уже рассматривал использование среднего из каждой последовательности заполнить пробелы, но я надеюсь на что-то более мощное)

6 ответов


Ну, если вы работаете с данными временных рядов, то вы можете использовать встроенную функцию интерполяции Matlab.

что-то вроде это должно работать для вашей ситуации, но вам нужно настроить его немного ... то есть. если у вас нет равных интервалов выборки, вам нужно будет изменить times линии.

nseq = cell(size(seq))
for i = 1:numel(seq)
    times = 1:length(seq{i});
    mask =  ~isnan(seq{i});
    nseq{i} = seq{i};
    nseq{i}(~mask) = interp1(times(mask), seq{i}(mask), times(~mask));

end

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


Я хотел бы использовать inpaint_nans, инструмент, предназначенный для замены nan-элементов в 1-d или 2-d матрицах интерполяцией.

seq{1} = [-0.50782 -0.32058 NaN -3.0292 -0.45701 1.2424 NaN 0.93373 NaN -0.029006];
seq{2} = [0.18245 -1.5651 -0.084539 1.6039 0.098348 0.041374 -0.73417];
seq{3} = [NaN NaN 0.42639 -0.37281 -0.23645 2.0237];

for i = 1:3
  seq{i} = inpaint_nans(seq{i});
end

seq{:}
ans =
 -0.50782 -0.32058 -2.0724 -3.0292 -0.45701 1.2424 1.4528 0.93373 0.44482 -0.029006

ans =
  0.18245 -1.5651 -0.084539 1.6039 0.098348 0.041374 -0.73417

ans =
  2.0248 1.2256 0.42639 -0.37281 -0.23645 2.0237

Если у вас есть доступ к Система Идентификации Toolbox можно использовать MISDATA функция для оценки недостающих значений. Согласно документация:

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

в основном алгоритм чередуется между оценкой отсутствующих данных и оценкой моделей, аналогично алгоритму максимизации ожиданий (EM).

оцененная модель может быть любой из линейных моделей idmodel (AR/ARX/..) или, если не задано, использует модель пространства состояний по умолчанию.

вот как применить его к Ваши данные:

for i=1:numel(seq)
    dat = misdata( iddata(seq{i}(:)) );
    seq{i} = dat.OutputData;
end

использовать griddedInterpolant

есть также некоторые другие функции, такие как interp1. Для криволинейных участков сплайн является лучшим методом поиска недостающих данных.


Как говорит Джудовилл, вам нужно предположить какую-то связь между вашими данными.

одним из тривиальных вариантов было бы вычислить среднее значение вашего общего ряда и использовать их для недостающих данных. Другой тривиальный вариант - взять среднее из N предыдущих и N следующих значений.

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


рассмотрим следующий пример

X=некоторый массив Nx1 Y=F (X) с некоторыми NaNs в нем

затем использовать

X1=X (найти (~isnan (Y))); Y1=Y (найти (~isnan (Y)));

теперь интерполируйте по X1 и Y1, чтобы вычислить все значения на всех X.