(学習ログ)Python007:複数CSVを読み込み→縦結合→主キーで結合→集計の基本
1. はじめに
-
この記事の目的
- 複数のCSVファイルを読み込み、
concatで縦に結合し、mergeで主キー結合し、最終的に数値列の生成・基本統計・欠損確認まで行う「実務の最小ワークフロー」を身につけます。
- 複数のCSVファイルを読み込み、
-
この記事の概要
- コード全体を提示し、処理ブロックごとに「何をしているか」を簡潔に説明します。
2. サンプルコード
import pandas as pd
sample_transaction1 = pd.read_csv('001_サンプル/sample_transaction_data1.csv')
sample_transaction2 = pd.read_csv('001_サンプル/sample_transaction_data2.csv')
sample_transaction = pd.concat([sample_transaction1, sample_transaction2], ignore_index=True)
sample_transaction_detail1 = pd.read_csv('001_サンプル/sample_transaction_detail1.csv')
sample_transaction_detail2 = pd.read_csv('001_サンプル/sample_transaction_detail2.csv')
sample_transaction_detail = pd.concat([sample_transaction_detail1, sample_transaction_detail2], ignore_index=True)
sample_join_data = pd.merge(sample_transaction_detail, sample_transaction[["transaction_id", "payment_date", "customer_id"]], on='transaction_id', how="left")
sample_file = pd.read_csv('001_サンプル/sample_file.csv')
sample_join_data = pd.merge(sample_join_data, sample_file, on="customer_id", how="left")
sample_item_list = pd.read_csv('001_サンプル/sample_item_list.csv')
sample_join_data = pd.merge(sample_join_data, sample_item_list, on="item_id", how="left")
sample_join_data["price"] = sample_join_data["quantity"] * sample_join_data["item_price"]
sample_join_data.isnull().sum()
sample_join_data.describe()
print(sample_join_data["payment_date"].min())
print(sample_join_data["payment_date"].max())
ブロックごとの解説(要点だけ)
-
import pandas as pd- データ分析の定番ライブラリpandasを読み込み。
-
pd.read_csv(...)× 5- 取引(transaction)・注文明細(transaction_detail)・顧客ファイル・商品マスタをそれぞれ読み込み。
- ポイント:実務では列名・文字コード(
encoding='utf-8'など)・型(dtype=)・日付(parse_dates=)の指定が安定運用に効きます。
-
pd.concat([df1, df2], ignore_index=True)× 2- 月次などに分かれたCSVを「同じ列構造」で縦結合。
ignore_index=Trueで連番に振り直し。
- 月次などに分かれたCSVを「同じ列構造」で縦結合。
-
sample_transaction[["transaction_id", "payment_date", "customer_id"]]- 不要列を落とし、結合に必要な列だけを選択。メモリ節約&思わぬ重複列の混入を防ぎます。
-
pd.merge(..., on='transaction_id', how='left')- 注文明細に対して、取引ヘッダ側の「支払日・顧客ID」を左外部結合。明細が主、ヘッダを付け足すイメージ。
-
pd.merge(..., on='customer_id', how='left')- 顧客属性(例:顧客名・会員区分など)を付与。
-
pd.merge(..., on='item_id', how='left')- 商品マスタ(例:商品名・単価)を付与。
-
sample_join_data["price"] = quantity * item_price- 明細行の金額を計算。算出列の基本パターン。
-
isnull().sum()- 列ごとの欠損数を一括確認。結合漏れ・データ欠落の早期発見に必須。
-
describe()- 数値列の要約統計(件数・平均・標準偏差・四分位など)。異常値の目安に。
-
print(payment_date.min()/max())- 期間の下限・上限を確認。レポート対象期間の妥当性チェックに便利。
- ※
payment_dateが文字列型だと「辞書順」比較になります。日付として扱うには後述の「中級Tips」を参照。
実行結果例
実際のファイル内容に依存しますが、再現の目安としてご覧ください。
欠損数の例(isnull().sum())
transaction_id 0
item_id 0
quantity 0
payment_date 0
customer_id 0
customer_name 5
membership_rank 5
item_name 0
item_price 0
price 0
dtype: int64
- 顧客マスタに存在しないIDが少数混ざり、
customer_name等が欠損になっている想定。
要約統計の例(describe() 抜粋)
quantity item_price price
count 1200.000000 1200.000000 1200.000000
mean 1.42 980.50 1392.31
std 0.68 320.10 910.22
min 1.00 120.00 120.00
25% 1.00 800.00 800.00
50% 1.00 1000.00 1000.00
75% 2.00 1200.00 2000.00
max 5.00 2980.00 8940.00
期間チェック(min()/max())
2024-01-01
2024-03-31
- ※この出力は
payment_dateが日付型であることを前提にしています。もし文字列のままなら"2024-01-01"と"2024-12-9"のように辞書順比較になる点に注意。
3. エラーと確認のポイント
代表的なエラー文(原因と対処)
-
FileNotFoundError: [Errno 2] No such file or directory: '...csv'- 原因:パスやファイル名の誤り。作業ディレクトリが想定と違う。
-
対処:相対パスの基準(
os.getcwd()で確認)を見直す/絶対パスで指定/Pathを使って組み立てる。
-
KeyError: 'transaction_id'(または他の列名)- 原因:CSVの列名が想定と不一致、前処理で列が落ちた、スペル・大文字小文字の違い。
-
対処:
df.columnsで列名を確認、前段のusecols=やrename()を活用。
-
ValueError: You are trying to merge on object and int64 columns- 原因:結合キーの型不一致(例:片方が文字列、もう片方が整数)。
-
対処:
astype(str)などで結合前に型を合わせる。
-
ParserError: Error tokenizing data- 原因:CSVの区切りや引用符が乱れている。
-
対処:
sep=','やquotechar='"'を明示、問題行の特定にはon_bad_lines='skip'(検証目的に限定)も。
-
DtypeWarning: Columns (X) have mixed types- 原因:同じ列に数値と文字列が混在。
-
対処:
dtype=を指定、読み込み後にto_numeric(errors='coerce')で揃える。
よく使う確認メソッドや出力例
1) 形と列名
sample_join_data.shape
# 例: (1200, 10)
list(sample_join_data.columns)
# 例: ['transaction_id','item_id','quantity','payment_date','customer_id',
# 'customer_name','membership_rank','item_name','item_price','price']
2) 先頭・末尾の確認
sample_join_data.head(3)
sample_join_data.tail(3)
3) 型の確認と修正(重要)
sample_join_data.dtypes
# payment_date object ← 文字列の可能性
# 日付に直す(推奨)
sample_join_data['payment_date'] = pd.to_datetime(sample_join_data['payment_date'], errors='coerce')
4) 結合キーの品質確認
# 重複チェック(主キー想定の列に)
sample_transaction['transaction_id'].duplicated().sum()
# 例: 0(0なら一意)
5) 結合漏れの特定
# どの顧客がマッチしなかったか
unmatched = sample_join_data[sample_join_data['customer_name'].isna()][['customer_id']].drop_duplicates()
print(unmatched.head())
6) 読み込みの安定化(中級Tips)
# 日付・型・必要列を安定指定して読み込む(例)
sample_transaction1 = pd.read_csv(
'001_サンプル/sample_transaction_data1.csv',
usecols=['transaction_id','payment_date','customer_id'],
dtype={'transaction_id':'string','customer_id':'string'},
parse_dates=['payment_date']
)
4. まとめ
-
縦結合(
concat)と横結合(merge)の基本パターンを押さえ、必要列だけを選んで安全に結合できるようになりました。 -
品質確認の要点(
isnull().sum(),describe(), 期間のmin/max) を通じて、早期に異常を見つける流れを学びました。 -
実務でハマりやすい論点(パス・列名・型不一致・日付型) への具体的な対処(
dtype,parse_dates,astype,to_datetime)を理解しました。
Discussion