行列の各要素に対して​すべての組み合わせで​引き算を行うやり方を​知りたい

以下の行列において,
A=[1 1 2 2 3 3 4 4 5 5 6 6
3 2 3 4 5 6 7 8 9 9 9 9
4 9 8 7 6 5 4 3 2 1 0 1
2 3 4 5 6 8 7 8 6 5 5 4];
操作* : 一列目, 二列目に関してして, 各々の要素の全ての組み合わせにおいて引き算の絶対値を求める
一列目: abs(1-3), abs(1-4), abs(1-2), abs(3-4), abs(3-2), abs(4-2)
二列目: abs(1-2), abs(1-9), abs(1-3), abs(2-9), abs(2-3), abs(9-3)
二列ごとに操作*を行いたいときはどうしたら良いのでしょうか?
具体的には,
A12=[1 1
3 2
4 9
2 3];
A34=[2 2
3 4
8 7
4 5];
%~A1112まで
A12, A34, A45...A1112について操作*を行いたいです.

Answers (1)

Atsushi Ueno
Atsushi Ueno on 28 Aug 2024
Edited: Atsushi Ueno on 28 Aug 2024

1 vote

組み合わせは nchoosek 関数、差分は diff 関数、絶対値は abs 関数が利用可能です。
下記サンプルでは、引き算の絶対値を”D”で始まる各変数に格納しました。
入力”A”の列数が奇数の場合、最後の列は無視されます。
A = [1 1 2 2 3 3 4 4 5 5 6 6
3 2 3 4 5 6 7 8 9 9 9 9
4 9 8 7 6 5 4 3 2 1 0 1
2 3 4 5 6 8 7 8 6 5 5 4];
% Aの全列について操作*を行う
for k = 1:width(A)
% 操作:k列目の各要素の組み合わせにおいて引き算の絶対値を求める
D(:,k) = abs(diff(nchoosek(A(:,k),2),1,2));
% kが偶数の時(2列毎)、AとDを個別変数に格納する
if(~mod(k,2))
eval("A"+(k-1)+(k)+"=[A(:,k-1) A(:,k)];");
eval("D"+(k-1)+(k)+"=[D(:,k-1) D(:,k)];");
end
end
D
D = 6x12
2 1 1 2 2 3 3 4 4 4 3 3 3 8 6 5 3 2 0 1 3 4 6 5 1 2 2 3 3 5 3 4 1 0 1 2 1 7 5 3 1 1 3 5 7 8 9 8 1 1 1 1 1 2 0 0 3 4 4 5 2 6 4 2 0 3 3 5 4 4 5 3
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
A12
A12 = 4x2
1 1 3 2 4 9 2 3
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
A34
A34 = 4x2
2 2 3 4 8 7 4 5
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
D12
D12 = 6x2
2 1 3 8 1 2 1 7 1 1 2 6
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
D34
D34 = 6x2
1 2 6 5 2 3 5 3 1 1 4 2
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
whos
Name Size Bytes Class Attributes A 4x12 384 double A1112 4x2 64 double A12 4x2 64 double A34 4x2 64 double A56 4x2 64 double A78 4x2 64 double A910 4x2 64 double D 6x12 576 double D1112 6x2 96 double D12 6x2 96 double D34 6x2 96 double D56 6x2 96 double D78 6x2 96 double D910 6x2 96 double ans 1x1 8 double cmd 1x1 294 string cmdout 1x33 66 char gdsCacheDir 1x14 28 char gdsCacheFlag 1x1 8 double i 0x0 0 double k 1x1 8 double managers 1x0 0 cell managersMap 0x1 8 containers.Map mshDir 1x18 36 char prefDir 1x1 170 string status 1x1 8 double

6 Comments

