はじめに
さて、年中行事のアドベントカレンダーにおける"MATLAB de EXCEL"を今年も紹介していきたいと思います。
MATLAB de EXCEL の過去記事:
MATLABにファイルデータを読みこむ関数
MATLABからファイルデータを書き出す関数
MATLABからEXCELに書き出す
今回は日本語混じりのファイルを読み込み、データ操作を行い、書き出す、というものをご紹介します。なお、今回の内容は、MATLAB R2023b Windows版で動作させたものとなります。
1. 素材データの用意
まず、素材として、csvファイルを用意します。ここでは、特許検索サイトの JPlatPat で検索した結果をcsvファイルに落としたものを用意しました。
『ビットコイン』、『採掘者』をキーワードとして検索した結果をcsvファイルでダウンロードします(csvファイルのダウンロードは無料ですが、登録が必要です。余談ですが)。
『ビットコイン』について195件、『採掘者』について187件のデータがあります。
2.文字を含むファイルを読み込む関数(readtable, readcell, readmatrix)
MATLABでcsvファイルを読み込む関数は、古いところではcsvreadがありますが、今回は新しい関数を用いてみます。
新しい関数はreadcell、readtable、readmatrixがあります。
readmatrixで普通に読み出すとNaNしか出てきませんので、出力データ型の指定が必要となります。
また、readtableでテーブルの見出しを表示したい場合は、'VariableNamingRule','preserve'が必要となります。
filename = 'ビットコイン.csv';% ファイル名は日本語もOK
MC = readcell(filename); % MCにセル型で出力される
MT = readtable(filename,'VariableNamingRule','preserve'); % MTにtable型で出力される
MX = readmatrix(filename,'OutputType','string'); % 出力型の指定が必要
readmatrixの場合には、数値と文字列が混在しているときに、全てが文字列になってしまうため、用途によってはお勧めできません。
3.読み込んだファイルをマージする
"ビットコイン.csv"と”採掘者.csv”を読み込んでマージさせてみましょう。
filename1 = 'ビットコイン.csv';
filename2 = '採掘者.csv';
% ビットコイン.csvの読み込み
MC1 = readcell(filename1); % セルに読み込み
MT1 = readtable(filename1,'VariableNamingRule','preserve'); % tableに読み込み
MX1 = readmatrix(filename1,'OutputType','string'); % マトリクスに読み込み
% 採掘者.csvの読み込み
MC2 = readcell(filename2); % セルに読み込み
MT2 = readtable(filename2,'VariableNamingRule','preserve'); % tableに読み込み
MX2 = readmatrix(filename2,'OutputType','string'); % マトリクスに読み込み
これらを同じタイプのもの同士でマージするわけですが、それぞれのcsvにはタイトル行があります。
なので、マージのときには連結するほうの(後ろのほうの)csvのタイトル行を削除しなければなりません。
%セル配列の結合
MC12 = [MC1;MC2(2:end,:)]; % MC2は2行目以下を用いる
%tableの結合
MT12 = [MT1;MT2]; % table型はタイトル行は自動的に修正される
%マトリクスの結合
MX12 = [MX1;MX2(2:end,:)]; % MX2は2行目以下を用いる
これでマージできます。
と、思いきや、Table型のマージで失敗しているようです。
次を使用中のエラー: tabular/vertcat
table 変数 '公告番号' は、ある table では cell 配列で、別の
table では cell 配列ではないため、連結することができません。
csvファイルの中に、値がないところがあり、読み込む際にcell配列になるところと、ならないところがあって、マージがうまくいかないようです。
この問題は、次のように入力オプションをつけることで、解決するようです。
filename1 = 'ビットコイン.csv';
filename2 = '採掘者.csv';
opts = detectImportOptions(filename1,'VariableNamingRule','preserve');
opts = setvaropts(opts,'FillValue',' ');
% ビットコイン.csvの読み込み
MT1 = readtable(filename1,opts); % tableに読み込み
% 採掘者.csvの読み込み
MT2 = readtable(filename2,opts); % tableに読み込み
%両者をマージする
MT12 = [MT1;MT2]; % table型はタイトル行は自動的に修正される
4. optsって何?
前の章で、いきなり "opts" が出てきます。MathWorksのドキュメント、例えば readtable の項でも、インポート オプション オブジェクト optsとあるのですが、わかりにくいです。
簡単に説明してみます。
T = readtable(filename);
% これは、filenameの中身をtable型で読み込み、Tに入力するものです。
% 細かい読み込み設定は、"デフォルト" となります。
T = readtable(filename,Name,Value);
% これは、デフォルトの設定では不都合があって、設定を変えたい場合に
% 使います。設定の名前(Name)と設定値(Value) を組み合わせて指定します。
T = readtable(filename,Name1,Value1,Name2,Value2);
% こういう風にして、複数の設定を変更することができます。ですが、
% 変更箇所が多くなると、やたら長くなったりして面倒です。
% そこで、
opts = detectImportOptions(filename);
% これを実行すると、optsの中に読み込み時の設定が全て入力されます。
% なので、必要なところを適宜変更します。
% 変更するには、setvaroptsを用います。例えば、本稿では、
opts = setvaropts(opts,'FillValue',' ');
% で、読み込む値がないセルを、スペース(' ')で埋めるようにしています。
T = readtable(filename,opts);
% とすると、変更された設定で読み込んでくれるようになります。
%%%%% 備考 %%%%%
%※optsのプロパティ'MissingRule'が'fill'でない場合、
opts = setvaropts(opts,'FillValue',' ');
% を行なっても、「値を入れて埋める」設定にはなっていないので、
% 空白に置き換えることはされません(このあたり、何かノウハウがある
% みたいなんですが、今回はパスします)
%※※optsの値の設定パラメータについては、ドキュメントに部分的に
% 載っているところしか発見できませんでした。
%※※※optsの中のパラメータ(disp(opts)で表示されるもの)については、
opts.Encoding = 'SHIFT_JIS';
%のようにして設定します。もしくは、
opts1 = detectImportOptions('myDataTT.csv','Encoding','SHIFT_JIS');
% のようにします。
5. ダブリを除く
これでマージできたわけですが、「ビットコイン」をキーワードにした特許と、「採掘者」をキーワードにした特許にはダブリがあり、両方のキーワードを含む特許が重複されてしまいます。
読み込んだ2つのcsvファイルに対し、ここでは1列目の"文献番号"を参照して、同じものを排除しましょう。
重複を探すには ismember を用います。
% セルの場合
Lia1C = ~ismember(MC1(:,1),MC2(:,1)); % MC2と重複していないMC1の項目にフラグ1を立てる(~はNOT)
Lia2C = ~ismember(MC2(:,1),MC1(:,1)); % MC1と重複していないMC2の項目にフラグ1を立てる
MC2P = MC2(Lia2C,:); % MC1と重複しないMC2を取り出す
MC12 = [MC1;MC2P]; % マージする
% Tableの場合
Lia2T = ~ismember(MT2(:,1),MT1(:,1)); % MT1と重複していないMT2の項目にフラグ1を立てる
MT2P = MT2(Lia2T,:); % MT1と重複しないMT2を取り出す
MT12 = [MT1;MT2P]; % マージする
% マトリクスの場合
Lia2X = ~ismember(MX2(:,1),MX1(:,1)); % MX1と重複していないMX2の項目にフラグ1を立てる
MX2P = MX2(Lia2X,:); % MX1と重複しないMX2を取り出す
MX12 = [MX1;MX2P]; % マージする
6. ソートする
ダブリがないようにしてマージしましたが、2つをくっつけただけなので、ここでソートして順番を整えます。
ソートにはsortrowsを用います。
%セルの場合
MC12_Sort = sortrows(MC12,2); % 2行目の要素に基づいてソート
%テーブルの場合
MT12_Sort = sortrows(MT12,'文献番号'); % 行名が使える
%マトリクスの場合
MX12_Sort = sortrows(MX12,1);%1列目の要素に基づいてソート
7. 書き出す
最後にソートしたデータを書き出してみましょう。csvファイルに書き出す場合、そのままですと UTF-8 で書き出されて(そしてそれをShift-JISで読み込まれた結果)文字化けしてしまうので、encodingをSHIFT_JISにするオプションをつける必要があります。
それと、セルの場合において、空白のセルが "Missing" になっており、このまま書き出そうとするとエラーが出るので、下記のようにして"Missing" を" " (空白)に変換してから書き出します。
cellfunは、セル配列の個々のセルに対して、演算を行う場合に使います。
%セルの場合
MC12_Sort(cellfun(@(x) all(ismissing(x)), MC12_Sort)) = {' '}; % Missingを空白に変換する
writecell(MC12_Sort,'セル.xlsx');
writecell(MC12_Sort,'セル.csv','Encoding','SHIFT_JIS');
%テーブルの場合
writetable(MT12_Sort,'テーブル.xlsx');
writetable(MT12_Sort,'テーブル.csv','Encoding','SHIFT_JIS');
%マトリクスの場合
writematrix(MX12_Sort,'マトリクス.xlsx');
writematrix(MX12_Sort,'マトリクス.csv','Encoding','SHIFT_JIS');
8. エクセルファイルの読み込み
今回、CSVファイルの読み込みから話を始めてしまいましたが、エクセルファイル(xlsxなど)においても同様に読み込むことができます。
ただし、指定できるオプションが異なるところがあり、
% CSVの場合
opts_csv = detectImportOptions("ビットコイン.csv")
% EXLSの場合
opts_xlsx = detectImportOptions("ビットコイン.xlsx")
を実行してみますと、例えばデリミタとかエンコーティングなどの設定はCSVにしかなく、逆にsheet、DataRangeなどはエクセルにしかありません。このあたりには注意が必要です。
9.終わりに
以上、MATLABでEXCELのデータを操作する方法をまとめてみました。
パラメータがデフォルトのままで、サクッと動いてくれればよいのですが、引っ掛かるところがあるため、TIPSとして書かせていただきました。
誰かのお役に立てば幸いです。