お世話になります。
3次元配列を、ページごとに違う値で割る計算をforループで行い、ループのすべての結果を格納しようとしていますが、結果がすべて同じ値になってしまいます。
具体的には、file_fig_t_yz(:,:,n)という3次元配列を、そのページごとの行と列の和であるfile_fig_sum_yz(:,n)で割り、ページごとの平均値を計算しMden_yz(:,n)にループのすべての結果を格納しようとしていますが、おそらくループの最後の結果のみがn個格納されてしまいます。
現在、書いているコードは以下の通りです。
Mden_yz=zeros(1,632)
n=1;
file_fig_t_yz=zeros(1109,1064,632);file_fig_sum_yz=zeros(1,632);
for i=1:632;
file_fig_t_yz(:,:,n)=boxes01(i-dif_x,1:ymax-ymin+1+dif_y,1:zmax-zmin+1+dif_z)-boxes00(i,1-dif_y:ymax-ymin+1,1-dif_z:zmax-zmin+1);
file_fig_sum_yz(:,n)=sum(sum(file_fig_t_yz(:,:,n)));
Mden_yz(:,n)=mean(mean(mean(file_fig_t_yz(:,:,n))/file_fig_sum_yz(:,n)));
 n=n+1;
end
Matlab初心者なので色々問題あるかもしれないですが、アドバイスよろしくお願いいたします。

 Accepted Answer

Atsushi Ueno
Atsushi Ueno on 21 Jan 2023

0 votes

Mden_yz(:,n) = mean(mean(mean(file_fig_t_yz(:,:,n))/file_fig_sum_yz(:,n)));
ここが意図しない動作の原因になっています。file_fig_t_yz(:,:,n)という3次元配列を、そのページごとの行と列の和であるfile_fig_sum_yz(:,n)で割る前に平均値を演算してしまっています。
Mden_yz(:,n) = mean(mean( ... % ← 平均値を自分で演算するのにmean関数を使うのはおかしい
mean(file_fig_t_yz(:,:,n)) ... % ←ここ 括弧の順番が違う。各要素を合計値で割る前にmean関数がある
/file_fig_sum_yz(:,n) ...
));
しかも、mean(file_fig_t_yz(:,:,n)) は、サイズが 1 ではない最初の配列の次元に沿った A の要素の平均値を返すのですが、入力が行列の場合は各列の平均値を含む行ベクトルを返します。つまり dim — 演算の対象の次元 のデフォルト値は1です。
直すなら下記の様に直すべきだと思います。
Mden_yz(n) = sum(sum(file_fig_t_yz(:,:,n)/file_fig_sum_yz(:,n)));

9 Comments

