基于多列对矩阵的行进行分组

时间:2016-06-13 14:56:51

标签: matlab matrix

我有一个矩阵A,其中包含第一列user_id,第二列year,第三列month,第四列day

 A=[0 2010 10 19; 
    0 2010 10 19; 
    0 2010 10 18; 
    0 2010 10 18; 
    0 2010 10 17; 
    0 2010 10 17; 
    0 2010 9 20; 
    0 2010 9 19; 
    0 2010 9 19; 
    0 2010 9 19]

我想根据月和日划分这些数据。我怎么能在MATLAB中做到这一点?

3 个答案:

答案 0 :(得分:4)

您可以使用unique按月和日(第3列和第4列)对每一行进行分组,然后使用splitapply对共享一个月/天的每组行执行操作。我们要执行的操作是简单地将它们放入单元格数组中:@(x){x}。以下代码可以实现此目的。

% Assign each unique month/day combination an ID
[~, ~, inds] = unique(A(:,[3 4]), 'rows');

% Divide up the rows based upon this ID
groups = splitapply(@(x){x}, A, inds);

celldisp(groups)

的结果
groups{1} =
           0        2010           9          19
           0        2010           9          19
           0        2010           9          19
groups{2} =
           0        2010           9          20
groups{3} =
           0        2010          10          17
           0        2010          10          17
groups{4} =
           0        2010          10          18
           0        2010          10          18
groups{5} =
           0        2010          10          19
           0        2010          10          19

话虽这么说,你可以在没有实际将数据分成不同部分的情况下进行分析。由于MATLAB针对矩阵运算进行了优化,因此这可能会更高效。

有关splitapply的更多信息,并对您的数据进行分组here

答案 1 :(得分:3)

如果你有版本R2015b,函数splitapply是一个很好的函数(实际上我从来没有听说过这个函数)。如果您没有这项功能,那么拨打accumarray可能是谨慎的。在使用唯一ID分配每个唯一月份和日期时使用相同的逻辑,您可以使用accumarray查找共享相同ID的行位置,然后通过使用这些行位置切片并返回来访问矩阵并返回元素的单元格数组中每个ID的矩阵子集,非常类似于splitapply

这样的事情可行:

% Assign each unique month/day combination an ID
% From Suever
[~,~,inds] = unique(A(:,[3 4]), 'rows');

% Divide up the rows based upon this ID
groups = accumarray(inds, (1:size(A,1)).', [], @(x) {A(x,:)});

我们得到:

>> format compact
>> celldisp(groups)
groups{1} =
           0        2010           9          19
           0        2010           9          19
           0        2010           9          19
groups{2} =
           0        2010           9          20
groups{3} =
           0        2010          10          17
           0        2010          10          17
groups{4} =
           0        2010          10          18
           0        2010          10          18
groups{5} =
           0        2010          10          19
           0        2010          10          19

答案 2 :(得分:3)

这是另一种方法:

  1. 根据相应的列对A行进行排序;
  2. 根据这些列中任何值的变化检测块大小;
  3. 根据这些尺寸拆分已排序的矩阵。
  4. 代码:

    key = [3 4]; % columns used as key for splitting
    As = sortrows(A, [3 4]); % sort based on that (step 1)
    chunks = diff([0; find(any(diff(As(:, [3 4]), [], 1), 2)); size(A,1)]); % sizes (step 2)
    result = mat2cell(As, chunks, size(A,2)); % split with those sizes (step 3)
    

    使用您的示例数据

    A = [0 2010 10 19; 
         0 2010 10 19; 
         0 2010 10 18; 
         0 2010 10 18; 
         0 2010 10 17; 
         0 2010 10 17; 
         0 2010 9 20; 
         0 2010 9 19; 
         0 2010 9 19; 
         0 2010 9 19];
    

    这给出了

    >> celldisp(result)
    result{1} =
               0        2010           9          19
               0        2010           9          19
               0        2010           9          19
    result{2} =
               0        2010           9          20
    result{3} =
               0        2010          10          17
               0        2010          10          17
    result{4} =
               0        2010          10          18
               0        2010          10          18
    result{5} =
               0        2010          10          19
               0        2010          10          19