【问题标题】:Histogram along one dimension in MATLABMATLAB中沿一维的直方图
【发布时间】:2016-01-22 05:40:39
【问题描述】:

假设我有一个N×M 矩阵A。我想为A 的每一列计算直方图。天真的方法是做这样的事情:

edges = 0:5:100;
counts = zeros(numel(edges) - 1, M);
for i_c = 1:M
  counts(:, i_c) = histcounts(A(:, i_c), edges);
end

有没有更好(更快)的方法来做到这一点?

编辑:添加一些性能测试

好的,让我们做一些测试。首先是histcounts + 循环,然后是使用arrayfun 和索引向量的替代方案,然后是btmcnellis/randomGuy 的解决方案cellfun,最后是obchardon 的解决方案使用histc。 对于长列,histcount 似乎更有效。但是对于较短但较多的列,histc 的优势很大!

niter = 10;

M = 100;
N = 10000;

A = rand(M, N);
edges = 0:.05:1;


counts1 = zeros(numel(edges) - 1, N);
counts2 = zeros(numel(edges) - 1, N);
counts3 = zeros(numel(edges) - 1, N);
counts4 = zeros(numel(edges), N);

tic;
for i_r = 1:niter
    for i_c = 1:N
        counts1(:, i_c) = histcounts(A(:, i_c), edges);
    end
end
toc

tic;
for i_r = 1:niter
    counts2 = cell2mat(arrayfun(@(ind) histcounts(A(:, ind), edges), 1:size(A, 2), 'UniformOutput', 0)')';
end
toc

tic;
for i_r = 1:niter
    Acell = num2cell(A, 1);
    counts3 = cell2mat(cellfun(@(column) histcounts(column, edges), Acell, 'UniformOutput', 0)')';
end
toc

tic;
for i_r = 1:niter
    counts4 = histc(A, edges, 1);
end
toc

all(counts1(:) == counts2(:))
all(counts1(:) == counts3(:))
counts4 = counts4(1:numel(edges)-1, :); % histc has an extra bin
all(counts1(:) == counts4(:))

实际测试:

niter = 100; 
M = 10000;
N = 100;

经过的时间是 2.423785 秒。
经过的时间是 2.730303 秒。
经过的时间是 3.774217 秒。
经过的时间是 2.721766 秒。

niter = 10;
M = 100;
N = 10000;

经过的时间是 5.438335 秒。
经过的时间是 7.387587 秒。
经过的时间是 7.647818 秒。
经过的时间是 0.276491 秒。

【问题讨论】:

  • 在您的实际情况中edges 是否也是0:5:100
  • @Divakar 我不想排除其他值,但是您对这种特殊情况的建议是什么?
  • 好吧,我试图以5 的渐进步长为阈值,然后在沿列的循环中使用 accumarray,但这似乎很慢。所以,我想,选择histchistcounts

标签: matlab histogram


【解决方案1】:

您可以使用:histc

x = [0:5:100];
y = histc(A,x, dim); 

其中dim 是沿其计数的维度。

然后

hist(y(:,1),x);
hist(y(:,2),x);
...

【讨论】:

  • 我完全忘记了使用histc ...在discouraged instances of histc上,他们实际上建议用循环替换我的用例中的histc..
  • @zeeMonkeez:但请记住,代码更紧凑但(我想)更慢。 Histcount 可能更有效。
  • 我的简短测试表明,实际上,histc 和循环的histcounts 花费的时间完全相同……我会用测试结果更新问题。
  • 我测试了(在 100x100000 矩阵上),我用histc 获得了 1.6 秒,用你的histcounts 循环获得了 0.4 秒。所以我们或许应该相信数学家们。
【解决方案2】:

将数组 A 拆分为一个元胞数组,其中每个元胞都是矩阵中的一列:

Acell = [mat2cell(A',ones(1,M))]';

将使用cellfun的函数应用到元胞数组Acell的每个元胞

counts = cellfun(@(x)histcounts(x,edges),Acell);

counts 将是一个单元格数组,每个单元格都包含来自 A 的相应列的 histcounts。

【讨论】:

    【解决方案3】:

    您可以使用num2cellcellfun,虽然我不知道这与简单方法的性能相比如何。

    num2cell 默认情况下采用矩阵并将其转换为元胞数组,其中每个元胞包含矩阵的一个元素,但传递第二个参数允许您沿特定维度执行此操作。所以对于 2x3 矩阵 Anum2cell(A, 1) 将返回一个 1x3 元胞数组,其中每个元胞包含一个 2×1 列的 A。

    cellfun 将函数应用于单元格的每个元素。因此,在这种情况下,您可以像上面一样从num2cell 获取单元格数组C 输出,并将 histcounts 应用于A 的每一列,如下所示:

    counts = cellfun(@(column) histcounts(column, edges), C);
    

    counts 应该是一个 3 元素数组,其中第 i 个元素包含 A 的第 i 列的 histcounts 结果。

    (请注意,上面的@() 语法是anonymous function.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-04
      • 2018-02-05
      • 1970-01-01
      相关资源
      最近更新 更多