【问题标题】:In matlab, find the frequency at which unique rows appear in a matrix在matlab中,找到矩阵中唯一行出现的频率
【发布时间】:2015-06-14 11:28:10
【问题描述】:

在 Matlab 中,假设我有以下矩阵,它代表 10 个人的群体:

pop = [0 0 0 0 0; 1 1 1 0 0; 1 1 1 1 1; 1 1 1 0 0; 0 0 0 0 0; 0 0 0 0 0; 1 0 0 0 0; 1 1 1 1 1; 0 0 0 0 0; 0 0 0 0 0];

oneszeros 的行定义了 6 种不同的个人“类型”。

a = [0 0 0 0 0];
b = [1 0 0 0 0];
c = [1 1 0 0 0];
d = [1 1 1 0 0];
e = [1 1 1 1 0];
f = [1 1 1 1 1];

我想在pop 中定义abcdef 的比例/频率。

我想最终得到以下列表:

a = 0.5;
b = 0.1;
c = 0;
d = 0.2;
e = 0;
f = 0.2;

我能想到的一种方法是对行求和,然后计算每行出现的次数,然后排序和索引

sum_pop = sum(pop')';
x = unique(sum_pop);
N = numel(x);
count = zeros(N,1);
   for l = 1:N
      count(l) = sum(sum_pop==x(l));
   end
pop_frequency = [x(:) count/10];

但这并不能完全得到我想要的(即当频率 = 0 时),而且似乎必须有更快的方法?

【问题讨论】:

    标签: arrays matlab matrix


    【解决方案1】:

    我认为ismember 是最直接、最通用的方法。如果您的组更复杂,这将是要走的路:

    population = [0,0,0,0,0; 1,1,1,0,0; 1,1,1,1,1; 1,1,1,0,0; 0,0,0,0,0; 0,0,0,0,0; 1,0,0,0,0; 1,1,1,1,1; 0,0,0,0,0; 0,0,0,0,0];
    groups = [0,0,0,0,0; 1,0,0,0,0; 1,1,0,0,0; 1,1,1,0,0; 1,1,1,1,0; 1,1,1,1,1];
    
    [~, whichGroup] = ismember(population, groups, 'rows');
    freqOfGroup = accumarray(whichGroup, 1)/size(groups, 1);
    

    在您的特殊情况下,组可以用它们的总和来表示,所以如果这个通用解决方案不够快,请使用sum-histc 简化Luis used

    【讨论】:

      【解决方案2】:

      方法#1

      bsxfun -

      A = cat(1,a,b,c,d,e,f)
      out = squeeze(sum(all(bsxfun(@eq,pop,permute(A,[3 2 1])),2),1))/size(pop,1)
      

      输出 -

      out =
          0.5000
          0.1000
               0
          0.2000
               0
          0.2000
      

      方法 #2

      如果这些元素是二进制数,您可以将它们转换为decimal 格式。

      因此,pop 的十进制格式变为 -

      >> bi2de(pop)
      ans =
           0
           7
          31
           7
           0
           0
           1
          31
           0
           0
      

      而连接数组的A变成-

      >> bi2de(A)
      ans =
           0
           1
           3
           7
          15
          31
      

      最后,您需要将A 中的十进制格式的数字计数到pop 的数字中,这可以使用histc 来完成。这是代码-

      A = cat(1,a,b,c,d,e,f)
      out = histc(bi2de(pop),bi2de(A))/size(pop,1)
      

      输出 -

      out =
          0.5000
          0.1000
               0
          0.2000
               0
          0.2000
      

      【讨论】:

      • 我期待这个答案(第二部分):-) 我试图更快!
      • @LuisMendo 好吧,太可预测了:)
      • @Divakar 太好了,然后我可以删除我的答案。感谢您提供工作示例。 Imo,如果您与他人共享代码或与他人共享许可证,则应使用具有唯一性的解决方案。但是,唯一性并不是最快的功能,所以如果出现性能问题,我想可读性需要支持性能。然后可以将具有等效输出的代码添加为注释或文档。
      • @patrik 啊,刚刚看到您的编辑后,我正要删除我的第二种方法!如果您考虑取消删除您的,我不介意删除!
      • @patrik 我认为unique 会很快解决这个问题,但我们再次处理'rows' 选项,所以我不太确定。
      【解决方案3】:

      unique 中有一些功能可以用于此目的。如果

      [q,w,e] = unique(pop,'rows');
      

      q是唯一行的矩阵,w是矩阵中最先出现的行的索引。第三个元素e 包含q 的索引,因此pop = q(e,:)。有了这个,剩下的问题应该是直截了当的。 e中某个值的概率应该是该行出现在pop中的概率。

      计数可以通过histc完成

      histc(e,1:max(e))/length(e)
      

      并且可以找到未出现的行

      ismember(a,q,'rows')
      

      当然还有其他方法,也许(可能)更快的方法,或者单线。为什么我发布这个是因为它提供了一种易于理解、可读且不需要任何特殊工具箱的方式。

      编辑 这个例子给出了预期的输出

      a = [0,0,0,0,0;1,0,0,0,0;1,1,0,0,0;1,1,1,0,0;1,1,1,1,0;1,1,1,1,1]; % catenated a-f
      [q,w,e] = unique(pop,'rows');
      prob = histc(e,1:max(e))/length(e);
      out = zeros(size(a,1),1);
      out(ismember(a,q,'rows')) = prob;
      

      【讨论】:

      • 这很棒,因为它适用于更一般的情况并且具有最佳复杂性!
      【解决方案4】:

      您可以使用pdist2(统计工具箱)获取所有频率:

      indiv = [a;b;c;d;e;f]; %// matrix with all individuals
      result = mean(pdist2(pop, indiv)==0, 1);
      

      在您的示例中,这给出了

      result =
          0.5000    0.1000         0    0.2000         0    0.2000
      

      同样,您可以使用bsxfun 手动计算pdist2(pop, indiv)==0,如Divakar's answer


      对于您示例中的特定个人(可以通过数量来识别),您也可以这样做

      result = histc(sum(pop, 2), 0:size(pop,2)) / size(pop,1);
      

      【讨论】:

      • 我喜欢histc,因为它具有最佳的复杂性!
      猜你喜欢
      • 1970-01-01
      • 2014-08-26
      • 1970-01-01
      • 2014-10-01
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多