2

c1c2、の 3 つの列を持つ行列があるとします。c3各列がこの行列の 2 つの列の任意の積である新しい行列を作成したいとします。

したがって、d 列のマトリックスがある場合d+d(d-1)/2+d列の新しいマトリックスを作成したいと思います。たとえば、3 列c1c2、の行列を考えてみましょうc3。作成したい行列には、、、、、、、、およびのc1列が必要です。c2c3c1xc2c2xc3c1xc3c1^2c2^2c3^2

これを行う効率的な方法はありますか?

4

3 に答える 3

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)'))];

このステップでは、実際に必要な組み合わせの数の2倍を計算するため、計算は効率的ではありませんB(つまり、c1。* c1、c1。* c2、c1。* c3、c2。* c1、c2。* c2、 c2。*c3、c3。* c1、c3。* c2、c3。* c3)、次に2番目のステップで、必要な列のみを引き出します(たとえば、c3。*c1を削除します)。すでにc1。*c3などを取得しています)。

更新:ちょうど運転していて、はるかに良い方法が私に起こりました。次の形式の2つのインデックスベクトルを作成する必要があります:I1 = [1 1 1 2 2 3]I2 = [1 2 3 2 3 3]、すると、(A(:, I1) .* A(:, I2))必要なすべての列積が得られます。私は現在コンピュータから離れていますが、後で戻って、インデックスベクトルを構築するための一般的な方法を考え出します。構造を使えばかなり簡単に達成できると思いますtril(toeplitz)。乾杯。数時間で更新されます。

更新: Rodyの2番目の解決策(+1)は、以前の更新で私が念頭に置いていたものとまったく同じなので、彼が今そこで行ったことをわざわざ繰り返すことはしません。ヨーダも実はかなり綺麗なので、さらに+1。

12月の更新:おかしなことに、ここで作業した後、私は自分の研究のためにこの問題を再検討する必要がありました(不均一分散性のホワイトのテストをコーディングします)。私は実際に新しいアプローチを支持しており、コメントで@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クロス積をすばやく簡単に構築するために必要なインデックスを正確に生成します。

于 2012-10-09T02:05:12.590 に答える
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)

これは、要求したものとは異なるシーケンスですが、固有の製品のみが含まれています。

順序はあなたの目的にとって重要ですか?

于 2012-10-09T04:38:21.620 に答える
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
于 2012-10-09T07:44:00.450 に答える