简体   繁体   English

在MATLAB中沿一维直方图

[英]Histogram along one dimension in MATLAB

Assume I have an N×M matrix A . 假设我有一个N×M矩阵A I would like to compute the histogram for each column of A . 我想计算A每一列的直方图。 The naïve way would be to do something like this: 天真的方法是做这样的事情:

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

Is there a better (faster) way to do this? 有没有更好(更快)的方法?

Edit: Add some performance tests 编辑:添加一些性能测试

OK, let's do some testing. 好的,让我们做一些测试。 First histcounts + loop, then an alternative using arrayfun and an indexing vector, then btmcnellis / randomGuy 's solution with cellfun , finally obchardon 's solution using histc . 第一histcounts +循环,然后使用替代arrayfun和索引向量,然后btmcnellis / randomGuy的溶液与cellfun ,终于obchardon '使用氏溶液histc It seems like for long columns, histcount is more efficient. 似乎对于长列, histcount更有效。 But for shorter but many columns, histc wins by a great margin! 但是对于较短但很多的列, 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(:))

Actual tests: 实际测试:

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

Elapsed time is 2.423785 seconds. 经过的时间是2.423785秒。
Elapsed time is 2.730303 seconds. 经过的时间是2.730303秒。
Elapsed time is 3.774217 seconds. 经过的时间是3.774217秒。
Elapsed time is 2.721766 seconds. 经过的时间是2.721766秒。

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

Elapsed time is 5.438335 seconds. 经过的时间是5.438335秒。
Elapsed time is 7.387587 seconds. 经过的时间是7.387587秒。
Elapsed time is 7.647818 seconds. 经过的时间是7.647818秒。
Elapsed time is 0.276491 seconds. 经过的时间是0.276491秒。

You can use: histc 您可以使用: histc

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

where dim is the dimension along which to count. 其中dim是要计算的维度。

And then 接着

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

Split the array A into a cell array where each cell is a single column from the matrix: 将数组A拆分为一个单元格数组,其中每个单元格都是矩阵中的单个列:

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

Apply the function using cellfun to each cell of the cell array Acell 将使用cellfun的功能cellfun单元格数组Acell每个单元格

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

counts will be a cell array with each cell containing histcounts from the respective column of A. counts将是一个单元格数组,每个单元格包含来自A的相应列的历史记录。

You could use num2cell and cellfun , although I don't know how this compares with the naive method performance-wise. 您可以使用num2cellcellfun ,尽管我不知道这与幼稚的方法在性能方面的比较。

num2cell by default takes a matrix and converts it into a cell array where each cell contains one element of the matrix, but passing a second argument allows you to do so along a particular dimension. 默认情况下, num2cell接受一个矩阵并将其转换为一个单元格数组,其中每个单元格都包含矩阵的一个元素,但是传递第二个参数允许您沿特定维度进行操作。 So for 2x3 matrix A , num2cell(A, 1) will return a 1x3 cell array where each cell contains a 2-by-1 column of A. 因此,对于2x3矩阵Anum2cell(A, 1)将返回1x3单元格数组,其中每个单元格包含A的2×1列。

cellfun applies a function to each element of a cell. cellfun将函数应用于单元格的每个元素。 So in this case you could take a cell array C output from num2cell as above and apply histcounts to each column of A as follows: 因此,在这种情况下,您可以像上面那样从num2cell获取一个单元格数组C输出, num2cell应用于A每一列,如下所示:

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

counts should then be a 3-element array, where the i-th element contains the histcounts result for the i-th column of A . counts应该是一个3元素的数组,其中第i个元素包含A的第i个列的历史histcounts结果。

(Note that the @() syntax above is an anonymous function. ) (请注意,上面的@()语法是一个匿名函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM