如何在 m 的窗口中选择序列的 n 个元素? (matlab)
Posted
技术标签:
【中文标题】如何在 m 的窗口中选择序列的 n 个元素? (matlab)【英文标题】:How do I select n elements of a sequence in windows of m ? (matlab) 【发布时间】:2011-10-29 07:11:57 【问题描述】:快速 MATLAB 问题。 在“m”的窗口中选择一定数量的元素“n”的最佳/最有效的方法是什么。换句话说,我想选择序列的前 50 个元素,然后是元素 10-60,然后是元素 20-70 等。 现在,我的序列是矢量格式(但这很容易改变)。
编辑: 我正在处理的序列太长而无法存储在我的 RAM 中。我需要能够创建窗口,然后调用我想要分析/执行另一个命令的窗口。
【问题讨论】:
如果窗口长度相同,则间隔为:1-50, 11-60, 21-70, ...
对吗?
是的,你是对的,它的 1-50、11-60、21-70 等。我的错。
【参考方案1】:
考虑以下矢量化代码:
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
事实上,代码改编自 Signal Processing Toolbox 中现已弃用的 SPECGRAM 函数(只需执行 edit specgram.m
即可查看代码)。
我省略了对序列进行零填充的部分,以防滑动窗口无法均匀划分整个序列(例如 x=1:105
),但如果您需要该功能,您可以轻松地再次添加它们...
【讨论】:
【参考方案2】:您是否有足够的 RAM 在内存中存储 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);
【讨论】:
哎呀,感谢您发现这一点 - 我高估了可能的窗口数量 :) 这是我最初的想法,但运行后我意识到我的序列可能会变得相当长,而且我没有足够的 RAM 来将数组存储在内存中。 是否可以对窗口进行编号,例如调用“Window 13”,而不将其存储在 RAM 中? @thepro22: 当然:窗口#13 是stepSize*(windowNumber-1)+(1:windowLength)
,如果windowNumber
是13。stepSize
是开始之间的索引差(在你的情况下是10),windowLength
是数字窗口中的元素数(在您的情况下为 50)。【参考方案3】:
您的问题描述存在小问题。你说你想“选择一个序列的前 50 个元素,然后选择 10-60 个元素……”;但是,这将转化为选择元素:
1-50 10-60 20-70 等第一个序列应该是 0-10 以适应模式,这在 MATLAB 中当然没有意义,因为数组使用单索引。为了解决这个问题,下面的算法使用一个名为 startIndex 的变量来指示从哪个元素开始序列采样。
您可以通过构造索引数组以矢量化方式完成此操作。创建一个由每个序列的起始索引组成的向量。为了重用,我将序列的长度、序列开始之间的步长以及最后一个序列的开始作为变量。在您描述的示例中,序列的长度应为 50,步长应为 10,最后一个序列的开始取决于输入数据的大小和您的需求。
>> 开始索引 = 10; >> 序列大小 = 5; >> finalSequenceStart = 20;创建一些示例数据:
>> 样本数据 = 兰迪 (100, 1, 28) 样本数据 = 第 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 序列开始 = 10 15 20创建一个索引数组以索引到数据数组中:
>> index = cumsum(ones(sequenceSize, length(sequenceStart))) 指数 = 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 >> 索引 = 索引 + repmat(sequenceStart, sequenceSize, 1) - 1 指数 = 10 15 20 11 16 21 12 17 22 13 18 23 14 19 24最后,使用这个索引数组来引用数据数组:
>> 样本数据(索引) 答案= 98 83 84 65 9 81 81 14 7 46 18 40 44 40 53【讨论】:
【参考方案4】:补充 Kerrek 的回答:如果您想循环执行,可以使用类似
n = 50
m = 10;
for i=1:m:length(v)
w = v(i:i+n);
% Do something with w
end
【讨论】:
【参考方案5】:使用(start : step : end)
索引:v(1:1:50)
、v(10:1:60)
等。如果step
为1
,则可以省略:v(1:50)
。
【讨论】:
以上是关于如何在 m 的窗口中选择序列的 n 个元素? (matlab)的主要内容,如果未能解决你的问题,请参考以下文章