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

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

Я хотел бы заменить все NaN, используя какой-то метод интерполяции, как я могу сделать это в 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

Редактировать:

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

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


person Dave    schedule 02.09.2010    source источник
comment
В вашем примере, я думаю, вам будет сложно найти способ интерполировать пропущенные значения. Интерполяция требует, чтобы между точками данных существовали какие-то отношения. Часто это может быть так, что они происходят из временного ряда (поэтому можно предположить, что недостающую часть можно вывести из ближайших точек). В данных вашего примера вы пытаетесь угадать бросок монеты, основываясь только на других бросках монеты. Если вы можете предоставить нам больше информации о вашем конкретном примере, мы можем помочь больше.   -  person JudoWill    schedule 02.09.2010
comment
@JudoWill: я думаю, что он просто использовал случайные данные в качестве примера, с которым люди могли поиграть.   -  person gnovice    schedule 02.09.2010


Ответы (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, чтобы выяснить, какие из них лучше всего подходят для вашей ситуации.

person JudoWill    schedule 02.09.2010
comment
спасибо, в моем случае мне нужно изменить вектор times, так как значения записываются каждые 3 секунды - person Dave; 02.09.2010
comment
... Теперь, когда я думаю об этом, это не имеет значения, если последовательности одинаково выбраны, не так ли? - person Dave; 02.09.2010
comment
да, пока они одинаково выбраны, это не имеет большого значения ... но я стараюсь быть как можно более явным. - person JudoWill; 02.09.2010

Я бы использовал 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
person Community    schedule 02.09.2010

Если у вас есть доступ к System Identification Toolbox, вы можете использовать MISDATA для оценки пропущенных значений. Согласно документации:

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

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

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

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

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

Используйте griddedInterpolant

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

person Jwalant Bhatt    schedule 05.09.2017
comment
Хотя эта ссылка может ответить на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если связанная страница изменится. – Из обзора - person Michel; 20.09.2018
comment
@Michel Это ответ не только по ссылке. Ответ — это имя используемой функции, а ссылка — это просто ссылка на документацию по этой функции. - person jwg; 20.09.2018
comment
@jwg Ваш вопрос находится в некачественном обзоре. Вы можете поделиться как использовать эту функцию, а не только название функции и ссылку. - person Erik A; 20.09.2018

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

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

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

person Kena    schedule 02.09.2010

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

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

затем используйте

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

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

person Jagte    schedule 21.06.2013