【问题标题】:Split matrix based on number in first column根据第一列中的数字拆分矩阵
【发布时间】:2012-09-18 18:42:26
【问题描述】:

我有一个具有以下形式的矩阵:

M = 
[1 4 56 1;
 1 3 5  1;
 1 3 6  4;
 2 3 5  0;
 2 0 0  0;
 3 1 2  3;
 3 3 3  3]

我想根据第一列中给出的数字拆分这个矩阵。所以我想把矩阵拆分成这样:

A = 
[1 4 56 1;
 1 3 5  1;
 1 3 6  4]

B = 
[2 3 5  0;
 2 0 0  0]

C =
[3 1 2  3;
 3 3 3  3]

我通过创建以下循环进行了尝试,但这给了我所需的带有零行的矩阵:

for i = 1:length(M)
    if (M(i,1) == 1)
        A(i,:) = M(i,:);
    elseif (M(i,1) == 2)
        B(i,:) = M(i,:);
    elseif (M(i,1) == 3)
        C(i,:) = M(i,:);
    end
end

矩阵 C 的结果例如是:

C = 
[0 0 0 0;
 0 0 0 0;
 0 0 0 0;
 2 3 5 0;
 2 0 0 0]

我应该如何解决这个问题?

其他信息:
实际数据的第一列中有日期,格式为yyyymmdd。该数据集跨越数年,我想将此数据集拆分为矩阵,用于每年和之后的每个月。

【问题讨论】:

    标签: matlab matrix


    【解决方案1】:

    你可以使用arrayfun来解决这个任务:

    M = [
    1 4 56 1;
     1 3 5  1;
     1 3 6  4;
     2 3 5  0;
     2 0 0  0;
     3 1 2  3;
     3 3 3  3]
    
    
    A = arrayfun(@(x) M(M(:,1) == x, :), unique(M(:,1)), 'uniformoutput', false)
    

    结果A 是一个元胞数组,其内容可以按如下方式访问:

    >> a{1}
    
    ans =
    
         1     4    56     1
         1     3     5     1
         1     3     6     4
    
    >> a{2}
    
    ans =
    
         2     3     5     0
         2     0     0     0
    
    >> a{3}
    
    ans =
    
         3     1     2     3
         3     3     3     3
    

    要在第一列中根据 yyyymmdd 格式拆分数据,可以使用以下命令:

    yearly = arrayfun(@(x) M(floor(M(:,1)/10000) == x, :), unique(floor(M(:,1)/10000)), 'uniformoutput', false)
    
    monthly = arrayfun(@(x) M(floor(M(:,1)/100) == x, :), unique(floor(M(:,1)/100)), 'uniformoutput', false)
    

    【讨论】:

    • +1 非常重要的一点是结果是一个 CELL 数组。当单个单元格数组就足够时,不要努力创建数以亿计的命名数组。这将使您更轻松地处理数据。
    【解决方案2】:

    如果您不知道您将拥有多少个输出,将数据放入cell array 而不是单独的数组是最方便的。执行此操作的命令是 MAT2CELL。请注意,这假设您的数据已排序。如果在运行代码之前没有使用sortrows

    %# count the repetitions
    counts = hist(M(:,1),unique(M(:,1));
    
    %# split the array
    yearly = mat2cell(M,counts,size(M,2))
    
    %# if you'd like to split each cell further, but still keep
    %# the data also grouped by year, you can do the following
    %# assuming the month information is in column 2
    yearByMonth = cellfun(@(x)...
        mat2cell(x,hist(x(:,2),unique(x(:,2)),size(x,2)),...
        yearly,'uniformOutput',false);
    

    然后您将以yearByMonth{3}{4} 的身份访问第 3 年第 4 个月的数据

    编辑 如果你的数据的第一列是yyyymmdd,我建议把它分成三列yyyy,mm,dd,如下图,方便以后分组:

    ymd = 20120918;
    yymmdd = floor(ymd./[10000 100 1])
    yymmdd(2:3) = yymmdd(2:3)-100*yymmdd(1:2)
    

    【讨论】:

    • 它适用于我的示例,但在我的附加信息中,我声明我的实际数据的第一列包含格式为 yyyymmdd 的数据。如果我对这些数据进行分类,我将获得每日数据,而不是每年。
    • @BartArondson:我已经添加了关于拆分第一列中的数字的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-29
    • 1970-01-01
    • 1970-01-01
    • 2016-05-13
    • 1970-01-01
    相关资源
    最近更新 更多