OctaveでCSVファイルを扱う完全ガイド: csvwrite関数の使い方から応用まで

2025-06-06

以下に詳しく説明します。

csvwriteの基本的な使い方

csvwrite関数の基本的な構文は以下の通りです。

csvwrite(filename, M)
  • M: CSVファイルに書き出す数値行列(データ)を指定します。
  • filename: 書き出すCSVファイルのファイル名を指定します。文字列で指定します(例: 'data.csv')。


% 3x4の数値行列を作成
data = [1, 2, 3, 4;
        5, 6, 7, 8;
        9, 10, 11, 12];

% 'my_data.csv'というファイルに書き出す
csvwrite('my_data.csv', data);

このコードを実行すると、my_data.csvというファイルが作成され、その中には以下のようにデータがカンマ区切りで保存されます。

1,2,3,4
5,6,7,8
9,10,11,12

csvwriteの特性と注意点

  1. 数値行列のみ対応: csvwriteは数値データのみを扱います。文字列やセル配列を含むデータは直接書き出すことができません。文字列を含む場合は、dlmwrite関数を使用するか、fprintfなどを用いて自分でファイル操作を行う必要があります。

  2. カンマ区切り: デフォルトでカンマ(,)を区切り文字(デリミタ)として使用します。

  3. 改行コード: csvwriteは、行の終わりにLF(Line Feed)のみを挿入します。これは多くのLinux/Unixシステムで標準的な改行コードですが、Windowsのメモ帳など一部のテキストエディタでは、CRLF(Carriage Return + Line Feed)がなければ正しく改行として認識されない場合があります。このため、Windowsのメモ帳で開くと一行に表示されてしまうことがあります。

  4. dlmwriteへの内部的な変換: Octaveのドキュメントによると、csvwrite関数は内部的にはdlmwrite(filename, x, ",")として機能します。これは、csvwritedlmwriteの特殊なケースであることを意味します。

csvwriteはシンプルですが、より柔軟なファイル書き出しが必要な場合はdlmwrite関数を検討することをお勧めします。dlmwriteは以下の点で優れています。

  • 改行コードの制御: newlineオプションを使って改行コードを指定できます。
  • ヘッダー行やフッター行の追加: データの前後にテキストを追加できます。
  • 精度(桁数)の指定: 数値の書き出し精度を制御できます。
  • 区切り文字の指定: カンマ以外の区切り文字(タブ、スペースなど)を指定できます。

例(dlmwriteでより詳細な制御を行う場合)

% 3x4の数値行列を作成
data = [1, 2, 3, 4;
        5, 6, 7, 8;
        9, 10, 11, 12];

% タブ区切りで、小数点以下2桁の精度で書き出す例
dlmwrite('my_data_tab.txt', data, 'delimiter', '\t', 'precision', 2);

% Windowsで正しく改行されるようにCRLFを指定する例
dlmwrite('my_data_win.csv', data, 'delimiter', ',', 'newline', 'pc');


csvwriteに関する一般的なエラーとトラブルシューティング

エラー: ファイルが存在しない、またはパスが不正 (Permission Denied / No such file or directory)

