三次元(XYZ)を1つの関数に置く

図1
図2
図1の縦方向をY軸、横方向をX軸とし、CXVファイルをZ軸方向としています。
この(XYZ)を使ってA=(XYZ)のような1つの関数に置きたいです。
宜しくお願いします。

 Accepted Answer

下記にサンプルコードを作成しました。全てのCSVファイルのX,Yのそれぞれのデータ数は全部等しいことを前提にしています。
% サンプルとなるCSVファイルを作成
fileName = 'file_';
for i = 1 : 10
data = zeros(11,11);
data(1,2:end) = 0:9;
data(2:end,1) = 0:9;
data(2:end, 2:end) = reshape(1:100, 10, 10); % サンプルデータはとりあえず連番データを挿入
fileData = num2cell(data);
fileData{1,1} = 'y/x';
writecell(fileData, [fileName, num2str(i-1), '.CSV']);
end
fileData % CSVに保存したデータのひとつを表示
fileData = 11×11 cell array
{'y/x'} {[ 0]} {[ 1]} {[ 2]} {[ 3]} {[ 4]} {[ 5]} {[ 6]} {[ 7]} {[ 8]} {[ 9]} {[ 0]} {[ 1]} {[11]} {[21]} {[31]} {[41]} {[51]} {[61]} {[71]} {[81]} {[ 91]} {[ 1]} {[ 2]} {[12]} {[22]} {[32]} {[42]} {[52]} {[62]} {[72]} {[82]} {[ 92]} {[ 2]} {[ 3]} {[13]} {[23]} {[33]} {[43]} {[53]} {[63]} {[73]} {[83]} {[ 93]} {[ 3]} {[ 4]} {[14]} {[24]} {[34]} {[44]} {[54]} {[64]} {[74]} {[84]} {[ 94]} {[ 4]} {[ 5]} {[15]} {[25]} {[35]} {[45]} {[55]} {[65]} {[75]} {[85]} {[ 95]} {[ 5]} {[ 6]} {[16]} {[26]} {[36]} {[46]} {[56]} {[66]} {[76]} {[86]} {[ 96]} {[ 6]} {[ 7]} {[17]} {[27]} {[37]} {[47]} {[57]} {[67]} {[77]} {[87]} {[ 97]} {[ 7]} {[ 8]} {[18]} {[28]} {[38]} {[48]} {[58]} {[68]} {[78]} {[88]} {[ 98]} {[ 8]} {[ 9]} {[19]} {[29]} {[39]} {[49]} {[59]} {[69]} {[79]} {[89]} {[ 99]} {[ 9]} {[10]} {[20]} {[30]} {[40]} {[50]} {[60]} {[70]} {[80]} {[90]} {[100]}
list = dir('*.CSV'); % CSVファイルの取り出し
filePath = fullfile(list(1).folder, list(1).name); % 一つ目のCSVファイルパスを取得
file1Data = readmatrix(filePath, 'Range', [2,2]); % データを示すセル(2行2列目)からデータの読み込み
csvData = zeros([size(file1Data), length(list)]); % データの初期化
csvData(:,:,1) = file1Data; % ひとつめのファイルのデータを挿入
for i = 2 : length(list) % 2ファイル目以降のファイル読み込みのためのループ文
filePath = fullfile(list(i).folder, list(i).name);
csvData(:,:,i) = readmatrix(filePath, 'Range', [2,2]); % CSVファイルのデータの代入
end
csvData(:,:,1) % 一つ目のファイルのデータを表示
ans = 10×10
1 11 21 31 41 51 61 71 81 91 2 12 22 32 42 52 62 72 82 92 3 13 23 33 43 53 63 73 83 93 4 14 24 34 44 54 64 74 84 94 5 15 25 35 45 55 65 75 85 95 6 16 26 36 46 56 66 76 86 96 7 17 27 37 47 57 67 77 87 97 8 18 28 38 48 58 68 78 88 98 9 19 29 39 49 59 69 79 89 99 10 20 30 40 50 60 70 80 90 100

9 Comments

