2017-02-02 76 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

希望它有帮助!