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

226 visualizzazioni (ultimi 30 giorni)
yuta
yuta il 15 Ago 2022
Commentato: yuta il 15 Ago 2022
文字列と数値を含む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 Commenti
yuta
yuta il 15 Ago 2022
コメントありがとうございます。
説明が不十分で申し訳ありませんでした。
欠損部はデータの解析に使用しません。
しかしながら、これらのデータは全て時系列データになっており、サンプリング周波数が異なります。
以下が具体例です。
  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 il 15 Ago 2022
返答ありがとうございます。
勝手ながらどちらでも対応できるようにしておきました。
ご確認ください。

Accedi per commentare.

Risposta accettata

Hernia Baby
Hernia Baby il 15 Ago 2022
Modificato: Hernia Baby il 15 Ago 2022
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 Commenti
Hernia Baby
Hernia Baby il 15 Ago 2022
回答に追記しました
yuta
yuta il 15 Ago 2022
すいません、私の説明が不十分でした。
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様のご教示いただいたものに少し修正を加えることで、おそらく読み込みができたかと思います。
ありがとございます!
私の説明が至らない部分が多くあり、お手数おかけいたしました。
いつもご丁寧に説明いただきありがとうございます。
今後とも、よろしくお願いいたします。

Accedi per commentare.

Più risposte (0)

Prodotti


Release

R2022a

Community Treasure Hunt

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

Start Hunting!