2017-02-02 75 views
0

我在Matlab一個矩陣A:分組通過嵌套唯一值

A = [176 5406 1 4 7903; 
    155 5406 1 5 7903; 
    122 5407 0 4 7903; 
    140 5407 0 5 7904; 
    130 5407 0 3 7904]; 

只爲信息 - 第2欄是一個用戶ID,而將第四列是時間。所以5406是一個用戶,5407是另一個用戶。這兩個用戶都有一些信息存儲在我有興趣訪問的第一列和第四列中。

所以基本上我想要做的是:

  1. 對於每個用戶把他們的價值的中位數在第一列。我已經編寫了代碼(如下),適用於此。

  2. 如果在每個用戶5列兩個相等的「時間」值,那麼我想在平均4列的值,所以像用戶5406時間值均爲7903,我想平均值的在第4欄 - 即45的平均值以一個值(4.5)結尾。

但是例如用於下一用戶5407我將具有兩個最終值 - 一個將是5和3的平均值(因爲7904重複)和一個將4(因爲7903不重複)。

我對如何做到這一點有點困惑,我知道需要有某種if聲明,但我一直堅持它的很長一段時間。誰能幫忙?

感謝

規範第一部分:

u=unique(A(:,2)); 
for i=1:size(u,1) 
    M=find(A(i,2)==u(i)); 
    med(i)=median(A(M,1)); 
end 
+0

例如,我會使用邏輯索引來做第一件事,你可以使用:'median(A((A(:,2)== 5406),1))'爲第一個用戶,等等... – bla

+0

我剛剛爲這個問題的目的,使矩陣更小,但我有大約20,000用戶,我不能列出每一個...... –

+0

,但你可以循環在寫入這個例子...只是用'u(i)'來代替值5406 – bla

回答

1

您可以運行unique爲每個用戶(內循環)的時間值,並做了類似的子循環收集的獨特的平均值該用戶的時間戳。

但是,在這裏我認爲它更適合使用accumarray。在下面的第一個例子中,我修改了一下你的代碼。

% Get unique 
[user, ~, userIdx] = unique(A(:,2)); 
nUser = numel(user); 

% Allocate container for result 
med = zeros(nUser,1); 
men = cell(nUser,1); % <-- Need a cell since length of result could vary 

for i = 1:nUser 
    % Median of col #1 
    med(i) = median(A(userIdx == i, 1)); 

    % Mean of col #4 for unique times 
    [~, ~, timeIdx] = unique(A(userIdx == i, 5)); 
    men{i} = accumarray(timeIdx, A(userIdx == i, 4), [], @mean); 
end 

結果:

>> med = 
     165.5 
      130 

>> celldisp(men) 
men{1} = 
      4.5 
men{2} = 
      4 
      4 

要擠多一點,你可以採取獨特的時間,整個A和使用accumarray兩個

[~, ~, userIdx] = unique(A(:,2)); 
[~, ~, timeIdx] = unique(A(:,5)); 

med = accumarray(userIdx, A(:,1), [], @median); 
men = accumarray([userIdx timeIdx], A(:,4), [], @mean, NaN); 

這給men不作爲一個細胞,但是一個矩陣。因此空格必須填寫(這裏我選擇NaN,因爲0可能是@mean的結果)。

men = 
      4.5   NaN 
      4   4 

如果你想把它當作一個細胞,而不NaN你可以只在行中循環,並挑選非NaN值,或僅發生在men計算的循環,或任何其他方式...

如果確定該列的A 4不含任何負數或零號(平均值不應該冒着被0),你可以收集men結果作爲稀疏矩陣,而不是

men = accumarray([userIdx timeIdx], A(:,4), [], @mean, 0, true); 
men = 
    (1,1)    4.5 
    (2,1)    4 
    (2,2)    4 
0

我沒有使用任何循環爲您的任務得到了另一個解決方案:

中值。

u=unique(A(:,2)); 
umedians = arrayfun(@(x) median (A(A(:,2)==x, 1)), u); 

說明:第一 找到所有的唯一用戶。然後使用arrayfun查找當前用戶的所有數據,併爲其中的每一個計算median。塔4

此任務的

平均值是有點困難。我們可以這樣:

temp = arrayfun(@(x) unique(A (A(:,2)==x,5)), u, 'UniformOutput',false); 
result = cellfun(@(y,z) arrayfun(@(x) mean(A(A(:,2) == u(z) & A(:,5) == x ,4)), ... 
      y, 'UniformOutput',false), temp , num2cell([1:size(u,1)]'), 'UniformOutput',false) 

說明:首先讓我們爲每個用戶找到所有獨特的時間。將其保存到單元陣列temp。現在我們需要爲每個細胞找到相同的時間並計算平均值。因此,讓我們使用cellfuntemp的每個單元格製作它,並使用arrayfun來計算mean

希望它有幫助!