假设我有一个包含3列的矩阵:c1
,c2
,c3
,我想创建一个新矩阵,其中每列是其中两列的任何可能产品这个矩阵的列。
所以,如果我有一个 d 列的矩阵,我想用 d + d(d-1)/ 2 + d 列创建一个新矩阵。例如,考虑具有3列c1
,c2
,c3
的矩阵。我要创建的矩阵应包含c1
,c2
,c3
,c1xc2
,c2xc3
,c1xc3
,{{列1}},c1^2
和c2^2
。
有没有有效的方法呢?
答案 0 :(得分:4)
我很尴尬发布这个 - 我敢肯定必须有一个更简单的方法(有一个很多更简单的方式 - 请参阅我在答案底部的12月更新),但是这个将完成这项工作:
A = [1 2 3; 4 5 6];
n = size(A, 2);
B = A(:, reshape(ones(n, 1) * (1:n), 1, n^2)) .* repmat(A, 1, n);
Soln = [A, B(:, logical(reshape(tril(toeplitz(ones(n, 1))), 1, n^2)'))];
计算效率不高,因为在B
步骤中我实际上计算了我需要的组合数量的两倍(即我得到c1。* c1,c1。* c2,c1。* c3,c2。 * c1,c2。* c2,c2。* c3,c3。* c1,c3。* c2,c3。* c3),然后在第二步中我只抽出我需要的列(例如我摆脱了c3。* c1因为我已经有了c1。* c3等等。
更新:刚刚开车,我发现了一个更好的方法。您只需构建两个形式为I1 = [1 1 1 2 2 3]
和I2 = [1 2 3 2 3 3]
的索引向量,然后(A(:, I1) .* A(:, I2))
将为您提供所有列产品。我现在离开了我的计算机,但稍后会回来并找出构建索引向量的一般方法。我认为使用tril(toeplitz)
构造可以很容易地完成它。干杯。将在几个小时内更新。
更新: Rody的第二个解决方案(+1)正是我之前更新过的内容,所以我不打算重复他现在所做的事情。 Yoda的实际上也非常整洁,所以另外+1。
12月更新:有趣的是,在这里工作之后,我不得不为自己的研究重新审视这个问题(编写White的异方差检验)。我现在实际上偏爱一种新的方法,在评论中由@slayton推荐(有点隐秘)。具体来说,使用nchoosek
。我的新解决方案如下所示:
T = 20; K = 4;
X = randi(100, T, K);
Index = nchoosek((1:K), 2);
XAll = [X, X(:, Index(:, 1)) .* X(:, Index(:, 2)), X.^2];
nchoosek
准确地生成了我们快速轻松地构建交叉产品所需的指数!
答案 1 :(得分:2)
以下内容有点不错:
B = arrayfun(@(x) circshift(A, [0 -x]), 0:size(A,2)-1, 'UniformOutput', false);
B = cat(2, ones(size(A)), B{:});
C = repmat(A, 1, size(A,2)+1) .* B
然而,这将导致矩阵
c1 c2 c3 (c1.*c1) (c2.*c2) (c3.*c3) (c1.*c2) (c2.*c3) (c3.*c1) (c1.*c3) (c2.*c1) (c3.*c2)
其顺序与您提出的顺序不同,且产品不是唯一的。如果您只想要所有独特的产品,请使用:
[sA1, sA2] = size(A);
aa = repmat(1:sA2, sA2,1);
C = [A, A(:,nonzeros(triu(aa))).*A(:,nonzeros(triu(aa.')))]
导致
c1 c2 c3 (c1.*c1) (c2.*c1) (c2.*c2) (c3.*c1) (c3.*c2) (c3.*c3)
这是一个与您要求不同的序列,但它只包含唯一的产品。
序列对您的目的是否重要?
答案 2 :(得分:1)
这是另一种选择。首先,定义一个函数,该函数返回给定数量列的所有可能的对(根据您在问题中的要求):
cols=@(n)cat(1,num2cell((1:n)'),num2cell((1:n)'*[1,1],2),num2cell(nchoosek(1:n,2),2))
该功能应该是相当不言自明的。尝试查看输出中的一些小值n
并亲自查看。有了这个,你可以按照以下步骤进行:
s = RandStream('twister','Seed',1); %for reproducibility
x = rand(s, 4, 3) %your matrix
% 0.4170 0.1468 0.3968
% 0.7203 0.0923 0.5388
% 0.0001 0.1863 0.4192
% 0.3023 0.3456 0.6852
o = cellfun(@(c)prod(x(:,c),2),cols(size(x,2)),'UniformOutput',0);
out = cat(2,o{:})
% 0.4170 0.1468 0.3968 0.1739 0.0215 0.1574 0.0612 0.1655 0.0582
% 0.7203 0.0923 0.5388 0.5189 0.0085 0.2903 0.0665 0.3881 0.0498
% 0.0001 0.1863 0.4192 0.0000 0.0347 0.1757 0.0000 0.0000 0.0781
% 0.3023 0.3456 0.6852 0.0914 0.1194 0.4695 0.1045 0.2072 0.2368