Как выбрать 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
), но вы можете легко добавить их снова, если вам нужна эта функциональность...