takumi
takumi on 28 Aug 2024
Moved: Atsushi Ueno on 28 Aug 2024
わかりやすい解答ありがとうございます.
ここからさらに, 算出したDについて,
SQ12=[sqrt(D(1,1)^2+D(1,2)^2)
sqrt(D(2,1)^2+D(2,2)^2)
sqrt(D(3,1)^2+D(3,2)^2)
sqrt(D(4,1)^2+D(4,2)^2)
sqrt(D(5,1)^2+D(5,2)^2)
sqrt(D(6,1)^2+D(6,2)^2)];
のように, D12について計算を行った値SQ12をプロット, 同じくD1112について計算を行ったSQ1112までプロットするにはどうしたらよいでしょうか?
以下のようなグラフが書きたいです.
二乗和は hypot 関数です。やりたい事からして別名の変数群に分ける必要はありません。
A = [1 1 2 2 3 3 4 4 5 5 6 6; 3 2 3 4 5 6 7 8 9 9 9 9; 4 9 8 7 6 5 4 3 2 1 0 1; 2 3 4 5 6 8 7 8 6 5 5 4];
for k = 1:width(A)
D(:,k) = diff(nchoosek(A(:,k),2),1,2); % 二項(全組み合わせ)の差分
end
SQ = hypot(D(:,1:end-1),D(:,2:end)); % 二乗和
p = plot(SQ'); % プロット
set(p,{'Marker'},{'o';'^';'square';'diamond';'pentagram';'hexagram'}); %"o","+","*",".","x","_","|","square","diamond","^","v",">","<","pentagram","hexagram"
Atsushi Ueno
Atsushi Ueno on 28 Aug 2024
for 文を除去しました
A = [1 1 2 2 3 3 4 4 5 5 6 6; 3 2 3 4 5 6 7 8 9 9 9 9; 4 9 8 7 6 5 4 3 2 1 0 1; 2 3 4 5 6 8 7 8 6 5 5 4];
index = nchoosek(1:height(A), 2); % 1列の全二項組み合わせ(行index)
D = A(index(:,2),:) - A(index(:,1),:); % の差分(abs()は外した)
SQ = hypot(D(:,1:end-1),D(:,2:end)); % 隣の列との二乗和
takumi
takumi on 28 Aug 2024
Edited: takumi on 29 Aug 2024
ご回答ありがとうございます.
SQの計算過程で
SQ=[2.23606797749979 1.41421356237310 2.23606797749979 2.82842712474619 3.60555127546399 4.24264068711929 5 5.65685424949238 5.65685424949238 5 4.24264068711929
8.54400374531753 10 7.81024967590665 5.83095189484530 3.60555127546399 2 1 3.16227766016838 5 7.21110255092798 7.81024967590665
2.23606797749979 2.82842712474619 3.60555127546399 4.24264068711929 5.83095189484530 5.83095189484530 5 4.12310562561766 1 1 2.23606797749979
7.07106781186548 8.60232526704263 5.83095189484530 3.16227766016838 1.41421356237310 3.16227766016838 5.83095189484530 8.60232526704263 10.6301458127347 12.0415945787923 12.0415945787923
1.41421356237310 1.41421356237310 1.41421356237310 1.41421356237310 2.23606797749979 2 0 3 5 5.65685424949238 6.40312423743285
6.32455532033676 7.21110255092798 4.47213595499958 2 3 4.24264068711929 5.83095189484530 6.40312423743285 5.65685424949238 6.40312423743285 5.83095189484530];
と計算されますが, 今回プロットしたいものは, SQ12,SQ34,SQ56,SQ78,SQ910,SQ1112ですので, グラフの横座標は11目盛り分ではなく, 6目盛り分になるかと思われます.
SQ_even=SQ(:,1:2:end);
plot(SQ_even')
としましたら所望のグラフが得られました.
また,
SQ = hypot(D(:,1:end-1),D(:,2:end));
SQ_even=SQ(:,1:2:end);
この二行を一行で表す方法などありますでしょうか?
Atsushi Ueno
Atsushi Ueno on 29 Aug 2024
あらま。隣同士の二乗和(の平方根)ではなく、2列ずつ組にして二乗和を求めるのですね。
>この二行を一行で表す方法などありますでしょうか?
⇛こうなります。なお列数が奇数の場合エラーになるので予め制限する必要があります。
D = D(:,1:floor(width(D)/2)*2) % 列数を偶数に制限する
%SQ = hypot(D(:,1:end-1),D(:,2:end)); % 隣列との二乗和の平方根を求める
SQ_even = hypot(D(:,1:2:end),D(:,2:2:end)) % 2列ずつ二乗和の平方根を求める
%SQ_even=SQ(:,1:2:end);
A = [1 1 2 2 3 3 4 4 5 5 6 6; 3 2 3 4 5 6 7 8 9 9 9 9; 4 9 8 7 6 5 4 3 2 1 0 1; 2 3 4 5 6 8 7 8 6 5 5 4];
A = A(:,1:floor(width(A)/2)*2); % 列数を偶数に制限する
index = nchoosek(1:height(A), 2); % 1列の全二項組み合わせ(行index)
D = A(index(:,2),:) - A(index(:,1),:); % の差分(abs()は外した)
SQ_even = hypot(D(:,1:2:end),D(:,2:2:end)); % 2列ずつ二乗和の平方根を求める
p = plot(SQ_even'); % プロット
set(p,{'Marker'},{'o';'^';'s';'d';'p';'h'});
takumi
takumi on 1 Sep 2024
大変たすかりました.
丁寧なご回答ありがとうございました.

Sign in to comment.

Categories

Products

Tags

Asked:

on 28 Aug 2024

Commented:

on 1 Sep 2024

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!