【问题标题】:Better way to extract all the rows from a Matrix A that contain an element of a matrix B从包含矩阵 B 元素的矩阵 A 中提取所有行的更好方法
【发布时间】:2017-10-31 02:13:04
【问题描述】:

矩阵 A 是我的起始矩阵,它将 MPU6050 和 GPS 记录的数据保存在 SD 卡上(纬度、经度、时间、Ax、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 useismember 在这种特定情况下

我希望我的画能更好地解释我的问题:)

感谢您的宝贵时间

【问题讨论】:

  • 我不确定我是否正确理解您要查找的内容。例如,您可以使用large_windows=repmat(large_indexes.',window_size,1)+(0:3).'large_windows=bsxfun(@plus,large_indexes,0:3).' 来创建large_windows 数组,而不是您的for 循环。它可能会更有效一些。你在找这样的东西吗?你的目标是让你的代码更快吗?您在处理大量数据吗?或者您只是想美化代码并理解一些花哨的 matlab 索引内容?
  • @uomodellamansarda 如果最终结果是矩阵 B,那么您实际上不需要计算矩阵“large_windows”。您可以直接从“large_indexes”中获取“B”。你怎么看?
  • @Max 我的目标是让我的代码更快,因为我有超过 4k 行,但我想了解一些花哨的 matlab 索引的东西(它们不是有用吗?我是菜鸟,没有计算机科学背景,每个人都不鼓励我在 matlab 上使用 for-loop):) 感谢您的建议,我会学习然后尝试 :)
  • @AmritbirSinghGill 我没有想到这个可能的解决方案,我会试试的! (做不做没有尝试)
  • 在您计算 B 的行中,您使用与 a-array 的第 5 列对应的行号作为线性索引。你确定这是你想做的吗?

标签: matlab matrix indexing vectorization submatrix


【解决方案1】:

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

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 个窗口。这些行需要转换为a-array 的线性索引,以获取可以传递给std-function 的值数组。在您的实现中,您在这里犯了一个小错误,因为您的for-loop 以size(a,1)-window_size 结束,实际上应该以size(a,1)-overlap 结束,否则您会错过最后一个窗口。
现在我们得到了窗口的标准值,我们可以检查哪些大于您预定义的阈值,然后将它们转换回相应的行:

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

highStdWindows 包含具有高标准值的窗口的索引。在下一行中,我们使用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)'th 元素并从中减去 4*l_2_a_r_e。你想写的是

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

这样您可以从传递给a 的索引中减去4*l_2_a_r_e。这仍然是错误的,因为在 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 关于此主题的内容。

【讨论】:

  • 谢谢我理解我所有的错误!现在我试图理解这一点:highStdWindows*step-step+1 很清楚bsxfun 是如何工作的,不清楚为什么你应该乘以*step 然后减去-step+1 :) 我在 matlab 上尝试了代码,看看结果,但我坚持这一点。提前致谢
  • highStdWindows 中,我们存储了具有高标准值的窗口的编号。所以现在我们需要计算相应的行号。想象一下,我们只有大小为 4 的窗口,并且有一个重叠,第一个、第三个和第四个窗口具有高标准值。现在highStdWindows 将包含数组[1, 3, 4],但我们需要计算这些窗口开始的行。将此向量与step 相乘并添加-step+1 就是这样做的。例如窗口 3 由[7 8 9 10] 组成,我们用3*step-step+1=7 计算起始行,用bsxfun 计算其他行
猜你喜欢
  • 1970-01-01
  • 2022-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-20
  • 2013-04-20
相关资源
最近更新 更多