Нахождение первого и конечного индексов для групп значений, отличных от NAN

#arrays #matlab

Вопрос:

У меня есть две строки, которые представляют данные во временном ряду:

 row1 = [1, 2, 3, nan, 5, 6, nan, nan, nan, 10];
row2 = [10, 9, nan, 8, 7, 6, 5, nan, nan, nan];
 

Данные в каждой строке являются показаниями датчика, и известен интервал времени (поэтому каждая точка данных находится с интервалом в 1 секунду). Не очень важно, просто какой-то контекст. Длина строк составляет >10000 элементов

Мне нужно найти среднее (среднее) значение непрерывных выборок. Например, в первой строке мне нужно среднее значение [1, 2, 3], среднее значение [5, 6] и среднее значение [10]. Аналогично для 2-го датчика/ряда мне нужно среднее[10, 9], [8, 7, 6, 5].

Затем мне нужно вычесть среднее значение из этого диапазона, чтобы первый диапазон [1, 2, 3] стал [1, 2, 3] - mean([1, 2, 3])

Есть ли простой способ сделать это? Прямо сейчас я пытаюсь сделать что-то подобное:

 current_index = 1;
% Find next element that is NAN
next_nan = find(isnan(row1(current_index:end)), 1);
% Mean of the range
mean_range = mean(row1(current_index:next_nan));
row1(current_index:next_nan) = row1(current_index:next_nan) - mean(row1(current_index:next_nan));
 

Это начинает немного усложнять перемещение индексов, поэтому я подумал, что хотел бы спросить, есть ли более простой способ или команда/аргумент/и т. Д. Matlab…, Которая сделает это за меня.

Желаемым результатом будет массив того же размера, но со значениями, из которых вычитается среднее значение. Например, в строке 1:

 % mean([1, 2,  3]) is 2
% mean([5, 6]) = 5.5
% mean([10]) = 10
% so [1, 2, 3] minus 2 leads to [-1, 0, 1], and so on
new_row_1 = [-1, 0, 1, nan, -0.5, 0.5, nan, nan, nan, 0]
 

Комментарии:

1. @LuisMendo Желаемым результатом будет среднее значение строки 1(строка 1). Итак, еще один массив скорректирован на среднее значение. Спасибо за вопрос, изменю свой вопрос, чтобы прояснить это.

Ответ №1:

Быстрое и грязное решение-это

 result = cell2mat(accumarray(cumsum([1; abs(diff(isnan(row1(:))))]), row1(:), [], @(x){x-mean(x)})).';
 

или эквивалентно

 result = cell2mat(splitapply(@(x){x-mean(x)}, row1(:), cumsum([1; abs(diff(isnan(row1(:))))]))).';
 

Вектор столбцов cumsum([1; abs(diff(isnan(row1(:))))]) группирует данные в диапазонах по мере необходимости, рассматривая каждый запуск NaN » s также как группу. Затем accumarray или splitapply примените анонимную функцию @(x){x-mean(x)} к каждой группе, чтобы вычесть ее среднее значение, упаковав результат в ячейку. Наконец, cell2mat преобразует полученный массив ячеек в вектор.

«Грязная» часть заключается в том, что среднее значение также вычисляется и вычитается из каждой группы последовательных NaN «s», что немного неэффективно.