2015-02-11 91 views
4

有沒有一種簡單的(理想情況下沒有多個for循環)的方式來根據Matlab中的一組類別對值向量進行分組?Matlab將柱狀數據轉換爲ndarray

我有數據矩陣形式

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}) 

,但我無法捉摸如何使它做我想要的東西!

回答

2

這也是一團糟,但工作。它採用ND陣列方式。

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 

在你的例子,結果如下四維陣列:

>> 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 
+0

不錯,我起初試過這個,但是被每個標籤部分的累計計數卡住了。 @SanjayManohar這可能是更好的解決方案... – Dan 2015-02-11 15:54:38

+0

@丹謝謝。您的解決方案實際上在內存方面效率更高,因爲它提供了單元陣列而不是N-D陣列 – 2015-02-11 15:58:58

+1

Perfect。還要感謝我介紹「unique」的第三個輸出。 'ind'最終告訴每個項目「去哪裏」,這真是可愛。 – 2015-02-11 16:01:25

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]

+1

哇 - 哇!這真是太神奇了。完美的作品。我會花一些時間研究你的代碼。 Accumarray非常強大。 – 2015-02-11 15:54:06

+0

你真的需要'sz'作爲單元陣列嗎?你只用它作爲'[sz {:}]' – 2015-02-11 15:55:48

+0

@LuisMendo我想不是那麼... – Dan 2015-02-11 15:56:36