Как выбрать n элементов последовательности в окнах m? (MATLAB) - PullRequest
4 голосов
/ 18 августа 2011

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

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

Ответы [ 5 ]

2 голосов
/ 18 августа 2011

Есть небольшая проблема с описанием вашей проблемы. Вы говорите, что хотите «выбрать первые 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 =

  Columns 1 through 18

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

  Columns 19 through 28

    40    84    81     7    40    53    42    66    63    30

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

>> sequenceStart = startIndex:sequenceSize:finalSequenceStart

sequenceStart =

    10    15    20

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

>> index = cumsum(ones(sequenceSize, length(sequenceStart)))

index =

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

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

index =

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

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

>> sampleData(index)

ans =

    98    83    84
    65     9    81
    81    14     7
    46    18    40
    44    40    53
2 голосов
/ 18 августа 2011

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

n = 50
m = 10;
for i=1:m:length(v)
    w = v(i:i+n);
    % Do something with w
end
2 голосов
/ 18 августа 2011

Достаточно ли у вас оперативной памяти для хранения массива 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);
1 голос
/ 18 августа 2011

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

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

1 голос
/ 18 августа 2011

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

...