CSVデータで指定し​た列数だけ行数を切り​取り、正方形のデータ​として抽出したい

音声データ(wav)をCSVに変換、そのCSVファイルをこちらで指定した行数で列数を切り分けたデータ(いわば正方形)を量産したいと考えています。
(例:257行、5000列のcsvデータに対し、こちらで0行から100行指定。→0からの100行×100列を5000列まで、新たなcsvとして切り分け保存するループのようなもの)
音声データをcsvファイルに変換することはできたのですが、そこからの分割が手も足も出ないです。
読み込み→指定して切り分け、保存→ループ→終了の流れはなんとなく掴めてはいるのですが。。。
どのような関数を使い組み立てていけばよいのでしょうか、ご教授願いたいです。

 Accepted Answer

Kojiro Saito
Kojiro Saito on 12 May 2021

2 votes

reshapeを使えば簡単にできそうです。
以下のようなサンプルでどうでしょうか?
t = readmatrix('data.csv');
numLines = 1:100;
n = size(numLines,2);
rt = reshape(t(numLines,:), n, n, []);
for n=1:size(rt,3)
filename = sprintf('data%d.csv', n);
writematrix(rt(:, :, n), filename)
end

5 Comments

Inagaki takeshi
Inagaki takeshi on 26 May 2021
こちらのサンプルを試してみたところ、読み込むCSVの列数が、こちらで指定した行数で割り切れないとエラーとなってしまいます。
様々な列数(奇数など)のCSVに対応したいと考えているため、指定した数で割り切れなかった場合は最後のデータを切り捨て、または割り切れるように0などを代入して出力したいと考えていたのですが、なかなかうまく機能できません。
reshape関数で上記のようなことを実装するのは可能でしょうか。
また、データを重ねわせでの出力も考えているのですが、(0から100行指定したら、はじめは0から100列、次は50列から150列、次は100列から200列のようなもの)
上記のような出力をする場合、for文の中をどのように変えればよいのでしょうか
ご教授願いたいです。
このような質問は、別途でまた質問する必要があるのであれば、教えていただけると幸いです。
Atsushi Ueno
Atsushi Ueno on 26 May 2021
→→横槍失礼いたします→→
>reshape関数で上記のようなことを実装するのは可能でしょうか。→NOです
>"明示的に指定する" 次元のサイズは入力行列の要素の数 numel(A) を割り切れる値にしなければなりません。
>指定した数で割り切れなかった場合は最後のデータを切り捨て、→やってみました
t = readmatrix('data.csv');
numLines = 1:100;
n = size(numLines,2); % ここまで上と同じ
dat = t(numLines,:); % 行指定したcsvデータ
dln = floor(numel(dat) / n^2) * n^2; % n^2で割り切れる要素数
rt = reshape(dat(1:dln), n, n, []); % 割り切れる様に削ってreshape
>また、データを重ねわせでの出力も考えているのですが、(0から100行指定したら、はじめは0から100列、次は50列から150列、次は100列から200列のようなもの)上記のような出力をする場合、for文の中をどのように変えればよいのでしょうか →matlabが古くてwritematrixを動確できませんでしたが多分OKです
for n=1:size(rt,3)
filename = sprintf('data%d.csv', n);
writematrix(rt(:, :, n), filename); % ここまで上と同じ
if(n < size(rt,3)) %最後の端でなかったらn枚目の後半とn+1枚目の前半を出力する
writematrix([rt(:, 51:100, n) rt(:, 1:50, n+1)], filename);
end
end
Inagaki takeshi
Inagaki takeshi on 27 May 2021
Edited: Inagaki takeshi on 27 May 2021
Uenoさんありがとうございます、reshapeでは0を加えたりできないんですね、学びました。
データの切り捨ては参考にしてできるようになりました。ありがとうございます。
重ね合わせについて更にお聞きしたい点があります。
データを指定通りに重ね合わせはできたのですが、reshape内で出た数値でループするため、CSVデータの最後まで出力せず、途中で終わってしまいます。
(重ね合わせているので30個のCSVデータがほしいが、reshape内での数値が20なので、size(rt,3)で指定すると、20個までしかCSVが出ないといった感じ。)
こちらでループ文の条件を変えてみたりもしたのですが、機能できませんでした。
また、最初のdata1.csvが、上記のプログラムで行くと50~150目の出力になってしまい、理想のdata1.csv(1~100)とは少し違う形となってしまいました。
なにか改善案はありますでしょうか。
ご教授願います。
Atsushi Ueno
Atsushi Ueno on 27 May 2021
ファイル名の事を考えていませんでした。filenameを変えればやりたい事は出来ます。但し重ね合わせ量の変更には対応していません。コメントにて追加された要件を統合すると、私の変更対応は場当たり的過ぎます。切り出す所から変更した方が良さそうですね。やります。
for n=1:size(rt,3) % 切り出した行列を半分ずつ重ね合わせてcsvファイルに出力する
filename = sprintf('data%d.csv', 2*n-1); % ファイル番号を2n-1にする
writematrix(rt(:, :, n), filename);
if(n < size(rt,3)) %最後の端でなかったらn枚目の後半とn+1枚目の前半を出力する
filename = sprintf('data%d.csv', 2*n); % 重なる部分はファイル番号を2nにする
writematrix([rt(:, 51:100, n) rt(:, 1:50, n+1)], filename);
end
end
Inagaki takeshi
Inagaki takeshi on 27 May 2021
Edited: Inagaki takeshi on 27 May 2021
Uenoさん対応ありがとうございます、ファイル保存の謎は解けました。
ちょうど重ね合わせの量のこともお聞きしたかったので助かります。
将来的には1-100、81-180、161-260、241-340(N量ずつ重ね合わせ、この場合は片側20の計40の重ね合わせ) のような複雑な重ね合わせ切り出しも考えているので、お力添えをしていただけると幸いです。
自分も切り出しの部分から見直しをしてみます。
よろしくお願いいたします。

