はじめに
MATLABでスクリプトを実行させる場合に、MATLAB以外のファイルを読み込んで使うケースはかなり多いと思います。
本記事は、古くからある(そして非推奨となってしまった)読み込み関数、代わりにお勧めされている読み込み関数についてまとめてみました。
1.古くからある関数
1-1 load
データが数値のみで、asciiコードで書かれているならば、loadが使えます。
A = load('test.dat');
のように簡単に読み込めて、Aには数値配列が入っています。
外部からの読み込みとは関係ないですが、matlabを使っていて、作業を中断したいが、変数などは取っておきたい場合には、
save
をやると、今ある変数が取りこまれたmatlab.matという構造体ファイルが生成されます。
復活させたいときは、
load
をやると、matlab.matに取りこまれていた変数が戻ってきます。
1-2 csvread(非推奨)
カンマ区切りのcsvファイルを読み込むのに使う関数です。よく使われます。なんといってもcsvファイルはエクセルで開けるのが大きいと思います。
A = csvread('testsignalA.csv');
で、Aに読み込むことができます。 ちなみにカンマ区切りであれば、拡張子が .txt や.datであっても読み込めます。
読み込めない場合の原因としては、文字列のヘッダーがある場合です。
計測器などのデータをエクスポートすると、こんな感じに、
freq[Hz],amplitude[V},phase[deg]
1,1.1,11
2,1.2,12
3,1.3,13
4,1.4,14
5,1.5,15
なっている場合が多いですが、csvreadでは文字列は読み込めないので、1行目をスキップします。
※ここで読み込もうとしているcsvファイルのサンプルは、上のtestsignalA.csvのようなもの、エクセルのサンプルファイルはtestsignalA.csvをxlsxで保存したもの(シートは同じような内容が何枚かある)という想定になっています。
A = csvread('testsignalA.csv',1,0);%2行目1列目から読みこみ
ここで、違和感があるのはMATLABなのに、2行目1列から読むのに"1,0"とゼロベースになっているところです。何でですかね。
1-3 dlmread(非推奨)
カンマ区切りだけではなくて、いろいろなデリミタに対応したものがdlmreadです。csvreadも中身はdlmreadです。
%dlmreadによるCSVファイル読み込み
M = dlmread('testsignalA.csv',',',1,0); %2行目1列目から読みこみ
%dlmreadによるtab区切りテキストファイル読み込み
M = dlmread('testsignalAtab.txt','\t',1,0); %2行目1列目から読みこみ
%dlmreadによるスペース区切りテキストファイル読み込み
M = dlmread('testsignalAspc.txt',' ',1,0); %2行目1列目から読みこみ
ところで、スペース区切りだけどスペースがたくさんあるような場合、例えば、
freq[Hz] amplitude[V}phase[deg]
1 1.1 11
2 1.2 12
3 1.3 13
4 1.4 14
5 1.5 15
こんなのの場合、dlmreadでデリミタにスペースを指定しても、
M =
1 列から 6 列
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
7 列から 12 列
0 0 0 0 0 1.0000
0 0 0 0 0 2.0000
0 0 0 0 0 3.0000
0 0 0 0 0 4.0000
0 0 0 0 0 5.0000
こんな感じにスペース分だけ、ゼロが入り、列数が増え、うまく読み取れません。
%dlmreadによるスペース区切りテキストファイル読み込み
M = dlmread('testsignalAspc.txt'); %1行目1列目から読みこみ
デリミタの指定をなくすとうまくいくはずですが、何行目の指定ができなくなるので、今度は1行目から読み込み始めて、「文字列は読めない」というエラーがでます。
どうにもならんねん、という場合は、ヘッダーの行を消して(!)対応するしかないみたいです。
ちなみにdlmreadでのデリミタは、コロン":"とかセミコロン";"なども読めます。
1-4 xlsread(非推奨)
古くからの読み込み関数の中のボスが、このxlsreadです。
excel拡張子のxls, xlsx, xlsm, xlsbなどが読み込めるほか、シート名の指定も可能です。
%シートが1枚しかなく、ヘッダー文字列なく、数値のみ
N = xlsread('testsignalA.xlsx'); %2行目1列目から読みこみ
%シートが1枚しかなく、ヘッダー文字列があるので2行目から読み込みたい
N = xlsread('testsignalA.xlsx',1,0); %2行目1列目から読みこみ
%シートが複数あり、特定のシートを読み込みたい。ヘッダー文字列なく、数値のみ
N = xlsread('testsignalA.xlsx','sheet2_name');
%シートが複数あり、特定のシートを読み込みたい。ヘッダー文字列があるので2行目から読み込みたい
N = xlsread('testsignalA.xlsx','sheet2_name',1,0);
%ヘッダーがあり、ヘッダーも数値も読み込みたい
[num,txt,raw] = xlsread('testsignalA.xlsx');%numに数値、txtに文字列、rawは両方
%が入力されます。
ここで最後の用例にあるように、数値もヘッダも読めるのはいいのですが、txtとrawはcell配列となります。
2.cell配列
「読み込めた!」と喜んだのも束の間、cell配列に入力されてしまって愕然、という方も多いと思います(半面、意図的にcell配列に入力させる方も)。
ここでは、cell配列とは何か、cell配列内のデータを出す(普通の数値や文字列にする)方法を書いてみたいと思います。
2-1 cell配列とは何ぞや
cell配列は「小物入れ」とか「食器棚」とかそういう収納アイテムと考えると合点がいくと思います。
cell配列に入っている数値に算術演算子も論理演算子も使えません。これは、えー、例えば、食器を食器棚に仕舞ったままで、料理の盛り付けをしないのと同じと考えてください。
cell配列は、いろいろ仕舞えるので収納アイテムとしては、とても有能ですが、それに特化しちゃっているものです。
2-2 cellからどうやって取り出すか
%まず、xlsreadによるxlsファイルの読み込み(指定なし)
[~,txt,~] = xlsread('testsignalA.xlsx');
%txtには列ヘッダーがcell配列で読み込まれる
%こうやると1つめのcellが取り出せるが、取り出したtxt1もcell
txt1 = txt(1);
%なんか中身を取り出そうとしたら引き出しごと出てきてしまった感じ
%こうすると中身(文字列)だけ取り出せます
txt1 = txt{1};
%これは、3つ取り出せるが、cellのまま
txt123 = txt(1:3);
%こうすると文字列で取り出せるが、連結しちゃっている
txt123=[txt{1:3}];
% 'freq[Hz]amplitude[V}phase[deg]' となる。
%3つ分割して取り出したい場合は、あらかじめ受け取る入れ物が必要
[txt1, txt2, txt3]=txt{1:3};
%ここは、カンマ区切りリストというものと関係あって、深いところです(省略します)
で、次に数値の読み込み、いってみましょう。
%まず、xlsreadによるxlsファイルの読み込み(指定なし)
[~,~,raw] = xlsread('testsignalA.xlsx');
%rawには全データがcell配列で読み込まれる
%これだと2列めの数値がcellで出てきてしまう
raw232=raw(2,1:3)
%数値で取り出したい場合は cell2mat関数 を使います
num323 = cell2mat(raw(2,1:3));
%これでもOKです(行方向取り出し)
num323s = [raw{2,1:3}];
%列方向ならば、
num323s2 = [raw{2:11,1}];%でも行ベクトルになってしまう
%行にも列にも複数個(cell2mat使用)
num323 = cell2mat(raw(2:5,1:3));
%行にも列にも複数個(cell2matを使わない)
dum=size(raw(2:5,1:3));
num323s3 = reshape([raw{2:5,1:3}],dum);
%raw(cell配列)から数値5x3個を取り出し、それぞれに1を加えて、cellに戻す
raw(2:6,1:3) = num2cell(cell2mat(raw(2:6,1:3))+1);
%cell2matの逆はnum2cellで、mat2cellではありません。
%mat2cellには別の機能が与えられています。
%変数はcellには入りません
a=100;
raw(2,3)={a};
% aでなくて100が入ってしまう
%行・列の指定に変数を使うことは可能
a=2;
dd=raw(a,3);
%cellに算術演算子は許されていないが、配列の回転などは許されている
rawflip=fliplr(raw);%左右反転
raw90=rot90(raw);%90度回転
こんな感じです。
3.新しい世代の読み込み関数
3-1 わりと最近でてきた読み込み関数
readmatrix, readcell, readtable の3つです。
古い読み込み関数は "〇〇read" なのに、新しいのは "read〇〇"なのはナゼ?
「〇〇から読み込む」と「〇〇に読み込む」の違いでしょうか。
古いタイプの読み込み関数では「デリミタ指定」でファイル形式を判定していたのに対し(拡張子はわりとどうでもよい)、新しいタイプは「拡張子によるファイル形式の判定」をします。
3-2 readmatrix
数値のみを読み込むときのxlsreadに似ています。読み込んだ結果も普通の数値配列です。
シートの指定もできますし、領域の指定もできます。
csvなどのファイルも読めます。
%readmatrixによるxlsファイルの読み込み(シートと場所指定あり)
N = readmatrix('testsignalA.xlsx','Sheet','sheet1_name','Range','A2:C11')
%readmatrixによるxlsファイルの読み込み(シートと場所の指定なし)
%列ヘッダは消える
N = readmatrix('testsignalA.xlsx')
文字列の読み込みもやってみたのですが(オプションで指定する)、「全て文字」でないと読み込めませんでした。あまり楽しいことはないようです。
3-3 readcell
なんでも読み込めますが、読み込んだものはことごとくcellになります。まさにその名のとおり。
でも、本記事の2章を読んだ方は、もう既にcellに関しては、MATLABを使っているエンジニアの大半より賢くなっているので(by Andrew 某 先生 口調)、きっと大丈夫です。
%readcellによるxlsファイルの読み込み(指定なし)
%1番目のシートの文字列ヘッダーを抜いて、読み込まれる
M = readcell('testsignalA.xlsx');
%xlsreadによるxlsファイルの読み込み(シート指定)
M = readcell('testsignalA.xlsx','Sheet','sheet2_name');
%xlsreadによるxlsファイルの読み込み(シート、場所指定)
M = readcell('testsignalA.xlsx','Sheet','sheet1_name','Range','A2:C11');
%readcellによるxlsファイルの読み込み(シート、場所指定)
M = readcell('testsignalA.xlsx','Sheet','sheet1_name','Range','A:C')
3-4 readtable
tableに読み込んでくれるファンクション。数値データと文字データの混在も扱えるところが素晴らしい。csvファイル(コンマ区切り)からtableに直してくれるし、データに欠損があっても NaN とか {0x0 char}で埋めてくれるという気配りの人。ドット構文(変数名.列ラベル)でいろいろできます。cellより扱いやすい印象です。
tableについては、d-kitamura先生の秀逸な記事があるので、そちらを参考にされると吉です。
さて、readtable の例文ですが、
%まず、csvファイルの読み込みから
N = readtable('testsignalA.csv');
%これだとfreq[Hz]がfreq_Hz_になってしまう(matlab識別子として使えるように)
% matlab識別子とはmatlabで使える変数名、で、だいたい合っていると思います。
N1=N.freq_Hz_; %ちゃんと動作して、freq_Hz_列がN1に入る
N.Properties.VariableDescriptions %ここに元の列ヘッダーがしまわれている
%(表示される警告は、そういうことを言っているようです)
%識別子の配慮せず、ヘッダーは変更しない場合は、
N = readtable('testsignalA.csv','VariableNamingRule','preserve');
%これならfreq[Hz]になるが、識別子として使えない
% N1=N.freq[Hz];%エラーが出る
%エクセルもcsvファイルと同じように読みこみが可能
N = readtable('testsignalA.xlsx');
%欠損データはNaNで埋められる
%(用例は省略します)
%ドット構文でデータを数値化できる
nn = N.freq_Hz_(4);
%ドット構文で算術演算も可能 cellだとできないところ
N.freq_Hz_(5) = N.freq_Hz_(5)+2;
4.終わりに
以上、MATLABで外部ファイルを読み込む場合の関数と用例をまとめてみました。半分は自分の備忘録になってしまっております。
間違いとか、「こんな使い方もある」がありましたら、お知らせいただけると幸いです。