これは最も一般的なエラーの一つです。

  • トラブルシューティング

    1. パスの確認
      指定したファイルパスが正しいか、書き込み先のディレクトリが存在するかを確認します。
      • 例: csvwrite('/home/user/my_data.csv', M) の場合、/home/user/ ディレクトリが存在するか確認。
    2. カレントディレクトリの確認
      pwd コマンドで現在の作業ディレクトリを確認します。ファイル名を指定する際にフルパスではなくファイル名だけを指定している場合、現在のディレクトリに書き込まれます。
      • pwd で確認し、必要であれば cd('新しいディレクトリ') で移動します。
    3. 書き込み権限の確認
      書き込み先のディレクトリに対する書き込み権限があるか確認します。特に / (ルート) や /usr, /bin などのシステムディレクトリには通常ユーザーは書き込めません。
      • 書き込み可能なディレクトリ(例: ホームディレクトリ、デスクトップ、または自分で作成したディレクトリ)に保存するようにパスを変更してください。
    4. ファイル名の確認
      ファイル名にWindowsで許可されていない文字(例: \ / : * ? " < > |)が含まれていないか確認します。
  • エラーメッセージ例

    error: '__dlmwrite__': unable to open file 'C:\path\to\nonexistent\directory\data.csv' for writing
    error: called from
        __dlmwrite__ at line 417 column 7
        csvwrite at line 46 column 10
    

    または

    error: '__dlmwrite__': unable to open file '/root/data.csv' for writing: Permission denied
    
    • 指定したファイル名に不正な文字が含まれている。
    • 書き込み先のディレクトリが存在しない。
    • 書き込み権限がないディレクトリに書き込もうとしている。
    • カレントディレクトリが意図しない場所になっている。

エラー: データ型が不正 (Input must be a numeric matrix)

csvwriteは数値行列のみを扱います。文字列やセル配列、論理値(boolean)などを含む行列を渡すとエラーになります。

  • トラブルシューティング

    1. データ型の確認
      書き込もうとしている変数 M の型を確認します。
      • class(M) コマンドで型を確認します。例えば、cellchar と表示されたら数値行列ではありません。
      • isnumeric(M) で数値かどうかを真偽値で確認できます。
    2. 数値データへの変換
      • もしデータに文字列が含まれている場合は、数値部分だけを抽出するか、文字列を数値に変換する必要があります。
      • 文字列と数値が混在するデータを書き出す場合は、dlmwriteをより柔軟に使うか、fprintf関数を使って手動でフォーマットして書き出すことを検討してください。
  • エラーメッセージ例

    error: csvwrite: input must be a numeric matrix
    
  • 考えられる原因

    • 書き込もうとしている行列に数値以外のデータが含まれている。

警告: 数値がNaN (Not a Number) または Inf (Infinity)

データ中に NaN (非数) や Inf (無限大) が含まれている場合、csvwriteはそれらをファイルに書き出しますが、読み込み側のプログラムによっては問題になることがあります。

  • トラブルシューティング

    1. データの確認
      M の中に NaNInf が含まれていないか確認します。
      • any(isnan(M(:)))NaNの存在を、any(isinf(M(:)))Infの存在を確認できます。
    2. NaN/Infの処理
      • これらの値を無視するか、特定の値(例: 0)に置き換えるかを決定します。
      • M(isnan(M)) = 0; (NaNを0に置き換える例)
      • M(isinf(M)) = NaN; (InfをNaNに置き換える例)
    3. 読み込み側の考慮
      CSVファイルを読み込む側のプログラムが NaNInf をどのように扱うかを理解しておくことが重要です。多くの言語ではこれらを正しく解釈できますが、一部のシンプルなパーサーでは問題になる可能性があります。
  • 考えられる原因

    • 計算結果が不定(0/0など)になったためにNaNが発生した。
    • オーバーフローやゼロ除算によってInfが発生した。

問題: ファイルの改行コード (Windowsで正しく表示されない)

csvwriteは内部的にLF(Line Feed)のみを改行コードとして使用します。このため、Windowsのメモ帳などの一部のテキストエディタで開くと、データが一行に表示されてしまうことがあります。

  • トラブルシューティング

    1. 高機能なテキストエディタの使用
      Notepad++、VS Code、Sublime Textなどの高機能なテキストエディタを使用すると、LFのみの改行コードでも正しく表示されます。
    2. dlmwriteの使用
      より確実にWindowsで正しく表示させたい場合は、dlmwrite関数で'newline', 'pc'オプションを指定します。
      data = [1, 2; 3, 4];
      dlmwrite('my_data_win.csv', data, 'delimiter', ',', 'newline', 'pc');
      
    3. Excelなどのスプレッドシートソフトでの開く
      Excelなどのスプレッドシートソフトで開く場合は、改行コードの違いは通常問題になりません。
  • 考えられる原因

    • Windowsのメモ帳はCRLF(Carriage Return + Line Feed)を標準の改行コードとして期待しているため。

問題: 桁数やフォーマットの制御

csvwriteは数値のフォーマット(小数点以下の桁数など)を直接制御するオプションがありません。

  • トラブルシューティング

    1. dlmwriteの使用
      dlmwrite関数では'precision'オプションを使って出力精度を制御できます。
      data = [1.2345, 6.7890];
      dlmwrite('formatted_data.csv', data, 'delimiter', ',', 'precision', '%0.2f'); % 小数点以下2桁に丸める
      
    2. fprintfの使用
      より複雑なフォーマットやヘッダー・フッターの追加が必要な場合は、fprintf関数を使ってファイルへの書き込みを完全に制御します。
      fid = fopen('custom_data.csv', 'w');
      fprintf(fid, 'Header Row 1,Header Row 2\n');
      fprintf(fid, '%f,%f\n', data'); % データの書き込み (転置して列ごとに処理)
      fclose(fid);
      
  • 考えられる原因

    • デフォルトの精度では意図した通りの桁数で出力されない。
  • Octaveのヘルプを利用
    help csvwritehelp dlmwrite コマンドで、関数の詳細な説明とオプションを確認できます。
  • 変数の内容を確認
    disp(M)M と入力してEnterを押すことで、書き込もうとしている変数の内容と型が期待通りになっているかを確認します。
  • 小さなデータセットで試す
    まずは非常に小さなテストデータセットでcsvwriteを試してみて、正しく動作するかどうかを確認します。


Octaveのcsvwrite関数は、数値行列をCSV(Comma Separated Values)形式のファイルに書き出すために使われます。非常にシンプルで直感的です。

基本的な使い方:数値行列をCSVに書き出す

最も一般的な使用例です。Octaveで作成した数値データをCSVファイルとして保存します。

% 例1: 基本的な数値行列の作成
data_matrix = [
    10, 20, 30;
    40, 50, 60;
    70, 80, 90
];

% 'my_data.csv' という名前でCSVファイルに書き出す
% このファイルはOctaveが実行されている現在のディレクトリに作成されます。
csvwrite('my_data.csv', data_matrix);

disp('data_matrixがmy_data.csvに書き出されました。');

% my_data.csv の内容は以下のようになります:
% 10,20,30
% 40,50,60
% 70,80,90

解説

  • csvwrite('my_data.csv', data_matrix)で、この行列のデータをmy_data.csvというファイルに保存しています。各要素はカンマで区切られ、各行は改行されます。
  • data_matrixという3x3の数値行列を作成しています。

計算結果をCSVに保存する

シミュレーションやデータ解析の結果をCSVとして保存する場面で役立ちます。

% 例2: 計算結果をCSVに保存
% 0から2πまでのサインとコサインの値を計算
t = linspace(0, 2*pi, 10); % 0から2πまで10点
sin_t = sin(t);
cos_t = cos(t);

% 時間(t)とsin(t)、cos(t)を結合して行列にする
% 注意: csvwriteは数値行列のみを受け付けるため、全て数値である必要があります。
results_matrix = [t', sin_t', cos_t']; % 行列として結合するために転置 (列ベクトルにする)

% 'simulation_results.csv' に書き出す
csvwrite('simulation_results.csv', results_matrix);

disp('計算結果がsimulation_results.csvに書き出されました。');

% simulation_results.csv の内容は以下のようになります(一部):
% 0.000000,0.000000,1.000000
% 0.698132,0.643037,0.765955
% ...

解説

  • この行列をsimulation_results.csvに保存しています。
  • これらのベクトルを[t', sin_t', cos_t']のように転置して結合することで、3列の行列を作成しています。これは、csvwriteが各行をCSVの1行として扱うためです。
  • linspaceで時間のベクトルを作成し、sincos関数で対応する値を計算しています。

指定したディレクトリにCSVファイルを保存する

現在の作業ディレクトリとは異なる場所にファイルを保存したい場合に、フルパスを指定します。

% 例3: 特定のディレクトリに保存
% Windowsの場合のパスの例: 'C:\\Users\\YourUser\\Documents\\output_data.csv'
% Linux/macOSの場合のパスの例: '/home/youruser/Documents/output_data.csv'

% 環境に合わせてパスを修正してください
if ispc() % Windowsの場合
    output_path = 'C:\\temp\\output_data.csv'; % 事前にC:\tempが存在することを確認してください
else % Linux/macOSの場合
    output_path = '/tmp/output_data.csv'; % /tmpは一時ファイル用ディレクトリとしてよく使われます
end

% データを生成
data_to_save = magic(5); % 5x5の魔方陣行列

% 指定したパスに書き出す
try
    csvwrite(output_path, data_to_save);
    disp(['データが ', output_path, ' に書き出されました。']);
catch
    disp(['エラー: ', output_path, ' への書き込みに失敗しました。パスを確認してください。']);
    disp('書き込み権限がないか、ディレクトリが存在しない可能性があります。');
end

解説

  • try...catchブロックを使用することで、ファイル書き込みが失敗した場合(例: 指定したディレクトリが存在しない、書き込み権限がない)にエラーメッセージを表示し、プログラムがクラッシュするのを防いでいます。実際にこのコードを実行する前に、指定したディレクトリが存在し、書き込み権限があることを確認してください。
  • ispc()関数を使ってOSを判別し、それぞれのOSに適したパスの例を示しています。

csvreadで読み込み、処理してcsvwriteで保存する

既存のCSVファイルを読み込み、何らかの処理を行った後に新しいCSVファイルとして保存する典型的なワークフローです。

% 例4: CSVの読み込み -> 処理 -> CSVの書き出し
% まず、テスト用のCSVファイルを作成します(以前の例で作成したmy_data.csvを使用)
data_matrix = [10, 20, 30; 40, 50, 60; 70, 80, 90];
csvwrite('my_data.csv', data_matrix);
disp('テスト用のmy_data.csvが作成されました。');

% 'my_data.csv' を読み込む
% csvreadは数値データのみを読み込みます
loaded_data = csvread('my_data.csv');
disp('my_data.csvを読み込みました:');
disp(loaded_data);

% 読み込んだデータに何らかの処理を行う(例: 各要素を2倍にする)
processed_data = loaded_data * 2;
disp('処理後のデータ:');
disp(processed_data);

% 処理後のデータを新しいCSVファイルに書き出す
csvwrite('processed_data.csv', processed_data);
disp('処理済みデータがprocessed_data.csvに書き出されました。');

% processed_data.csv の内容は以下のようになります:
% 20,40,60
% 80,100,120
% 140,160,180

解説

  • 最後に、処理後のデータをprocessed_data.csvという新しいファイルに保存しています。
  • 読み込んだデータに対して簡単な算術演算(各要素を2倍)を行っています。
  • csvread('my_data.csv')でファイルからデータを読み込み、loaded_data変数に格納しています。
  • 最初にcsvwriteを使ってmy_data.csvを作成し、これを読み込むための準備をしています。

dlmwriteを使ったより柔軟な書き出し(csvwriteの代替)

csvwriteはシンプルですが、区切り文字の変更や数値のフォーマット制御、ヘッダーの追加など、より高度な機能が必要な場合はdlmwriteを使用します。csvwriteは内部的にdlmwriteをカンマ区切りで使用しているため、dlmwriteを理解することは重要です。

% 例5: dlmwriteを使ったより柔軟な書き出し
data_with_precision = [
    1.2345, 6.7890;
    10.111, 20.222
];

% 小数点以下2桁で書き出す例
% 'delimiter'で区切り文字、'precision'で数値のフォーマットを指定します
dlmwrite('formatted_output.csv', data_with_precision, 'delimiter', ',', 'precision', '%0.2f');
disp('formatted_output.csvが作成されました(小数点以下2桁)。');

% formatted_output.csv の内容:
% 1.23,6.79
% 10.11,20.22

% ヘッダー行を追加する例 (dlmwriteのappendモードや、fprintfと組み合わせる)
% dlmwriteで直接ヘッダーを追加する機能はないため、一般的にはfprintfでヘッダーを書き込んだ後にdlmwriteでデータを追記します。
header_row = 'Column A,Column B,Column C';
data_with_header = [1,2,3; 4,5,6];

% ファイルを書き込みモードで開く
fid = fopen('data_with_header.csv', 'w');
% ヘッダー行を書き込む (改行も含む)
fprintf(fid, '%s\n', header_row);
% ファイルを閉じる (dlmwriteが再度開くため)
fclose(fid);

% データを追記モードで書き込む
% 'append', 'on' で既存のファイルに追記します
dlmwrite('data_with_header.csv', data_with_header, 'delimiter', ',', 'append', 'on');
disp('data_with_header.csvが作成されました(ヘッダー付き)。');

% data_with_header.csv の内容:
% Column A,Column B,Column C
% 1,2,3
% 4,5,6
  • ヘッダー行の追加はdlmwrite単体では少し複雑ですが、fprintfでヘッダーを書き込んだ後、dlmwrite'append', 'on'オプションで追記モードで実行することで実現できます。これはCSVにヘッダーを含めたい場合の一般的なアプローチです。
  • dlmwrite'precision'オプションを使って、出力される数値の小数点以下の桁数を制御しています。'%0.2f'は浮動小数点数を小数点以下2桁で表示するという意味です。


Octaveにおけるcsvwriteの代替方法

csvwriteは数値行列をCSV形式で書き出すのに便利ですが、より柔軟性が必要な場合や、特定の種類のデータを扱う場合には、他の関数や手法が役立ちます。主な代替方法としては、dlmwritefprintf、そして場合によってはsave関数が挙げられます。

dlmwrite (Delimiter-Separated Value file write) は、csvwriteのより強力で汎用性の高いバージョンです。実際、csvwriteは内部的にdlmwriteをカンマ区切りで使用しています。

特徴

  • 改行コードの指定: Windows (CRLF) や Unix/Linux (LF) など、OSに応じた改行コードを指定できます。
  • 追記モード: 既存のファイルにデータを追記することができます。
  • 数値フォーマットの制御: 出力する数値の精度(小数点以下の桁数)やフォーマットを細かく指定できます。
  • 区切り文字の指定: カンマ以外にも、タブ (\t)、スペース ()、セミコロン (;) など、任意の区切り文字を指定できます。
% サンプルデータ
data = [1.2345, 6.7890;
        10.111, 20.222];

% 1. タブ区切りで書き出す例
dlmwrite('tab_separated.txt', data, 'delimiter', '\t');
disp('tab_separated.txt が作成されました(タブ区切り)。');
% ファイル内容の例:
% 1.2345    6.7890
% 10.111    20.222

% 2. 小数点以下2桁でカンマ区切りに書き出す例
dlmwrite('formatted_output.csv', data, 'delimiter', ',', 'precision', '%0.2f');
disp('formatted_output.csv が作成されました(小数点以下2桁)。');
% ファイル内容の例:
% 1.23,6.79
% 10.11,20.22

% 3. 既存ファイルにデータを追記する例
new_data = [30.33, 40.44];
dlmwrite('formatted_output.csv', new_data, 'delimiter', ',', 'precision', '%0.2f', 'append', 'on');
disp('formatted_output.csv に新しいデータが追記されました。');
% ファイル内容の例:
% 1.23,6.79
% 10.11,20.22
% 30.33,40.44

% 4. Windows互換の改行コードで書き出す例
dlmwrite('windows_compatible.csv', data, 'delimiter', ',', 'newline', 'pc');
disp('windows_compatible.csv が作成されました(Windows互換改行)。');

fprintf関数: 最高の柔軟性と制御

fprintf関数は、C言語のprintfに似た機能を提供し、ファイルへのテキスト出力において最も細かい制御を可能にします。数値だけでなく、文字列や混在するデータ型も自由にフォーマットして書き出すことができます。

  • ファイル操作の基本: ファイルを開く (fopen)、書き込む (fprintf)、閉じる (fclose) という基本的なファイルI/Oの概念を理解するのに役立ちます。
  • 文字列データの書き出し: csvwritedlmwriteでは直接扱えない文字列を含むデータを書き出せます。
  • ヘッダー/フッターの追加: データの前後に任意のテキスト(ヘッダー、メタデータなど)を自由に追加できます。
  • 自由なフォーマット: %f (浮動小数点数), %d (整数), %s (文字列) などのフォーマット指定子を使って、データの出力形式を正確に制御できます。
% サンプルデータ
numeric_data = [10, 20.5;
                30, 40.0];
string_header = {'Name', 'Value'}; % 文字列のヘッダー

% 出力ファイル名
output_filename = 'custom_formatted_data.csv';

% 1. ファイルを書き込みモードで開く
% 'w' は書き込みモード(ファイルが既存の場合は上書きされます)
% 'a' は追記モード
fid = fopen(output_filename, 'w');

% 2. ヘッダー行を書き込む
% 文字列は %s で、カンマで区切り、改行 (\n) を追加
fprintf(fid, '%s,%s\n', string_header{1}, string_header{2});

% 3. データ行を書き込む
% 各行のデータをループで処理
% %d は整数、%f は浮動小数点数
% 注意: Octaveは列優先で処理するため、転置オペレーター (') を使うことがよくあります
for i = 1:rows(numeric_data)
    fprintf(fid, '%d,%.1f\n', numeric_data(i, 1), numeric_data(i, 2));
end

% 4. ファイルを閉じる (重要!)
fclose(fid);

disp([output_filename, ' が作成されました(カスタムフォーマット)。']);
% ファイル内容の例:
% Name,Value
% 10,20.5
% 30,40.0

解説

  • fclose(fid)を忘れないでください! これを忘れると、データが正しくファイルに書き込まれなかったり、ファイルがロックされたままになったりする可能性があります。
  • ループ処理を使って、行列の各行を個別にフォーマットして書き出しています。
  • 文字列ヘッダーの書き出しには%sを使用し、数値データには%d%f(小数点以下の桁数指定も可能)を使用しています。
  • fprintfの最初の引数はfid、2番目の引数はフォーマット文字列です。その後に、フォーマット文字列に合うデータを渡します。
  • fopenでファイルを開き、戻り値のfid (ファイルID) を使ってファイル操作を行います。

save関数: Octave固有のデータ保存(CSVではない)

これは直接CSV形式で保存するものではありませんが、Octaveのワークスペース変数全体を保存する目的で使用されます。.matファイルとして保存され、OctaveやMATLABで後で読み込むことができます。これは「CSVに書き出す」という目的とは異なりますが、データ永続化の代替手段として紹介します。

  • 高速: 大量のデータを保存する際にcsvwritefprintfよりも高速な場合があります。
  • 全てのデータ型を保存: 数値、文字列、セル配列、構造体など、あらゆるOctaveのデータ型を元の形式で保存できます。
  • Octave/MATLAB固有: .matファイルはOctaveやMATLABでのみ(または対応するライブラリを使って)読み込めます。汎用的なCSVとは異なります。
% サンプルデータ (様々なデータ型)
my_numeric_data = [1, 2; 3, 4];
my_string = 'Hello, Octave!';
my_cell_array = {'apple', 10, true};
my_struct.name = 'Test';
my_struct.value = 99;

% ワークスペースの変数をすべて 'my_workspace.mat' に保存
save('my_workspace.mat');
disp('ワークスペースの変数が my_workspace.mat に保存されました。');

% 特定の変数のみを保存
save('selected_data.mat', 'my_numeric_data', 'my_string');
disp('my_numeric_data と my_string が selected_data.mat に保存されました。');

% 後で読み込む際
% load('my_workspace.mat'); % これで保存した変数がすべてワークスペースに戻ります
  • この方法は、CSVのように汎用的なデータ交換フォーマットとしてではなく、主にOctave/MATLAB環境内でのデータの一時保存や共有に用いられます。
  • save('filename.mat', 'var1', 'var2')のように変数名を指定することで、特定の変数のみを保存することもできます。
  • save('filename.mat')で、現在のワークスペースにある全ての変数を指定した.matファイルに保存します。
  • Octave/MATLAB環境で全てのデータ型を高速に保存・復元したい場合: save (CSVではない)
  • 文字列を含む、複雑なフォーマット、ヘッダー/フッターを自由に追加したい場合: fprintf
  • 区切り文字、精度、追記、改行コードを制御したい場合: dlmwrite
  • 簡単な数値データのCSV書き出し: csvwrite