皓
on 24 Jul 2023
ご回答ありがとうございます。
2つ目のコードを書くと以下に添付している代入を実行できませんと出てきます。
似たような質問内容があったのですが、良く分からないです。
よろしくお願いいたします。
エラーが出ているのは「csvData(:,:,i) = readmatrix(filePath, 'Range', [2,2]); % CSVファイルのデータの代入」の行だと思いますが、これは、readmatrixで読み取ったファイルにデータがなく(サイズ0x0)、左辺(csvData(:,:,i) (csvData(1:10,1:10,i)と同意))で要求しているデータサイズ10x10が満たせていませんと言っています。
おそらく、エラーが出たcsvファイルの中身が空だったりすると予想しますので、コードをスクリプトファイル(.mファイル)上に記述して、実行して、ブレークポイントを貼ったりして、エラー原因となったcsvファイルを特定してみるとよいと思います。
皓
on 25 Jul 2023
ありがとうございます。解決しました。
追加の質問になってしまうのですが、csvData(:,:,1)の1つ目の:をx軸、2つ目の:をy軸と置いた場合、csvData(:,:,1)のコンター図を描くことはできますか?
上記のサンプルだと、csvData(:,:,1)の1つ目の:がY軸、2つ目の:をX軸になっていますので、サンプルに転置処理を加えて、csvData(:,:,1)の1つ目の:がX軸、2つ目の:をY軸に変換させた変数csvDataを作成しました。
また、csvData(:,:,1)のコンター図を描画しました。
% サンプルとなるCSVファイルを作成
fileName = 'file_';
for i = 1 : 10
data = zeros(11,11);
data(1,2:end) = 0:9;
data(2:end,1) = 0:9;
data(2:end, 2:end) = reshape(1:100, 10, 10); % サンプルデータはとりあえず連番データを挿入
fileData = num2cell(data);
fileData{1,1} = 'y/x';
writecell(fileData, [fileName, num2str(i-1), '.CSV']);
end
fileData % CSVに保存したデータのひとつを表示
fileData = 11×11 cell array
{'y/x'} {[ 0]} {[ 1]} {[ 2]} {[ 3]} {[ 4]} {[ 5]} {[ 6]} {[ 7]} {[ 8]} {[ 9]} {[ 0]} {[ 1]} {[11]} {[21]} {[31]} {[41]} {[51]} {[61]} {[71]} {[81]} {[ 91]} {[ 1]} {[ 2]} {[12]} {[22]} {[32]} {[42]} {[52]} {[62]} {[72]} {[82]} {[ 92]} {[ 2]} {[ 3]} {[13]} {[23]} {[33]} {[43]} {[53]} {[63]} {[73]} {[83]} {[ 93]} {[ 3]} {[ 4]} {[14]} {[24]} {[34]} {[44]} {[54]} {[64]} {[74]} {[84]} {[ 94]} {[ 4]} {[ 5]} {[15]} {[25]} {[35]} {[45]} {[55]} {[65]} {[75]} {[85]} {[ 95]} {[ 5]} {[ 6]} {[16]} {[26]} {[36]} {[46]} {[56]} {[66]} {[76]} {[86]} {[ 96]} {[ 6]} {[ 7]} {[17]} {[27]} {[37]} {[47]} {[57]} {[67]} {[77]} {[87]} {[ 97]} {[ 7]} {[ 8]} {[18]} {[28]} {[38]} {[48]} {[58]} {[68]} {[78]} {[88]} {[ 98]} {[ 8]} {[ 9]} {[19]} {[29]} {[39]} {[49]} {[59]} {[69]} {[79]} {[89]} {[ 99]} {[ 9]} {[10]} {[20]} {[30]} {[40]} {[50]} {[60]} {[70]} {[80]} {[90]} {[100]}
list = dir('*.CSV'); % CSVファイルの取り出し
filePath = fullfile(list(1).folder, list(1).name); % 一つ目のCSVファイルパスを取得
fileData = readmatrix(filePath, 'Range', [2,2]); % データを示すセル(2行2列目)からデータの読み込み
file1Data = fileData'; % 転置をして、(:,:,1)のひとつめをX軸、2つめをY軸となるように変換する。
csvData = zeros([size(file1Data), length(list)]); % データの初期化
csvData(:,:,1) = file1Data; % ひとつめのファイルのデータを挿入
for i = 2 : length(list) % 2ファイル目以降のファイル読み込みのためのループ文
filePath = fullfile(list(i).folder, list(i).name);
fileData = readmatrix(filePath, 'Range', [2,2])'; % CSVファイルの読み取り
csvData(:,:,i) = fileData'; % 転置をして、(:,:,1)のひとつめをX軸、2つめをY軸となるように変換する。
end
csvData(:,:,1) % 一つ目のファイルのデータを表示
ans = 10×10
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
contourf(0:size(csvData, 1)-1, 0:size(csvData, 2) - 1, csvData(:,:,1)); % コンター図の描画 (X,YデータはCSVのデータにあわせて0スタート)
colorbar; % カラーバーも一緒に描画
皓
on 27 Jul 2023
コンター図を描くことができました。
ありがとうございます。
①listを1,2,3,100と小さい順にしたいのですが、下図のように100を超えると1の後ろに来てしまいます。何か方法はありますでしょうか?
➁csvData = zeros([size(file1Data), length(list)]); % データの初期化
csvData(:,:,1) = file1Data; % ひとつめのファイルのデータを挿入
初心者なので、あまり分かっていないのですが、一回データを初期化してからファイルのデータを挿入しないといけないのでしょうか?プログラミングが上手く行かないのかとは思いますが、なぜうまくいかないのかが分からないです。
➂ list(1).folder, list(1).nameの中のlist(1)の番号は何に反映されるのでしょうか?
番号変えた場合でも同じ結果になったので、どうなっているのか分からなかったです。
① ファイル名の数値を抜け出し、昇順に入れ替えるといった方法になると思います。
下記にlist構造体を数値の昇順になるように入れ替えるサンプルを書きました。
% サンプルとなるCSVファイルを作成
fileName = 'file_';
for i = 1 : 10
data = zeros(11,11);
data(1,2:end) = 0:9;
data(2:end,1) = 0:9;
data(2:end, 2:end) = reshape(1:100, 10, 10); % サンプルデータはとりあえず連番データを挿入
fileData = num2cell(data);
fileData{1,1} = 'y/x';
writecell(fileData, [fileName, num2str(i), '.CSV']);
end
list = dir('*.CSV');
{list.name}' % 全ファイル名を表示。2番目のファイルがfile_10.CSVになってしまっている。
ans = 10×1 cell array
{'file_1.CSV' } {'file_10.CSV'} {'file_2.CSV' } {'file_3.CSV' } {'file_4.CSV' } {'file_5.CSV' } {'file_6.CSV' } {'file_7.CSV' } {'file_8.CSV' } {'file_9.CSV' }
allnames = {list.name};% list構造体から全ファイル名を取得
numberStrCell = regexp(allnames, '^file_(\d+)\.', 'once', 'tokens'); % ファイル名のfile_〇〇. の〇〇(数字)を抽出
numberStr = [numberStrCell{:}];% セル配列の中にセル配列の中に文字列というデータ型になっているので、最初のセル配列の中身を出す。
number = str2double(numberStr);% セル配列の文字列を数値配列に変換する。
[~, sortIdx] = sort(number);% 数値を昇順に入れ替えを行ったそのインデックスを取得
list = list(sortIdx); % list構造体を数値の昇順に入れ替え
{list.name}' % 全ファイル名を表示。ファイル名が昇順に入れ替わった。
ans = 10×1 cell array
{'file_1.CSV' } {'file_2.CSV' } {'file_3.CSV' } {'file_4.CSV' } {'file_5.CSV' } {'file_6.CSV' } {'file_7.CSV' } {'file_8.CSV' } {'file_9.CSV' } {'file_10.CSV'}
② 初期化せずに実行することも可能です。ただし変数の配列数がひとつずつ追加されている形になるので、実行速度が遅くなります。(MATLABで下記サンプルのコードを書くと警告が出ます。)
data = rand(100,100);
% 変数の初期化なしの実行速度
tic;
for i = 1 : 1000
test1(:,:,i) = data;
end
toc
Elapsed time is 0.135108 seconds.
% 変数を初期化した場合の実行速度
test2 = zeros(100, 100, 1000);
tic;
for i = 1 : 1000
test2(:,:,i) = data;
end
toc
Elapsed time is 0.037940 seconds.
③ listは構造体配列になっており、list(1)は構造体配列の1番目の要素を差しています。今回はたまたまfolderメンバーは全て同一の値のため、差がないように見えてしまったようです。下記のようになっています。
配列の中身は、ワークスペースの変数名をダブルクリックするか、コマンドで「open('list')」のように打つと、下記図のようなダイアログが現れて変数の詳細を確認できます。
皓
on 28 Jul 2023
①昇順に入れ替えることができました。
➁➂も分かりやすく解説してくださり、ありがとうございます。
④ ①のnumberStrCell = regexp(allnames, '^file_(\d+)\.', 'once', 'tokens'); % ファイル名のfile_〇〇. の〇〇(数字)を抽出でのコードで分からないところがあります。% ファイル名のfile_〇〇. の〇〇(数字)を抽出と書いてくださっているので、何をこのコードで実行しているのかは分かるのですが、'^file_(\d+)\.', 'once', 'tokens'が何を表しているのかが分からないです。
⑤ ①の[~, sortIdx] = sort(number);% 数値を昇順に入れ替えを行ったそのインデックスを取得のコードでは何を行っているのかが分からないです。配列を変換して昇順に順番を入れ替えているということでしょうか?
⑥colorbarのラベルと色がcsvファイルによって図1のようにラベルの数値と色が変わってしまうので、毎回同じ色と数値にしていただきたいです。数値は0,10,20,30,40,50,60,70,80,90,100で色は図2が理想形です。
図1
図2
④ '^file_(\d+)\.'は正規表現です。^は文字列の先頭を指し、\dは数字、\d+は一つ以上連続した数値の文字列、\.は、.を指します。(正規表現で.は任意の文字を表すので、文字の.を表現するには\.になります。)
また、(\d+)の()はトークンを表します。
'once'は一回の一致のみの検索を表します。
'tokens'は正規表現で指定したトークンの文字列の抽出の指定になり、今回のトークンの対象は(\d+)の部分です。これにより、連続の数字の文字列(\d+)を抽出することができます。
sortの第2出力はソート結果の並べ替えインデックスを指します。
a = [3,2,1,5,4];
[data, sortIdx] = sort(a) % 出力1は昇順に並び替えたデータで、出力2はソート結果の並び替えインデックス
data = 1×5
1 2 3 4 5
sortIdx = 1×5
3 2 1 5 4
また、配列データのインデックスに並び替えたい数値配列を指定すると、その配列順にデータを並び替えることができます。
orderIdx = [3,2,1];
data = [1,2,3];
orderData = data(orderIdx)% orderIdxで指定した順序に並び替え
orderData = 1×3
3 2 1
この2つを組み合わせると、sortで指定した並び替え順序を他のデータに反映させることができます。
data = [3,2;1,2;2,7;6,8;5,11;4,100]%1列目の数値が昇順になるように行全体を並べ替えたい。
data = 6×2
3 2 1 2 2 7 6 8 5 11 4 100
[~, sortIdx] = sort(data(:,1));% 1列目の数値配列のソート結果のインデックス取得
sortData = data(sortIdx,:) %ソート結果のインデックスをもとに行の並び替え
sortData = 6×2
1 2 2 7 3 2 4 100 5 11 6 8
⑥ カラーのラベルについて、climでカラーの上下限値を設定できるので、全てのグラフでclim([0,100])を指定すれば、全て0~100の幅を持ったカラーバーに統一できます。(MATLAB R2022aより前のバージョンの場合はcaxisです。)
また、カラーの色の指定はcolormapでできます。カラーの色は標準でいくつか用意されています。(色を自作することも可)
サンプルを下記に書きました。
sample1 = peaks(0:9) .* 10; % サンプルデータ1の作成
[min(sample1(:)), max(sample1(:))] % data1の上下限の確認
ans = 1×2
0.0000 58.5913
sample2 = sample1 .* 2;% サンプルデータ2の作成。サンプル1より2倍大きい
colormap(turbo()); % カラーマップの色の指定 理想形に近そうな色を選択
contourf(0:9,0:9,sample1); % sample1のコンター図描画
clim([0,100]); % カラーマップの上下限値の指定
colorbar; % カラーバー表示
contourf(0:9,0:9,sample2);% sample2のコンター図描画
clim([0,100]);% カラーマップの上下限値の指定
colorbar;% カラーバー表示
皓
on 2 Aug 2023
コンター図を描くことができました。
追加で何度も何度も質問に答えてくださり、ありがとうございました。

Sign in to comment.

More Answers (0)

Categories

Products

Release

R2022b

Community Treasure Hunt

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

Start Hunting!