【问题标题】:Matlab convert columnar data into ndarrayMatlab将列数据转换为ndarray
【发布时间】:2015-02-11 14:54:12
【问题描述】:

有没有一种简单(最好没有多个 for 循环)的方法来根据 Matlab 中的一组类别对值向量进行分组?

表格中有数据矩阵

CATEG_A    CATEG_B   CATEG_C  ...   VALUE

   1          1        1      ...   0.64
   1          2        1      ...   0.86
   1          1        1      ...   0.74
   1          1        2      ...   0.56
  ...

等等

而我想要的是一个N维数组

 all_VALUE( CATEG_A, CATEG_B, CATEG_C, ..., index ) = VALUE_i

当然,同一类别组合中可能有任意数量的值,因此size(end) 将是最大类别中的值的数量——其余项目将用nan 填充。

或者我会很高兴

 all_VALUE { CATEG_A, CATEG_B, CATEG_C, ... } ( index )

即向量元胞数组。我想这有点像创建一个数据透视表,但有 n 维,而不是计算 mean

我在帮助中找到了这个功能

A = accumarray(subs,val,[],@(x) {x})

但我不知道如何让它做我想做的事!

【问题讨论】:

    标签: matlab cell-array n-dimensional


    【解决方案1】:

    这也是一团糟,但有效。它采用 ND-array 方式。

    X = [1        1        1        0.64
         1        2        1        0.86
         1        1        1        0.74
         1        1        2        0.56]; %// data
    N = size(X,1); %// number of values
    [~, ~, label] = unique(X(:,1:end-1),'rows'); %// unique labels for indices
    cumLabel = cumsum(sparse(1:N, label, 1),1); %// used for generating a cumulative count
        %// for each label. The trick here is to separate each label in a different column
    lastInd = full(cumLabel((1:N).'+(label-1)*N)); %'// pick appropriate values from 
        %// cumLabel to generate the cumulative count, which will be used as last index
        %// for the result array
    sizeY = [max(X(:,1:end-1),[],1) max(lastInd)]; %// size of result
    Y = NaN(sizeY); %// initiallize result with NaNs
    ind = mat2cell([X(:,1:end-1) lastInd], ones(1,N)); %// needed for comma-separated list
    Y(sub2ind(sizeY, ind{:})) = X(:,end); %// linear indexing of values into Y
    

    您的示例中的结果是以下 4D 数组:

    >> Y
    Y(:,:,1,1) =
        0.6400    0.8600
    Y(:,:,2,1) =
        0.5600       NaN
    Y(:,:,1,2) =
        0.7400       NaN
    Y(:,:,2,2) =
       NaN   NaN
    

    【讨论】:

    • 很好,我一开始尝试了这个,但被每个标签部分的累积计数卡住了。 @SanjayManohar 这可能是更好的解决方案...
    • @Dan 谢谢。您的解决方案实际上在内存方面更有效,因为它提供了元胞数组而不是 N-D 数组
    • 完美。也感谢您向我介绍unique 的第三个输出。 ind 最终告诉每个项目“去哪里”真是太可爱了。
    【解决方案2】:

    这是一团糟,但这里有一个解决方案

    [U,~,subs] = unique(X(:,1:end-1),'rows');
    
    sz = max(U);
    Uc = mat2cell(U, size(U,1), ones(1,size(U,2)));
    %// Uc is converted to cell matrices so that we can take advantage of the {:} notation which returns a comma-separated-list which allows us to pass a dynamic number of arguments to functions like sub2ind
    
    I = sub2ind(sz, Uc{:});
    
    G = accumarray(subs, X(:,end),[],@(x){x});
    
    A{prod(max(U))} = [];  %// Pre-assign the correct number of cells to A so we can reshape later
    A(I) = G;
    reshape(A, sz)
    

    在您的示例数据(忽略...s)上返回:

    A(:,:,1) = 
    
        [2x1 double]    [0.8600]
    
    
    A(:,:,2) = 
    
        [0.5600]    []
    

    其中A(1,1,1)[0.74; 0.64]

    【讨论】:

    • 哇——哇!这真是太神奇了。完美运行。我会花一些时间研究你的代码。 Accumarray 非常强大。
    • 你真的需要sz 成为一个元胞数组吗?你只用[sz{:}]
    • @SanjayManohar accumarray 绝对是非常强大的。它在 StackOverflow-matlab 有很多粉丝 :-)
    猜你喜欢
    • 2013-11-16
    • 2017-03-10
    • 2021-08-09
    • 2015-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-05
    • 1970-01-01
    相关资源
    最近更新 更多