【问题标题】:Get rid of identical permutations in a matrix, Matlab摆脱矩阵中的相同排列,Matlab
【发布时间】:2013-07-25 16:03:54
【问题描述】:

我用 Matlab 生成了一个 X×10 的数字数组。该数组在“精神上”分为 4、3 和 3 列集。如果此数组在下面给出,则为两行

[1 2 3 4 ; 5 6 7 ; 8 9 10] [1 2 3 4 ; 8 9 10 ; 5 6 7]

分号是心理分区。我需要进一步处理这个数组,但“心理列”排列给出了相同的信息。第二行是第一行的第二和第三“心理行”的排列。

有什么简单的方法可以摆脱 Matlab 内置函数的排列吗?有点像识别排列的独特

【问题讨论】:

  • [1 2 4 3 ; 5 6 7 ; 8 9 10] 是否也被视为[1 2 3 4 ; 5 6 7 ; 8 9 10] 的排列?
  • 原则上是的,但是那些已经被删除了。在“心理行”中,排列由构造处理。
  • 所以解决方案只需要处理“心理”列的排列,对吧?
  • 是的,完全正确。如果我将数字序列转换为整数(例如 1 2 3 4 映射到 10203040 或类似的东西),我原则上可以将此问题映射到您之前链接的问题上,然后通过排序和“唯一”来消除排列。但这似乎有点乏味
  • 相关问题:Find permutations of rows in matrix(虽然不能解决这个具体问题)

标签: matlab permutation


【解决方案1】:

假设您的行存储在矩阵A 中,列集宽度存储在len 中(在您的情况下为len = [4, 3, 3])。首先,我们应该在一个元胞数组中正确地表示这些数据:

X = mat2cell(A, ones(size(A, 1), 1), len);

然后我们在这样一个元胞数组中找到所有可能的列组合(不重复):

cols = perms(1:numel(len));

现在,给定来自X 的两行,索引为r1r2,我们检查一个是否是另一个的排列(ie 重新排序的“心理”列):

any(arrayfun(@(n)isequal(X(r1, :), X(r2, cols(n, :))), 1:size(cols, 1)))

接下来,我们现在可以找到所有可能的行对(不重复),并为每对行检查它们是否是彼此的排列:

rows = nchoosek(1:size(A, 1), 2);
N = size(cols, 1);
isperm = @(ii, jj)any(arrayfun(@(n)isequal(X(ii, :), X(jj, cols(n, :))), 1:N));
remove_idx = arrayfun(isperm, rows(:, 1), rows(:, 2));

删除它们就像馅饼一样简单:

A(remove_idx, :) = [];

示例

让我们将以下数据作为输入:

A = [1:10; 11:20; 1:4 8:10 5:7];
len = [4 3 3];

即:

A =
    1    2    3    4    5    6    7    8    9   10
   11   12   13   14   15   16   17   18   19   20
    1    2    3    4    8    9   10    5    6    7

len =
   4   3   3

并运行以下代码:

X = mat2cell(A, ones(size(A, 1), 1), len);
cols = perms(1:numel(len))
rows = nchoosek(1:size(A, 1), 2)
N = size(cols, 1)
isperm = @(ii, jj)any(arrayfun(@(n)isequal(X(ii, :), X(jj, cols(n, :))), 1:N));
remove_idx = arrayfun(isperm, rows(:, 1), rows(:, 2));
A(remove_idx, :) = [];

结果是:

remove_idx =
   0
   1
   0

A =
    1    2    3    4    5    6    7    8    9   10
    1    2    3    4    8    9   10    5    6    7

【讨论】:

  • 很高兴为您提供帮助 :) 请记住,arrayfun 可能会很慢,但对于大型矩阵,您应该考虑将其替换为 for 循环(这可能会更好地通过 JIT 加速)...
【解决方案2】:

这并不比将数字转换为数字序列好多少。但这是相同的想法,即将数字组映射到唯一标识符。这是我的代码。

M=[1 2 3 4 5 6 7 8 9 10;1 2 3 4 8 9 10 5 6 7;5 6 7 8 9 10 11 1 2 3;5 6 7 8 1 2 3 9 10 11];
%chop matrix into mental columns
M4=M(:,1:4);
M3=[M(:,5:7);M(:,8:10)]; % stack the 3s together

[u_M4,ia_M4,ic_M4]=unique(M4,'rows');% give each unique row of 4 a one digit id 
[u_M3,ia_M3,ic_M3]=unique(M3,'rows');% give each unique row of 3 a one digit id 
idx3=[ic_M3(1:length(ic_M3)/2) ic_M3(length(ic_M3)/2+1:end)]; % reshape the ids for the 3 so it matches the original format
sort_idx3=sort(idx3,2); % sort
idx=[ic_M4 sort_idx3]; % construct the idx matrix consist of the one digit ids
[u_idx,ia_idx,ic_idx]=unique(idx,'rows'); %find of unique id ROWs (that's why we need to sort before)
R=M(ia_idx,:); % now filter the original matrix 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-08
    • 1970-01-01
    • 1970-01-01
    • 2013-12-14
    • 2011-01-26
    • 1970-01-01
    相关资源
    最近更新 更多