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

115 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)

Categorie

Scopri di più su データ型の変換 in Help Center e File Exchange

Prodotti


Release

R2022a

Community Treasure Hunt

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

Start Hunting!