【问题标题】:What is the easiest/ computationally efficient way to find the indexes at particular locations?在特定位置查找索引的最简单/计算效率最高的方法是什么?
【发布时间】:2016-04-22 16:27:49
【问题描述】:

我有一个矩阵

m =

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

这可能是 N x 3,其中 N 可能非常大。

我想在我有零的第一列 (1-13) 中找到索引,但前提是存在重复行或行是唯一的。我不希望第二列和第三列相同但第一列不为零的行。换句话说,如果第一列有一个零,但它在第二和第三列中的对应数字与另一个在第一列中具有不同数字而不是零的数字相同,则忽略该零的索引。因此,在上面的示例中,我只想返回索引 6、11、12、13。不应该返回索引 3,4,因为它们违反了规则,即存在与该行类似的行(第 2 列和第 3 列)但是第一列不同,如下所示:

 0     4     1
 0     4     1
 5     4     1

一个缓慢的解决方案是找到第一列为 0 indm=m(:,1)==0 的行的索引,然后遍历矩阵的行,检查矩阵 (m) 中是否存在具有相同第二列的任何其他行和第 3 列,但第 1 列不同。如果这种情况不存在,则将该行的索引添加到程序要返回的列表中。 但是,这种方法需要遍历大型矩阵的“for 循环”。

【问题讨论】:

  • 行的顺序是否重要,即如果第 5 行位于列表的最后,第 3,4 行是否算好?
  • 没有。顺序并不重要

标签: matlab matrix indexing unique


【解决方案1】:

解决这个问题的一种方法(假设如果有任何其他行具有相同的第 2 列和第 3 列,则该行是错误的)是找到所有不同的行,然后检查第一列是否在所有地方都相同。

%# uIdx is the same for sets of rows where m(i,2:3) is equal
[~,~,uIdx] = unique(m(:,2:3),'rows');
%# allZeros is true if all entries in the first column of m
%# corresponding to a set are the zero 
allZeros = accumarray(uIdx,m(:,1),[],@(x)all(x==0)); 

%# a good row belongs to a set of rows from m(:,2:3)
%# where all corresponding entries in the first column are zeros
%# use allZeros(uIdx) to expand allZeros to size(m,1)
goodRowIndices = find(allZeros(uIdx) == true)

goodRowIndices =

     6
    11
    12
    13

【讨论】:

  • 我的 Matlab 上没有 range 函数。这是什么功能?
  • 我做了一些小的修改:allTheSame = accumarray(uIdx,m(:,1)) == 0; ,然后是goodRowIndices = find(allTheSame(uIdx));。我认为应该是等价的。 IMO,比我的解决方案好得多!
  • 你能给我解释一下解决方案吗?我不熟悉 accumarray。
  • @JustCurious:unique 的第三个输出返回“组号”,即数组第 2 列和第 3 列中的第一、第二、第三组唯一行的一个、二、三。 range 函数(如果所有条目都相似,则相当于 @(x)max(x)-min(x) 为 0。accumarray 是一个有用的 Matlab 函数,它将函数(例如 @range)应用于所有按第一个输入分组的第二个输入的值,即输出的第一个元素是应用于第二个输入的所有元素的函数,其中第一个输入等于 1。
  • @Bentoy13:很好,因为所有条目都必须为 0,所以可以简化。正如您所建议的那样,总和将与accumarray 一起使用,但我使用all(x==0) 以提高可读性(并考虑到m(:,1) 中可能存在负条目的可能性
【解决方案2】:

这是我的解决方案:

mm = m(:,1)==0;
imm = find(mm);
[mu,~, imu] = unique(m(mm,2:3),'rows','stable');
[~,ia] = setdiff(mu,m(~mm,2:3),'rows');
X = imm(ismember(imu,ia));

第 3 行提取以 0 开头的唯一行;第4行只保留不以0开头的行中没有出现的行,第5行取回要保留的行的索引。

不确定它是最有效的方法,因为它涉及两种。

【讨论】:

  • 我得到并且索引超出矩阵尺寸错误。它对你有用吗?
  • 这似乎是“最干净”的解决方案。很棒的编码
  • 经过的时间是 0.343366 秒。 @Jonas 解决方案:经过的时间是 0.088097 秒。但由于我对 Jonas 的解决方案没有信心,我想知道他们是否在做同样的事情......
  • @JustCurious 他们在做同样的事情,他的方式更加优化。
猜你喜欢
  • 1970-01-01
  • 2013-03-22
  • 1970-01-01
  • 2017-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-26
  • 1970-01-01
相关资源
最近更新 更多