Как выбрать n элементов последовательности в окнах m? (MATLAB)

Быстрый вопрос MATLAB. Что было бы лучшим / наиболее эффективным способом выбора определенного количества элементов, 'n' в окнах 'm'. Другими словами, я хочу выбрать первые 50 элементов последовательности, затем элементы 10-60, затем элементы 20-70 и т. Д. Прямо сейчас моя последовательность в векторном формате (но это легко можно изменить).

РЕДАКТИРОВАТЬ: последовательности, с которыми я имею дело, слишком длинные, чтобы быть сохраненными в моей оперативной памяти. Мне нужно иметь возможность создавать окна, а затем вызывать окно, которое я хочу проанализировать / выполнить другую команду.

5 ответов

Решение

Достаточно ли у вас оперативной памяти для хранения массива 50 на nWindow в памяти? В этом случае вы можете создать свои окна за один раз, а затем применить обработку к каждому столбцу

%# idxMatrix has 1:50 in first col, 11:60 in second col etc
idxMatrix = bsxfun(@plus,(1:50)',0:10:length(yourVector)-50); %'#

%# reshapedData is a 50-by-numberOfWindows array
reshapedData = yourVector(idxMatrix);

%# now you can do processing on each column, e.g.
maximumOfEachWindow = max(reshapedData,[],1);

Есть небольшая проблема с описанием вашей проблемы. Вы говорите, что хотите "выбрать первые 50 элементов последовательности, затем элементы 10-60..."; однако это будет означать выбор элементов:

  • 1-50
  • 10-60
  • 20-70
  • и т.п.

Эта первая последовательность должна быть 0-10, чтобы соответствовать шаблону, который, конечно, в MATLAB не имеет смысла, поскольку массивы используют одноиндексирование. Чтобы решить эту проблему, приведенный ниже алгоритм использует переменную startIndex, чтобы указать, с какого элемента начинать выборку последовательности.

Вы можете сделать это векторизованным способом, создав индексный массив. Создайте вектор, состоящий из начальных индексов каждой последовательности. Для повторного использования в качестве переменных я указал длину последовательности, размер шага между запусками последовательности и начало последней последовательности. В примере, который вы описываете, длина последовательности должна быть 50, размер шага должен быть 10, а начало последней последовательности зависит от размера входных данных и ваших потребностей.

>> startIndex = 10;
>> sequenceSize = 5;
>> finalSequenceStart = 20;

Создайте пример данных:

>> sampleData = randi (100, 1, 28)

sampleData =

  Столбцы с 1 по 18

     8 53 10 82 82 73 15 66 52 98 65 81 46 44 83 9 14 18

  Столбцы с 19 по 28

    40 84 81 7 40 53 42 66 63 30

Создайте вектор начальных индексов последовательностей:

>> sequenceStart = startIndex: sequenceSize: finalSequenceStart

sequenceStart =

    10 15 20

Создайте массив индексов для индексации в массив данных:

>> index = cumsum (единицы (sequenceSize, length(sequenceStart))))

индекс =

     1 1 1
     2 2 2
     3 3 3
     4 4 4
     5 5 5

>> index = index + repmat (sequenceStart, sequenceSize, 1) - 1

индекс =

    10 15 20
    11 16 21
    12 17 22
    13 18 23
    14 19 24

Наконец, используйте этот индексный массив для ссылки на массив данных:

>> sampleData (индекс)

ANS =

    98 83 84
    65 9 81
    81 14 7
    46 18 40
    44 40 53

В дополнение к ответу Керрека: если вы хотите сделать это в цикле, вы можете использовать что-то вроде

n = 50
m = 10;
for i=1:m:length(v)
    w = v(i:i+n);
    % Do something with w
end

Использование (start : step : end) индексация: v(1:1:50), v(10:1:60)и т. д. Если step является 1Вы можете опустить это: v(1:50),

Рассмотрим следующий векторизованный код:

x = 1:100;                                     %# an example sequence of numbers

nwind = 50;                                    %# window size
noverlap = 40;                                 %# number of overlapping elements
nx = length(x);                                %# length of sequence

ncol = fix((nx-noverlap)/(nwind-noverlap));    %# number of sliding windows
colindex = 1 + (0:(ncol-1))*(nwind-noverlap);  %# starting index of each

%# indices to put sequence into columns with the proper offset
idx = bsxfun(@plus, (1:nwind)', colindex)-1;   %'

%# apply the indices on the sequence
slidingWindows = x(idx)

Результат (усеченный для краткости):

slidingWindows =
     1    11    21    31    41    51
     2    12    22    32    42    52
     3    13    23    33    43    53
    ...
    48    58    68    78    88    98
    49    59    69    79    89    99
    50    60    70    80    90   100

Фактически, код был адаптирован из устаревшей функции SPECGRAM из панели инструментов обработки сигналов (просто edit specgram.m чтобы увидеть код).

Я опустил части, которые дополняют нулями последовательность в случае, если скользящие окна не делят равномерно всю последовательность (например, x=1:105), но вы можете легко добавить их снова, если вам нужна эта функциональность...

Другие вопросы по тегам