[英]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. 您可以使用
num2cell
和cellfun
,尽管我不知道这与幼稚的方法在性能方面的比较。
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矩阵
A
, num2cell(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.