2016-01-21 126 views
1

假設我有一個N×M矩陣A。我想計算每列A的直方圖。天真的辦法是做這樣的事情:MATLAB中一維的直方圖

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

有沒有更好的(快)的方式來做到這一點?

編輯:添加一些性能測試

OK,讓我們做一些測試。第一個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秒。

+0

會'edges'是'0:5:在您的實際情況100'嗎? – Divakar

+0

@Divakar我不想排除其他值,但是你對這種特殊情況的建議是什麼? – zeeMonkeez

+0

那麼,我試圖在漸進式步長5的門檻,然後使用accumarray沿着列的循環,但似乎這很慢。所以,我想,用'histc'或'histcounts'去。 – Divakar

回答

1

您可以使用:histc

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

其中dim是沿着計算的尺寸。

然後

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

我完全忘記了'histc'的使用... ... [[不鼓勵histc的實例]](http://www.mathworks.com/help/matlab/creating_plots/replace-discouraged-instances-of-hist-and -histc.html)他們實際上建議在我的用例中用循環替換'histc' .. – zeeMonkeez

+0

@zeeMonkeez:但請記住,代碼更緊湊,但(我想)會更慢。 Histcount可能更有效。 – obchardon

+0

我的簡短測試表明,實際上'histc'和loop''的計數完全相同......我將用測試結果更新問題。 – zeeMonkeez

0

拆分陣列A分成單元陣列,其中每個小區是從矩陣的單個列:

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

應用使用cellfun所述函數應用於所述單元陣列的每個單元Acell

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

計數將是一個單元陣列,每個單元包含來自各個列A的記分。

0

你可以使用num2cellcellfun,雖然我不知道這是如何比較天真的方法性能明智。

num2cell默認採用矩陣並將其轉換爲單元格數組,其中每個單元格包含矩陣的一個元素,但傳遞第二個參數允許您沿特定維度這樣做。因此,對於2×3矩陣Anum2cell(A, 1)將其中每個單元包含A的2×1列

cellfun應用一個函數的小區的每個元素返回一個1×3單元陣列。因此,在這種情況下,你可能需要一個單元陣列C輸出從如上述num2cell並應用histcounts到的A每一列如下:

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

counts然後應該是一個3元素數組,其中第i個元素包含A第i列的histcounts結果。

(請注意,上述@()語法是anonymous function.