如何使用第一列作为索引从单个矩阵创建矩阵数组?
Posted
技术标签:
【中文标题】如何使用第一列作为索引从单个矩阵创建矩阵数组?【英文标题】:How can I create an array of matrices from a single matrix by using first column as index? 【发布时间】:2017-03-19 15:04:47 【问题描述】:假设,我有以下矩阵,
1 2 3 4 5 6 7 8
2 3 4 5 6 7 8 1
3 4 5 6 7 8 1 2
4 5 6 7 8 1 2 3
1 8 7 6 5 4 3 2
2 7 6 5 4 3 2 9
3 6 5 4 3 2 9 8
4 5 4 3 2 9 8 7
我想创建一个由 4 个矩阵组成的数组,按照列 #1 进行分类。
例如,输出应该如下所示,
[
2 3 4 5 6 7 8
8 7 6 5 4 3 2
3 4 5 6 7 8 1
7 6 5 4 3 2 9
4 5 6 7 8 1 2
6 5 4 3 2 9 8
5 6 7 8 1 2 3
5 4 3 2 9 8 7
]
我的目标是将this Parzen function 应用于他们每个人。
是不是像下面这样?
function [retval] = bayes (train, test)
classCounts = rows(unique(train(:,1)));
pdfmx = ones(rows(test), classCounts);
variance = 0.25;
pdf = parzen(train(:,2:end), test(:,2:end), variance);
for cl=1:classCounts
clidx = train(:,1) == cl;
mu(:,cl) = train(clidx,2:end);
end
retval = mu;
endfunction
此代码正在生成以下错误,
>> bayes(mat, mat)
error: bayes: A(I,J,...) = X: dimensions mismatch
error: called from
bayes at line 11 column 12
>>
【问题讨论】:
【参考方案1】:这是accumarray
的经典工作。它输出一个元胞数组,但我建议您继续使用 3D 矩阵。
%// data
A = [1 2 3 4 5 6 7 8
2 3 4 5 6 7 8 1
3 4 5 6 7 8 1 2
4 5 6 7 8 1 2 3
1 8 7 6 5 4 3 2
2 7 6 5 4 3 2 9
3 6 5 4 3 2 9 8
4 5 4 3 2 9 8 7]
%// input
groupid = A(:,1); %// group identifier
rowidx = 1:size(A,1); %// row index
%// accumarray
cellArray = accumarray(groupid(:),rowidx (:),[],@(x) A(x,2:end))
%// transform cell array to 3D-Matrix
threeDArray = cat(3,cellArray:)
说明
accumarray
是什么?
vals = rowidx
的所有元素与相同的subs = groupid
组合起来并执行操作。
由于您想对矩阵的行而不是单个向量执行操作,但需要向量输入,您可以通过实际引入行索引作为输入来“欺骗”accumarray,而不是在函数中使用 apply
A(x,2:end)
表示您将所有rowidx
与存储在x
中的相同groupid
一起使用,并使用它来访问您的矩阵A
,您将
放在周围以获得单元格数组输出
cellArray1 =
8 7 6 5 4 3 2
2 3 4 5 6 7 8
cellArray2 =
7 6 5 4 3 2 9
3 4 5 6 7 8 1
cellArray3 =
6 5 4 3 2 9 8
4 5 6 7 8 1 2
cellArray4 =
5 4 3 2 9 8 7
5 6 7 8 1 2 3
threeDArray(:,:,1) =
8 7 6 5 4 3 2
2 3 4 5 6 7 8
threeDArray(:,:,2) =
7 6 5 4 3 2 9
3 4 5 6 7 8 1
threeDArray(:,:,3) =
6 5 4 3 2 9 8
4 5 6 7 8 1 2
threeDArray(:,:,4) =
5 4 3 2 9 8 7
5 6 7 8 1 2 3
如果输出中的行顺序很重要,则需要accumarray
的“稳定版本”(受this answer 启发:
%// stabilize accumarray
sz = max(groupid,[],1);
[~, I] = sort(groupid*cumprod([1,sz(1:end-1)]).');
%// stable accumarray
cellArray = accumarray(groupid(I,:),rowidx(I),[],@(x) A(x,2:end))
cellArray1 =
2 3 4 5 6 7 8
8 7 6 5 4 3 2
cellArray2 =
3 4 5 6 7 8 1
7 6 5 4 3 2 9
cellArray3 =
4 5 6 7 8 1 2
6 5 4 3 2 9 8
cellArray4 =
5 6 7 8 1 2 3
5 4 3 2 9 8 7
threeDArray(:,:,1) =
2 3 4 5 6 7 8
8 7 6 5 4 3 2
threeDArray(:,:,2) =
3 4 5 6 7 8 1
7 6 5 4 3 2 9
threeDArray(:,:,3) =
4 5 6 7 8 1 2
6 5 4 3 2 9 8
threeDArray(:,:,4) =
5 6 7 8 1 2 3
5 4 3 2 9 8 7
【讨论】:
cellArray = accumarray(subs(:),vals(:),[],@(x) A(x,2:end))
这很难理解。
@anonymous 看看我的编辑,连同文档,现在应该更清楚了以上是关于如何使用第一列作为索引从单个矩阵创建矩阵数组?的主要内容,如果未能解决你的问题,请参考以下文章
使用pandas创建稀疏矩阵,并使用来自.dat文件的其他两列的索引[x,y]的.dat文件的一列中的值填充它