假设我有一个包含 3 列的矩阵:c1
、c2
、c3
,我想创建一个新矩阵,其中每个列是该矩阵的两列的任何可能的乘积。
因此,如果我有一个包含 d 列的矩阵,我想创建一个包含 d+d(d-1)/2+d 列的新矩阵。例如,考虑具有 3 列 c1
、c2
、c3
的矩阵。我想要创建的矩阵应包含列 c1
、c2
、c3
、c1xc2
、c2xc3
、c1xc3
、c1^2
、c2^2
和 c3^2
。
有什么有效的方法可以做到这一点吗?
最佳答案
我很尴尬地发布这个 - 我确信一定有一个更简单的方法(有一个非常更简单的方法 - 请参阅答案底部我的 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)
构造可以相当容易地完成。干杯。几个小时后更新。
更新:罗迪的第二个解决方案(+1)正是我在之前的更新中所想到的,所以我不会费心重复他现在所做的事情。尤达的实际上也很整洁,所以另一个+1。
十二月更新:有趣的是,在这里工作之后,我不得不重新审视这个问题以进行我自己的研究(编码怀特的异方差性检验)。我现在实际上更喜欢一种新方法,这是 @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
准确地生成了我们快速轻松地构建叉积所需的索引!
关于matlab - 基于矩阵 A,通过矩阵 A 的列的所有可能的乘法生成矩阵 B,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12790753/