Sign in to comment.

More Answers (1)

Atsushi Ueno
Atsushi Ueno on 27 May 2021

1 vote

前回答のコメントで追加された要件への対応です。末端の処理は「余るデータを切り捨て」ではなく「データ数不足でも保存」に変更しました。while文ループなのでreshape関数に比べると処理が遅いです。
function k = moving_window_data2csv(n, m)
% CSVファイルの数値データをmoving windowで走査し別CSVファイルに保存する
% 引数: n:指定抽出行数(=指定抽出列数)
% 引数: m:指定移動列数
% データ先頭から指定抽出行数×指定抽出列数を抽出する
% 行方向の指定抽出行数以降のデータは抽出不要(逆に行数不足でも抽出する)
% 列方向は指定移動列数ずつずらしながら列の最後まで抽出していく
% 抽出した指定抽出行数×指定抽出列数のデータは各々異なるCSVファイルに保存する
% 指定抽出行数×指定抽出列数未満のデータ数があれば最後のCSVファイルに保存する
k = 0; % ファイル名用カウンタ
t = readmatrix('data.csv'); %csvファイルの素性が決定されていれば、最初のn行のみ読み出すべき
t = t(1:min(n,size(t,1)), :); % 速度向上の為、頭から指定抽出行数のみまとめて抽出
while ~isempty(t)
k = k + 1;
writematrix(t(:, 1:min(n,size(t,2))), ['data' num2str(k) '.csv']);
if n^2 >= numel(t), break; end % 残りデータ数が全て抽出済なら終了
t(:, 1:min(m,size(t,2))) = []; % データ先頭から指定移動列数を削除する
end
end
手持ちのmatlabが古くreadmatrix,writematrix関数を直接動確できませんでした。
作りながら、これは音声フィルタ処理の為の前処理”Moving Window”である事に気付きました。MATLABにも"moving window"を動かして何らかの演算を行う関数が多数あります(下記参照)。コメントにあった末端の処理方法(データを切り捨てるかゼロ埋めするか等)も選択肢を持っています。しかし、moving windowが捉えたデータそのものを出力する機能はいずれの関数にもありません。もしかするとMoving Window機能単体が動作するMATLAB関数が何かあるかもしれません。
  • デジタルフィルタ(filter, filter2関数)
  • 畳み込み演算(conv, conv2関数)
  • 移動平均等の演算(movsum, movprod関数など)

3 Comments

Atsushi Ueno
Atsushi Ueno on 27 May 2021
moving window機能(slide function)単体の関数 slidefun - File Exchange - MATLAB Central (mathworks.com)
Inagaki takeshi
Inagaki takeshi on 28 May 2021
Uenoさん、ありがとうございます。
動作確認は出来ました。問題なく動きそうです。
moving window、初めて聞きました、自分も調べてみます。
色々と助かります。ありがとうございます。

Sign in to comment.

Products

Release

R2021a

Tags

Community Treasure Hunt

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

Start Hunting!