根据替换组合计算列的乘积
Posted
技术标签:
【中文标题】根据替换组合计算列的乘积【英文标题】:Calculate products of columns according to combinations with replacement 【发布时间】:2020-11-04 12:41:08 【问题描述】:问题
这有点难以解释,但我会尽力而为。我知道找到替换组合数量的方程式。假设我有 6 个向量:A、B、C、D、E、F。如果我想找到这 6 个变量的每一个可能的三次乘积,那就是 (6+3-1)!/3!(6- 1)! = 56 种组合(见末尾)。同样,如果我想要每个二次产品,它是 21。对于线性,当然是 6(只是每个变量本身)。我想计算所有 6+21+56 = 83 个组合。我正在考虑 3 个循环,每个内部循环都从其外部循环开始迭代,例如
for i1=1:6
X(:,?) = X.*X(:,i1)
for i2=i1:6
X(:,?) = X.*X(:,i2)
for i3=i2:6
X(:,?) = X.*X(:,i3)
但是左侧存储所有数据的 83 列矩阵的索引让我感到困惑。如您所见,它们标有问号。
PS:可能也需要使用 5 阶来执行此操作,因此它会添加另外 126 和 252 列,总共 461 列。因此,更通用的代码更好,不会对 3 阶进行硬编码。但如果它被硬编码到第 5 位,那没关系,因为我绝对不会超过那个。
MATLAB 或 Python 都可以,因为我可以在两者之间轻松切换。
用一个例子计算的二次组合
这是我期望的 21 列的示例,用于 6 个变量(A 到 F)的二次组合。在 Excel 中完成。我为每个向量采集了 3 个样本。
三次组合列表
这是我需要计算的 56 种组合:
A,A,A
A,A,B
A,A,C
A,A,D
A,A,E
A,A,F
A,B,B
A,B,C
A,B,D
A,B,E
A,B,F
A,C,C
A,C,D
A,C,E
A,C,F
A,D,D
A,D,E
A,D,F
A,E,E
A,E,F
A,F,F
B,B,B
B,B,C
B,B,D
B,B,E
B,B,F
B,C,C
B,C,D
B,C,E
B,C,F
B,D,D
B,D,E
B,D,F
B,E,E
B,E,F
B,F,F
C,C,C
C,C,D
C,C,E
C,C,F
C,D,D
C,D,E
C,D,F
C,E,E
C,E,F
C,F,F
D,D,D
D,D,E
D,D,F
D,E,E
D,E,F
D,F,F
E,E,E
E,E,F
E,F,F
F,F,F
【问题讨论】:
为什么ABA
、ACA
等不在列表中?
@Sushanth 这是组合,而不是排列。所以 ABA 和 ACA 已经算在 AAB 和 AAC 中了。
在这种情况下为什么不使用内置,***.com/a/33144821/4985099
您能否添加一个具有精确输入和输出的小示例,以便我们更好地了解您想要什么?
另外,您可以接受两种标记语言中的任何一种的解决方案吗?
【参考方案1】:
这是 Matlab 中的矢量化方法。它应该很快,但内存效率不高,因为它会生成所有笛卡尔元组的所有索引,然后只保留那些不递减的。
x = [2 2 3 2 8 8; 5 1 7 9 4 4; 4 1 2 7 2 9]; % data
P = 2; % product order
ind = cell(1,P);
[indend:-1:1] = ndgrid(1:size(x,2)); % Cartesian power of column indices with order P
ind = reshape(cat(P+1, ind:), [], P); % 2D array where each Cartesian tuple is a row
ind = ind(all(diff(ind, [], 2)>=0, 2), :); % keep only non-decreasing rows
result = prod(reshape(x(:,ind.'), size(x,1), P, []), 2); % apply index into data. This
% creates an intermediate 3D array. Compute products
result = permute(result, [1 3 2]); % convert to 2D array
【讨论】:
非常感谢。我现在不太关心内存,因为我不会在超大数据上使用它。充其量,可能是 20-30 个向量,在这种情况下,我可能会减少订单。现在我将尝试将其迁移到 Python。看起来像标准功能,所以我认为它应该很容易。 permute 是做什么的? [1 3 2] 是特定于订单 2 还是适用于任何订单?permute
更改尺寸的顺序(而不是它们相关的尺寸)。它是矩阵转置的推广。它的第二个参数是通用的,而不仅仅是为了 2 的情况。我认为它的 Numpy 等价物可能是 moveaxis
,但我不精通 Python/Numpy
感谢您的澄清!这就说得通了。如果/当我让它工作时,我会在这里发布 Python 答案,但这完美地完成了工作,所以我很高兴:)
@ZackFair 我很高兴!
@ZackFair 你是对的,它应该是P
(或任何更大的东西)而不是3
。谢谢你抓住它!已编辑。我已更改为 P+1
而不是 P
,因为我认为这样更清晰(沿下一个暗淡堆叠所有 P
-dim 数组)【参考方案2】:
您可以通过使用计数器来避免索引混淆:
clear all; close all
% Original matrix
M = [
2 2 3 2 8 8;
5 1 7 9 4 4;
4 1 2 7 2 9
];
% Number of combinations
order = 3;
sizeX = nchoosek(size(M,2)+order-1,order);
% Combinations
imat = ones(sizeX,order);
for c=2:sizeX
imat(c,:) = imat(c-1,:);
for o=order:-1:1
if (imat(c-1,o)<size(M,2))
imat(c,o:end) = imat(c-1,o)+1;
break
end
end
end
% Transpose & display combinations
imat = transpose(imat)
% Computations of products
X = ones(size(M,1),sizeX);
for o=1:order
X = X.*M(:,imat(o,:));
end
% Display result
X
当你执行你得到的脚本时:
>> test_script
imat =
Columns 1 through 16
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 2 2 2 2 2 3 3 3 3 4
1 2 3 4 5 6 2 3 4 5 6 3 4 5 6 4
Columns 17 through 32
1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
4 4 5 5 6 2 2 2 2 2 3 3 3 3 4 4
5 6 5 6 6 2 3 4 5 6 3 4 5 6 4 5
Columns 33 through 48
2 2 2 2 3 3 3 3 3 3 3 3 3 3 4 4
4 5 5 6 3 3 3 3 4 4 4 5 5 6 4 4
6 5 6 6 3 4 5 6 4 5 6 5 6 6 4 5
Columns 49 through 56
4 4 4 4 5 5 5 6
4 5 5 6 5 5 6 6
6 5 6 6 5 6 6 6
X =
Columns 1 through 16
8 8 12 8 32 32 8 12 8 32 32 18 12 48 48 8
125 25 175 225 100 100 5 35 45 20 20 245 315 140 140 405
64 16 32 112 32 144 4 8 28 8 36 16 56 16 72 196
Columns 17 through 32
32 32 128 128 128 8 12 8 32 32 18 12 48 48 8 32
180 180 80 80 80 1 7 9 4 4 49 63 28 28 81 36
56 252 16 72 324 1 2 7 2 9 4 14 4 18 49 14
Columns 33 through 48
32 128 128 128 27 18 72 72 12 48 48 192 192 192 8 32
36 16 16 16 343 441 196 196 567 252 252 112 112 112 729 324
63 4 18 81 8 28 8 36 98 28 126 8 36 162 343 98
Columns 49 through 56
32 128 128 128 512 512 512 512
324 144 144 144 64 64 64 64
441 28 126 567 8 36 162 729
我为 order=4
测试了它,它应该可以工作。
【讨论】:
我认为这里可能有一些小错误,因为最后 4 行(EEE、EEF、EFF、FFF)的前两行应该是 512、64,然后是 8、36、162、729 ,分别是我在下面使用 Luis 的代码时得到的。这就是为什么我选择它作为正确答案的原因,因为它也适用于任何顺序。不过还是谢谢! 抱歉,我不明白出了什么问题2^3=8
、5^3=125
和4^3=64
没错。也许我不明白你的问题或你的评论。看起来你找到了解决问题的方法,所以主要的事情;)
你是对的,我的错。我使用示例代码并没有过多关注结果。所有乘法都必须在三个 FOR 循环内完成。我编辑了答案感谢您的反馈!
是的,矩阵形式肯定更快。考虑到您对索引感到困惑,我试图尊重您的原始代码,我不想完全改变您的解决方案。我还没有理解订单作为参数。我会为你编辑代码。
无论原始矩阵和顺序如何,它现在都应该完成这项工作。对于这个问题,计算并不是很重,内存消耗可能是大问题。祝你下次好运!以上是关于根据替换组合计算列的乘积的主要内容,如果未能解决你的问题,请参考以下文章
R - 给定一个矩阵和一个幂,生成多个矩阵,其中包含矩阵列的所有唯一组合
三个未知数乘积相加等于一个固定值,,怎么用EXCEL计算三个未知数组合?