文字列と数値を含むcsvファイルを読み込みたい

120 ビュー (過去 30 日間)
yuta
yuta 2022 年 8 月 15 日
コメント済み: yuta 2022 年 8 月 15 日
文字列と数値を含むcsvファイルの読み方についてご教示いただければと思います。
自身で調べてみたものの、全くうまくいかなかったため、質問させていただきます。
今までtest.csvのような、csvファイルを読み込んでいましたが、question.csvのようなデータを読み込む必要が出てきました。
question.csvは、test.csvにGait Cycle ParametersとEventsが増えている形になります。
なお、test.csvは、以下の方法で読み込んでいました。
% データの読み込み
clear,clc;
filepath = "test.csv";
data = readmatrix(filepath);
%2列目のNANの判定をし、前後を引く
idx = isnan(data(:,2));
idx_or =[0;diff(idx)]<0|[diff(idx);0]>0;
% 行番号を見つける
num = find(idx_or);
if mod(length(num),2)
num = [num;height(idx_or)];
end
% numの半分のサイズだけ繰り返し操作
for ii = 1:length(num)/2
A{ii,1} = data(num(2*ii-1):num(2*ii),:);
end
% NANを消し、cell型に格納
B = cellfun(@(x) rmmissing(x,2),A,'UniformOutput',false);
cellfun(@size,B,'UniformOutput',false)
ans = 3×1 cell array
{[ 20 57]} {[13 425]} {[30 161]}
上記の方法では、Gait Cycle ParametersやEventsを読み込めません。
Gait Cycle Parametersは毎回同じ構造で出てくるため、
Value列(4行目の4〜29列)を抽出できればと思っております。
Eventsはデータにより列の数が異なります。
読み込みたいのもはTimeのとこなのですが、それらは
Context(LeftおよびRight)、Name(Foot strikeおよびFoot off)
の 2×2 の計4パターンで出てくるため、それらを判定して4つに分けて抽出できればと思っております。
何卒、よろしくお願いいたします。
  5 件のコメント
yuta
yuta 2022 年 8 月 15 日
コメントありがとうございます。
説明が不十分で申し訳ありませんでした。
欠損部はデータの解析に使用しません。
しかしながら、これらのデータは全て時系列データになっており、サンプリング周波数が異なります。
以下が具体例です。
  1. Deviceは1000Hzで計測
  2. Model Outputsは100Hzで計測
  3. Trajectoriesは100Hzで計測
また、これらの時系列データは373など(データによって異なる)から始まっており、0秒から出力されているわけではありません。
1行目のFrameが少数第二位までの値、2列目のSub Frameが少数第三位の値になります。
したがって、1の場合は以下のような時間となり、
2、3の場合は以下のような時間となります。
データを合わせて解析する際には、1000Hzデータを100Hzにダウンサンプリングして行う予定になっております。
データの欠損値の列を削除した場合、これらの関係性が崩れなければ、欠損部の列は削除してしまって構わないと考えております。
説明がわかりにくくて申し訳ありません。
よろしくお願いいたします。
Hernia Baby
Hernia Baby 2022 年 8 月 15 日
返答ありがとうございます。
勝手ながらどちらでも対応できるようにしておきました。
ご確認ください。

サインインしてコメントする。

採用された回答

Hernia Baby
Hernia Baby 2022 年 8 月 15 日
編集済み: Hernia Baby 2022 年 8 月 15 日
test.csv, question.csvのどちらでもできるようにしました
解説していきます
■ファイルの指定
clc,clear;
% filename = 'test.csv';
filename = 'question.csv';
■キーワードに当てはまる行の探索
 行番号を知りたいので、readlineregexpを用いました
 後々のため、最後の行番号もstartIndexに格納します
str = readlines(filename);
keywords = ["Gait Cycle Parameters","Events","Devices","Model Outputs","Trajectories"];
for ii = 1:length(keywords)
startIndex{ii,1} = find(~cellfun('isempty',regexp(str,keywords(ii))));
end
startIndex = [cell2mat(startIndex);height(str)];
■読み込み
 readmatrixのオプション'Range'を活用しています
 何行から何行まで読むといったものです
 オプション指定が文字なのでsprintfで文字にしています
 後々の操作のため、キーワードの行+2行目 から読み込ませてます
 (※1行目だけにある100とかの数字が邪魔なのでそこを読まないようにしています)
num = length(startIndex)-1;
for ii = 1:num
T{ii} = readmatrix(filename,'Range',sprintf('%i:%i',startIndex(ii)+2,startIndex(ii+1)));
end
■NaNを取り除く
 rmmissingだとNaNが1つでもあると消してしまうので自作しました
T = cellfun(@(x) MyFcn(x),T,"UniformOutput",false);
■コメントで質問した②の該当箇所も消してサイズを見る
 一応やっておきます
cellfun(@(x) size(rmmissing(x,2)),T,'UniformOutput',false)
ans = 1×5 cell array
{[26 1]} {[18 1]} {[21 2]} {[13 425]} {[30 161]}
■Eventsについて(追記)
 keywordsの順番が変わらない前提で今回書いています
 Aからcellで読み込み7列目以降を消しました
ii = 1;
A = readcell(filename,'Range',sprintf('%i:%i',startIndex(ii)+2,startIndex(ii+1)-2));
A(:,7:end) = [];
 テーブル型に変更します
A = cell2table(A(2:end,:),"VariableNames",A(1,:));
 ContextとNameを抽出します
 今回、Foot strikeがないのでSingle Supportで代用しています
Context = ["Left","Right"];
Name = ["Single Support","Foot Off"];
for ii = 1:2
for jj = 1:2
B{ii,jj} = table2array(A(A.Context == Context(ii) & A.Name == Name(jj),'Value'));
end
end
B
B = 2×2 cell array
{[0.2800]} {[50]} {[0.3200]} {[72]}
 Tの最終列に加えておきますか
T{length(T)+1} = B
T = 1×6 cell array
{26×1 double} {18×1 double} {21×57 double} {13×569 double} {30×161 double} {2×2 cell}
■関数の説明
 idx1 : 全ての行がNaNである部分を除外
 idx2 : 全ての列がNaNである部分を除外
function y = MyFcn(x)
idx1 = ~all(isnan(x),2);
idx2 = ~all(isnan(x),1);
y = x(idx1,idx2);
end
  4 件のコメント
Hernia Baby
Hernia Baby 2022 年 8 月 15 日
回答に追記しました
yuta
yuta 2022 年 8 月 15 日
すいません、私の説明が不十分でした。
Eventsはこちらの方を指しておりました。
ii = 2;
A = readcell(filename,'Range',sprintf('%i:%i',startIndex(ii)+2,startIndex(ii+1)-2));
A(:,5:end) = [];
A = cell2table(A(2:end,:),"VariableNames",A(1,:));
Context = ["Left","Right"];
Name = ["Foot Strike","Foot Off"];
for ii = 1:2
for jj = 1:2
B{ii,jj} = table2array(A(A.Context == Context(ii) & A.Name == Name(jj),'Time (s)'));
end
end
しかし、Hernia Baby様のご教示いただいたものに少し修正を加えることで、おそらく読み込みができたかと思います。
ありがとございます!
私の説明が至らない部分が多くあり、お手数おかけいたしました。
いつもご丁寧に説明いただきありがとうございます。
今後とも、よろしくお願いいたします。

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

Help Center および File Exchangeデータ型の変換 についてさらに検索

製品


リリース

R2022a

Community Treasure Hunt

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

Start Hunting!