从矩阵A中提取包含矩阵B元素的所有行的更好方法

时间:2017-05-30 14:27:59

标签: matlab matrix indexing vectorization submatrix

矩阵A是我的起始矩阵,它保存从我的MPU6050和GPS记录在SD卡上的数据(纬度,经度,时间,轴,Ay,Az,Gx,Gy,Gz)。

我计算了窗口大小为5的Az的标准偏差,并确定了满足条件(>阈值)的所有元素。

然后在矩阵" large_windows" 中,我在窗口中存储满足条件的所有Az的索引。

从矩阵" large_windows" 我计算了一个新矩阵B,矩阵A中的所有行包含矩阵" large_windows" 元素。

我认为我的代码是effective,但非常丑陋和混乱,而且我仍然不太习惯 indexing ,但我想学习它。

1。是否存在更好的解决方案?

2。可以使用逻辑索引吗?怎么样?效率很高*?

这里我的代码是一个带有通用条件的简化示例,不仅可以更好地理解整个概念, starting from suggestions of a previous problem(how to create a sliding window

%random matix nXm
a=rand(100,6); 

%window dimension
window_size=4; 

%overlap between two windows
overlap=1;

%increment needed
step=window_size - overlap; 

%std threshold
threshold=0.3; 
std_vals= NaN(size(a,1),1); 

%The sliding window will analyze only the 5th column 
for i=1: step: (size(a,1)-window_size)
  std_vals(i)=std(a(i:(i+window_size-1),5));
end

% finding the rows with standard deviation larger than threshold
large_indexes = find(std_vals>threshold);

%Storing all the elements that are inside the window with std>threshold 

large_windows = zeros(numel(large_indexes), window_size);
for i=1:window_size
    large_windows(:,i) = large_indexes + i - 1;
end

% Starting extracting all the rows with the 5th column outlier elements 
n=numel(large_windows);

%Since i will work can't know how long will be my dataset 
%i need to knwo how is the "index distance" between two adjacent elements
% in the same row [es. a(1,1) and a(1,2)]


diff1=sub2ind(size(a),1,1);
diff2=sub2ind(size(a),1,2);

l_2_a_r_e = diff2-diff1 %length two adjacent row elements 
large_windows=large_windows'
%calculating al the index of the element of a ith row containing an anomaly
for i=1:n

   B{i}=[a(large_windows(i))-l_2_a_r_e*4 a(large_windows(i))-l_2_a_r_e*3 a(large_windows(i))-l_2_a_r_e*2 a(large_windows(i))-l_2_a_r_e*1 a(large_windows(i))-l_2_a_r_e*0 a(large_windows(i))+l_2_a_r_e];
end 

C= cell2mat(B');

我在发布之前还先阅读了一些问题,但This was to specific

B未包含在A中,因此此问题无效Find complement of a data frame (anti - join)

在此特定情况下

I don't know how to use ismember

我希望我的绘图可以更好地解释我的问题:)

感谢您的时间 enter image description here

1 个答案:

答案 0 :(得分:1)

这是一种实现您实际想要实现的结果的新方法。我纠正了你犯的2个错误并用bsxfun替换了所有for循环,这是一个非常有效的函数来做这样的事情。对于Matlab R2016b或更新版本,您也可以implicit expansion代替bsxfun 我从你实现滑动窗口开始。您可以使用

代替for - 循环
stdInds=bsxfun(@plus,1:step:(size(a,1)-overlap),(0:3).');
std_vals=std(a(sub2ind(size(a),stdInds,repmat(5,size(stdInds)))));

这里。 bsxfun创建一个包含窗口行的数组。它在每列中保存1个windo。需要将这些行转换为a - 数组的线性索引,以获取可以传递给std - 函数的值数组。在您的实现中,您在此处犯了一个小错误,因为您的for - 循环在size(a,1)-window_size结束,并且实际上应该在size(a,1)-overlap结束,否则您错过了最后一个窗口。
现在我们得到了窗口的std值,我们可以检查哪些值大于预定义的阈值,然后将它们转换回相应的行:

highStdWindows=find(std_vals_2>threshold);
highStdRows=bsxfun(@plus,highStdWindows*step-step+1,(0:3).');

highStdWindows包含具有高Std值的窗口索引。在下一行中,我们使用highStdWindows*step-step+1计算这些窗口的起始行,然后再次使用bsxfun计算与每个窗口对应的其他行。
现在我们得到你代码中的实际错误。这条线就在这里

B{i}=[a(large_windows(i))-l_2_a_r_e*4 a(large_windows(i))-l_2_a_r_e*3 a(large_windows(i))-l_2_a_r_e*2 a(large_windows(i))-l_2_a_r_e*1 a(large_windows(i))-l_2_a_r_e*0 a(large_windows(i))+l_2_a_r_e];

没有做你想做的事。不幸的是,你错过了几个括号。通过这种方式,您可以获取矩阵a的large_windows(i)'元素并从中减去4*l_2_a_r_e。你想写的是

B{i}==[a(large_windows(i)-l_2_a_r_e*4)  % and so on

这样,您可以从传递给4*l_2_a_r_e的索引中减去a。这仍然是错误的,因为在large_windows中存储了行号而不是与矩阵a对应的线性索引。
然而,使用下标索引而不是线性索引可以更轻松地实现这一点:

rowList=reshape(highStdRows,1,[]);
C=a(rowList,:); % all columns (:) and from the rows in rowList

这两个简单的行告诉matlab将highStdRows中存储的所有行都包含在所有列中(由:表示)。如果有两个相邻的窗口具有高标准值,您将获得两次重叠的行。如果您不想这样,可以改为使用此代码:

rowList=unique(reshape(highStdRows,1,[]));
C=a(rowList,:);

如果您想进一步了解Matlab中索引的工作方式,请查看LuisMendo关于此主题的post