Atsushi Ueno
Atsushi Ueno on 21 Jan 2023
Edited: Atsushi Ueno on 21 Jan 2023
mean 関数の機能を使えば、下記で同様の演算が可能です。vecdim を設定し mean(A,[1 2]) とする事で三次元行列の各ページの平均値を演算出来ます。
for i = 1:632
file_fig_t_yz(:,:,i)=boxes01(i-dif_x,1:ymax-ymin+1+dif_y,1:zmax-zmin+1+dif_z)-boxes00(i,1-dif_y:ymax-ymin+1,1-dif_z:zmax-zmin+1);
end
Mden_yz = mean(file_fig_t_yz,[1 2]);
Atsushi Ueno
Atsushi Ueno on 21 Jan 2023
file_fig_sum_yz(:,n)=sum(sum(file_fig_t_yz(:,:,n)));
この行を単独でみると「そのページごとの行と列の和」はスカラ値なので、file_fig_sum_yz(:,n)と2次元にする必要は無いなと思ってしまいます。なおスカラ値でも当該コードは問題無く動作します。何か file_fig_sum_yz を他の用途に使う為に2次元として持っているのかもしれません。
Uka
Uka on 21 Jan 2023
ご回答、誠にありがとうございます。
さっそくコマンドウィンドウの方でmean(file_fig_t_yz,[1 2])の計算を確認してみたのですが、以下のエラーが出てしまいました。配列の一部要素が0であるためかと思い、‘omitnan’など試したのですが、うまくいきません。
>> mean(file_fig_t_yz,[1 2])
??? エラー ==> sum
次元の引数は、インデックス付け範囲の中で、正の整数のスカラーでなければなりません。
エラー ==> mean at 30
y = sum(x,dim)/size(x,dim);
>> nanmean(file_fig_t_yz,[1 2])
??? 未定義の関数またはメソッド 'nanmean' (タイプ 'double' の入力引数)
>> mean(file_fig_t_yz,[1 2],'omitnan')
??? エラー ==> mean
入力引数が多すぎます。
>> mean(file_fig_t_yz,'omitnan')
??? エラー ==> sum
文字列の入力の終わりは 'double' または 'native' でなければなりません。
Atsushi Ueno
Atsushi Ueno on 21 Jan 2023
先に紹介した vecdim を設定し mean(A,[1 2]) とする 機能は、R2018b でサポートされました。それより前のリリースで同じ事をするには mean(mean(A,1),2) または単に mean(mean(A)) とすれば良いです。
Uka
Uka on 21 Jan 2023
ご回答ありがとうございます。
おっしゃる通り、バージョンが古くサポートされていなかったようです。ありがとうございます。
そこで、以下のように書き換えてみたのですが、Mden_yzBの要素がある同じ数値の繰り返しとNaNだけになってしまいました(NaNはおそらく0÷0の結果)。ある同じ数値というのは、0÷0(NaN)になる1つ手前のループの計算結果です。
ループ計算ごとの格納がうまくいってないのでしょうか?
file_fig_t_yz=zeros(1109,1064,632);file_fig_sum_yz=zeros(1,632);Mden_yz=zeros(1109,1064,632); %Mden_yzB=zeros(1,1,632);
for i=1:632;
file_fig_t_yz(:,:,i)=boxes01(i-dif_x,1:ymax-ymin+1+dif_y,1:zmax-zmin+1+dif_z)-boxes00(i,1-dif_y:ymax-ymin+1,1-dif_z:zmax-zmin+1);
file_fig_sum_yz(i)=sum(sum(file_fig_t_yz(:,:,i)));
Mden_yz(:,:,i) = file_fig_t_yz(:,:,i)./file_fig_sum_yz(i).*SW./BS;
end
Mden_yzB=mean(mean(Mden_yz,1),2);
Atsushi Ueno
Atsushi Ueno on 21 Jan 2023
ちょっとこんがらがって来ました。改めて最初の質問を見直しました。
書くまでもありませんが平均値の定義は下記の通りです。
しかし最初の質問では、平均の定義とは異なる演算をしています。私も、Nで割るべき所を配列の合計値で割っている所を指摘出来ていませんでした。改めて回答を見直して修正します。
あと気付いたのが
boxes01(i-dif_x,1:ymax-ymin+1+dif_y,1:zmax-zmin+1+dif_z)-boxes00(i,1-dif_y:ymax-ymin+1,1-dif_z:zmax-zmin+1)
2次元配列のサイズがいつも同じ大きさになるのか、それとも最大1109*1064の可変サイズになるのかという事です。もし可変サイズなら、割る数も変更する必要があります。
Atsushi Ueno
Atsushi Ueno on 21 Jan 2023
Moved: Atsushi Ueno on 21 Jan 2023
注目すべき点を抽出するとこういう事ですね。最後の結果のみがn個格納されてしまうのではなく、毎回同じ演算結果になっています。
rtN = 10;
N = rtN^2; % 100
for i=1:10
yz = rand(rtN,rtN);
mean(mean(yz/sum(sum(yz))))
end
ans = 0.0100
ans = 0.0100
ans = 0.0100
ans = 0.0100
ans = 0.0100
ans = 0.0100
ans = 0.0100
ans = 0.0100
ans = 0.0100
ans = 0.0100
Uka
Uka on 21 Jan 2023
すみません、私も計算の意味を考えなおします。
ご丁寧なアドバイス、誠にありがとうございます。
配列の要素を、配列の合計値で割り、要素ごとに合計値との比を出すことが目的です。とりあえず以下のように書き換えました。ページごとの平均値をページごとの和で割りたいので引き続き検討します。
for i=1:632;
file_fig_t_yz(:,:,i)=boxes01(i-dif_x,1:ymax-ymin+1+dif_y,1:zmax-zmin+1+dif_z)-boxes00(i,1-dif_y:ymax-ymin+1,1-dif_z:zmax-zmin+1);
file_fig_sum_yz(i)=sum(sum(file_fig_t_yz(:,:,i)));%ページごとの和
end
Mden_yzB=mean(mean(file_fig_t_yz,1),2); %ページごとの平均値
Mden_yzC=squeeze(Mden_yzB);
Uka
Uka on 21 Jan 2023
アドバイスいただいてから、色々計算の意味などを見直し、無事解決致しました。誠にありがとうございます!

Sign in to comment.

More Answers (0)

Categories

Tags

Asked:

Uka
on 21 Jan 2023

Commented:

Uka
on 21 Jan 2023

Community Treasure Hunt

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

Start Hunting!