2013-10-30 55 views
2

我有a=[1 2 3 1 4 2 5]'矢量的發生數量

我想創建一個新的載體,這將使每一行,該元素在的發生數的向量。例如,對於這個矩陣,結果將是[1 1 1 2 1 2 1]':第四個元素是2,因爲這是第一次重複1。

我能看到實現這一目標的唯一方法是創建一個零向量,其行數將是唯一元素的數量(這裏是:c = [0 0 0 0 0],因爲我有5個元素)。 我還創建了一個與a相同長度的零矢量d。然後,通過矢量a,向我們讀取的元素的c行添加一個,並將相應的c數添加到d的當前行。

任何人都可以考慮更好的東西嗎?

回答

9

這是做的很好的方式

C=sum(triu(bsxfun(@eq,a,a.'))) 

我的第一個建議是這樣的,一個不是很好for

for i=1:length(a) 
    F(i)=sum(a(1:i)==a(i)); 
end 
+0

這確實是for循環,但這比我做的更好,更簡單! – teaLeef

+0

我添加了一個可能更有效的不同方法。 – David

+0

+1使用'triu'。非常聰明!如果你跳過B,你甚至可以把它變成一行代碼。 – nispio

4

這你想要做什麼,沒有循環:

m = max(a); 
aux = cumsum([ ones(1,m); bsxfun(@eq, a(:), 1:m) ]); 
aux = (aux-1).*diff([ ones(1,m); aux ]); 
result = sum(aux(2:end,:).'); 
4

我的第一個想法:

M = cumsum(bsxfun(@eq,a,1:numel(a))); 
v = M(sub2ind(size(M),1:numel(a),a')) 
4

在完全不同的級別上,您可以查看tabulate以獲取有關值的頻率的信息。例如:

tabulate([1 2 4 4 3 4]) 

    Value Count Percent 
    1  1  16.67% 
    2  1  16.67% 
    3  1  16.67% 
    4  3  50.00% 
+5

謝謝,我不知道「表格」。如果這回答了問題,我會給+1。 :) – nispio

0

請注意,由大衛,chappjc和路易斯Mendo提出的解決方案是美麗的,但如果向量是大無法使用。在這種情況下,幾個天真的方法是:

% Big vector 
a = randi(1e4, [1e5, 1]); 
a1 = a; 
a2 = a; 

% Super-naive solution 
tic 
x = sort(a); 
x = x([find(diff(x)); end]); 
for hh = 1:size(x, 1) 
    inds = (a == x(hh)); 
    a1(inds) = 1:sum(inds); 
end 
toc 

% Other naive solution 
tic 
x = sort(a); 
y(:, 1) = x([find(diff(x)); end]); 
y(:, 2) = histc(x, y(:, 1)); 
for hh = 1:size(y, 1) 
    a2(a == y(hh, 1)) = 1:y(hh, 2); 
end 
toc 

% The two solutions are of course equivalent: 
all(a1(:) == a2(:)) 

其實,現在的問題是:我們能避免最後的循環?也許使用arrayfun?