【MATLAB】空白セル有りCSVファイルを処理する

## はじめに
[前回](https://qiita.com/dokagui_tairan/items/16661e6376fc464e6364)は`CSV`ファイルに計算セルを追加して`excel`ファイルとして保存するやつを実装した．

前回使った`CSV`ファイルは1行目にデータのラベルがあって各列に同じタイプのデータが並ぶという非常にきれいな作りになっているが，業務で実際取り扱うファイルはもっとぐちゃぐちゃになっている．
ざっくり説明すると以下のような感じ．

<img width="400" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373168/c5983ab0-253c-652d-c0d9-0e473e279c88.png"> [^1]

同じデータが横方向に並んでいるし，`excel`で開いた時の'''映え'''を重視して5行目に空行とかG列に空列が入ってたりする．

データが横に並んでいる点については`matlab`で処理する上では特に問題はなかったが，空白セルが入ってるとそのままでは出力出来なかったので，回避方法を簡単にまとめる．
今回はエラーになってキレそう[^2]になっているところから順に書いていくため，結論だけ見たい場合はスキップしてください．

## 空白セルをそのまま出力してみる
``` matlab:
% ファイルを読み取ってcellに格納
path = 'C:\Users\dejiko';
file = '身長体重_空白セルあり.csv';
filepath = fullfile(path, file);
T = readcell(filepath,'DatetimeType','text');

% データ内容は変更せずにとりあえずそのまま出力する
Tout = T;

% ファイルに書き込む
[path, file] = fileparts(filepath);
newFile = sprintf('%s_matlab.xlsx', file);
outputFilePath = fullfile(path, newFile);
writecell(Tout, outputFilePath);
```

### 結果
実行してみると，以下のようなエラーが出て終了してしまった．
![missing.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373168/9a619729-f2d8-80a7-0d00-fe7453ab8f72.png)
>エラー: writecell (line 119)
>'missing' 型の cell 要素はサポートされていません．書き込む前に，要素を数値，logical，string，datetime，duration または categorical
に変換してください．

とのこと[^3]．

### missingの罠
変数Tの中身を`matlab`で表示してみると，以下のようになった．空白セルは`missing`という型で格納されるらしく，出力する際にこれを何かに変換する必要があるっぽい．
![missingT.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373168/5ec3ae2a-604c-637c-fbfb-e8112799b627.png)

## missingを処理
`missing`部分を空`char`に置き換える処理を追加する．

### 実装

``` matlab:
% missingを判定
missingCell = cellfun(@ismissing, T, 'UniformOutput',false);
% maskをcell2matしてlogical配列にしたいが，
% char配列のセルについては{1×N(文字数) logical}になっていて，そのままではcell2matできない
% {1×N logical}となっている部分を抽出して{1×1 logical}に置き換える
len = cellfun(@length, missingCell, 'UniformOutput',false);
len = cell2mat(len);
lenMask = len ~= 1;
missingCell(lenMask) = {false};
% 全セルが{1×1 logical}になったのでcell2mat出来る
mask = cell2mat(missingCell);

Tout = T;
% missing部分を空文字に置き換える
Tout(mask) = {''};
```

### 解説

まず`ismissing`で各セルが`missing`かどうかを判定する．

``` matlab:
missingCell = cellfun(@ismissing, T, 'UniformOutput',false);
```
以下に`ismissing`した結果を示す．
文字列の部分が`{1×N logical}`となっており，このままでは`cell2mat`が出来ない．
<img width="400" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373168/e349cae5-d85c-4fa2-9d4f-83a1d3684bba.png"> 
<hr>
次に`{1×N logical}`となる部分を抽出するために，`length`を適用する．

``` matlab:
len = cellfun(@length, missingCell, 'UniformOutput',false);
len = cell2mat(len);
lenMask = len ~= 1;
```


<hr>
次に`{1×N logical}`の部分を`{false}`に置き換える．

``` matlab:
missingCell(lenMask) = {false};
```

これで全部`{1×1 logical}`になったので，`cell2mat`してマスクを作って元のセルにマスクを適用すれば終わりである．
<img width="400" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373168/08ba4ecf-140b-725f-a544-fbb72fe4a6c5.png"> 


## まとめ
空白セルを考慮した`excel`ファイルの入出力を`matlab`で実装した．
引き続き`excel`との和解を果たしていく．

[^1]: https://ja.wikipedia.org/wiki/%E3%81%8A%E3%81%A1%E3%81%93%E3%81%BC%E3%82%8C%E3%83%95%E3%83%AB%E3%83%BC%E3%83%84%E3%82%BF%E3%83%AB%E3%83%88
[^2]: https://www.nicovideo.jp/watch/sm37510647
[^3]: https://www.google.com/search?q=%E3%81%AF%E3%81%84%E3%81%AF%E3%81%84%E5%87%9B%E4%B8%96%E3%81%8C%E6%82%AA%E3%81%86%E3%81%94%E3%81%96%E3%81%84%E3%81%BE%E3%81%97%E3%81%9F