MATLABでExcel・CSVファイルを完全マスター:読み書きから大量データ処理まで
はじめに
データ分析業務において、ExcelやCSVファイルの処理は避けて通れない作業です。本記事では、MATLABを使用したファイル操作の基本から応用まで、実際の業務シナリオを交えながら解説します。
目次
- 基本的なファイル読み書き
- 高度なデータ処理テクニック
- 実践例:月次レポートの自動化
- 実践例:複数部署のデータ統合
- パフォーマンス最適化のコツ
1. 基本的なファイル読み書き
readtableを使用した読み込み
readtableは最も汎用的で使いやすい関数です。Excel、CSV、テキストファイルなど様々な形式に対応しています。
% CSVファイルの読み込み
data = readtable('sales_data.csv');
% Excelファイルの読み込み
data = readtable('monthly_report.xlsx');
% 特定のシートを指定
data = readtable('monthly_report.xlsx', 'Sheet', 'Sheet2');
% 範囲を指定して読み込み
data = readtable('monthly_report.xlsx', 'Range', 'A1:E100');
writetableを使用した書き込み
% CSVファイルへの書き込み
writetable(data, 'output_data.csv');
% Excelファイルへの書き込み
writetable(data, 'processed_report.xlsx');
% シートを指定して書き込み
writetable(data, 'processed_report.xlsx', 'Sheet', 'Results');
xlsread/xlswrite(レガシー関数)
これらの関数は古いバージョンとの互換性のために残されていますが、新しいコードではreadtable/writetableの使用が推奨されます。
% xlsreadの使用例(非推奨)
[num, txt, raw] = xlsread('old_format.xls');
% xlswriteの使用例(非推奨)
xlswrite('old_output.xls', data_matrix);
2. 高度なデータ処理テクニック
データ型の指定と変換
% データ型を指定して読み込み
opts = detectImportOptions('sales_data.csv');
opts = setvartype(opts, {'Date'}, 'datetime');
opts = setvartype(opts, {'ProductID'}, 'string');
opts = setvartype(opts, {'Sales'}, 'double');
data = readtable('sales_data.csv', opts);
% 読み込み後のデータ型変換
data.Date = datetime(data.Date, 'InputFormat', 'yyyy-MM-dd');
data.Sales = str2double(data.Sales);
欠損値の処理
% 欠損値の検出
missing_rows = any(ismissing(data), 2);
fprintf('欠損値を含む行数: %d\n', sum(missing_rows));
% 欠損値の削除
data_clean = rmmissing(data);
% 欠損値の補完
data.Sales = fillmissing(data.Sales, 'linear');
data.Category = fillmissing(data.Category, 'previous');
% カスタム値での置換
data.Sales(isnan(data.Sales)) = 0;
エンコーディングの指定
% 日本語を含むファイルの読み込み
data = readtable('japanese_data.csv', 'Encoding', 'Shift_JIS');
% UTF-8で保存
writetable(data, 'output_utf8.csv', 'Encoding', 'UTF-8');
3. 実践例:月次レポートの自動化
営業部門の月次レポートを自動生成するシナリオを考えます。複数の支店から送られてくるExcelファイルを統合し、分析レポートを作成します。
function generate_monthly_report(year, month)
% 設定
input_folder = 'data/branches/';
output_file = sprintf('reports/monthly_report_%d_%02d.xlsx', year, month);
% すべての支店データを読み込み
branch_files = dir(fullfile(input_folder, sprintf('*_%d%02d.xlsx', year, month)));
all_data = table();
for i = 1:length(branch_files)
file_path = fullfile(input_folder, branch_files(i).name);
% 支店名を抽出
branch_name = extractBefore(branch_files(i).name, '_');
% データ読み込み
branch_data = readtable(file_path);
branch_data.Branch = repmat({branch_name}, height(branch_data), 1);
% データ結合
all_data = [all_data; branch_data];
end
% データクレンジング
all_data = clean_sales_data(all_data);
% 集計処理
summary_by_branch = groupsummary(all_data, 'Branch', 'sum', 'Sales');
summary_by_product = groupsummary(all_data, 'Product', 'sum', 'Sales');
% レポート作成
writetable(all_data, output_file, 'Sheet', 'Raw Data');
writetable(summary_by_branch, output_file, 'Sheet', 'Branch Summary');
writetable(summary_by_product, output_file, 'Sheet', 'Product Summary');
% グラフの追加
create_charts(output_file, summary_by_branch, summary_by_product);
fprintf('月次レポートを生成しました: %s\n', output_file);
end
function data = clean_sales_data(data)
% 欠損値処理
data = rmmissing(data);
% 異常値の除去
Q1 = quantile(data.Sales, 0.25);
Q3 = quantile(data.Sales, 0.75);
IQR = Q3 - Q1;
outliers = data.Sales < (Q1 - 1.5 * IQR) | data.Sales > (Q3 + 1.5 * IQR);
data(outliers, :) = [];
% 日付の統一
data.Date = datetime(data.Date, 'Format', 'yyyy-MM-dd');
end
4. 実践例:複数部署のデータ統合
人事部、経理部、営業部から異なる形式で提供されるデータを統合する例です。
function integrate_department_data()
% 各部署のデータ読み込み関数
hr_data = read_hr_data();
finance_data = read_finance_data();
sales_data = read_sales_data();
% 共通キー(社員ID)でデータを結合
integrated_data = outerjoin(hr_data, finance_data, ...
'Keys', 'EmployeeID', 'MergeKeys', true);
integrated_data = outerjoin(integrated_data, sales_data, ...
'Keys', 'EmployeeID', 'MergeKeys', true);
% 統合レポートの生成
generate_integrated_report(integrated_data);
end
function hr_data = read_hr_data()
% 人事データ(CSV形式)
hr_data = readtable('data/hr/employee_master.csv', 'Encoding', 'Shift_JIS');
% カラム名の統一
hr_data.Properties.VariableNames{'社員番号'} = 'EmployeeID';
hr_data.Properties.VariableNames{'氏名'} = 'Name';
hr_data.Properties.VariableNames{'部署'} = 'Department';
% データ型の変換
hr_data.EmployeeID = string(hr_data.EmployeeID);
end
function finance_data = read_finance_data()
% 経理データ(Excel形式、複数シート)
salary_data = readtable('data/finance/salary.xlsx', 'Sheet', '給与');
bonus_data = readtable('data/finance/salary.xlsx', 'Sheet', '賞与');
% データの結合
finance_data = outerjoin(salary_data, bonus_data, ...
'Keys', 'EmpNo', 'MergeKeys', true);
% カラム名の統一
finance_data.Properties.VariableNames{'EmpNo'} = 'EmployeeID';
finance_data.EmployeeID = string(finance_data.EmployeeID);
end
function sales_data = read_sales_data()
% 営業データ(複数のCSVファイル)
files = dir('data/sales/performance_*.csv');
sales_data = table();
for i = 1:length(files)
monthly_data = readtable(fullfile('data/sales', files(i).name));
% 月情報の追加
[~, filename] = fileparts(files(i).name);
month_str = extractAfter(filename, 'performance_');
monthly_data.Month = repmat({month_str}, height(monthly_data), 1);
sales_data = [sales_data; monthly_data];
end
% 社員IDごとに集計
sales_data = groupsummary(sales_data, 'SalesPersonID', 'sum', 'Revenue');
sales_data.Properties.VariableNames{'SalesPersonID'} = 'EmployeeID';
sales_data.EmployeeID = string(sales_data.EmployeeID);
end
5. パフォーマンス最適化のコツ
大量ファイルの並列処理
function process_large_dataset()
files = dir('data/large_dataset/*.csv');
n_files = length(files);
% 並列処理の設定
if isempty(gcp('nocreate'))
parpool('local', 4); % 4コアで並列処理
end
% 結果を格納する配列
results = cell(n_files, 1);
% 並列処理
parfor i = 1:n_files
file_path = fullfile('data/large_dataset', files(i).name);
data = readtable(file_path);
% 各ファイルの処理
results{i} = process_single_file(data);
end
% 結果の統合
final_result = vertcat(results{:});
writetable(final_result, 'output/processed_data.xlsx');
end
function result = process_single_file(data)
% データクレンジング
data = rmmissing(data);
% 集計処理
result = groupsummary(data, 'Category', {'mean', 'std'}, 'Value');
end
メモリ効率的な読み込み
% 大きなファイルを分割して読み込み
function data = read_large_file(filename, chunk_size)
opts = detectImportOptions(filename);
total_rows = opts.DataLines(2);
data = table();
for start_row = 1:chunk_size:total_rows
end_row = min(start_row + chunk_size - 1, total_rows);
opts.DataLines = [start_row, end_row];
chunk = readtable(filename, opts);
% チャンクごとの処理
chunk = process_chunk(chunk);
data = [data; chunk];
end
end
まとめ
MATLABでのExcel・CSVファイル処理は、適切な関数と手法を選択することで、効率的かつ確実に実行できます。本記事で紹介した技術を組み合わせることで、複雑な業務要件にも対応可能です。
重要なポイント
- readtable/writetableを基本として使用する
- データ型と欠損値の適切な処理を行う
- 大量データは並列処理やチャンク処理で効率化する
- 実際の業務フローに合わせて関数を組み合わせる
これらの技術を活用して、日々のデータ処理業務を自動化し、より価値の高い分析作業に時間を割けるようになることを願っています。
追加のTips
エラーハンドリング
function safe_read_files(folder_path)
files = dir(fullfile(folder_path, '*.xlsx'));
failed_files = {};
for i = 1:length(files)
try
data = readtable(fullfile(folder_path, files(i).name));
% 処理を続行
catch ME
warning('ファイル読み込みエラー: %s', files(i).name);
failed_files{end+1} = files(i).name;
continue;
end
end
if ~isempty(failed_files)
fprintf('失敗したファイル:\n');
cellfun(@(x) fprintf(' - %s\n', x), failed_files);
end
end
進捗表示
function process_with_progress(files)
n_files = length(files);
fprintf('処理開始: %d ファイル\n', n_files);
for i = 1:n_files
% ファイル処理
data = readtable(files(i).name);
% ... 処理 ...
% 進捗表示
if mod(i, 10) == 0 || i == n_files
fprintf('進捗: %d/%d (%.1f%%)\n', i, n_files, 100*i/n_files);
end
end
end