🐍

(学習ログ)Python006:複数CSVの結合と売上集計の基本フロー

に公開

1. はじめに

  • この記事の目的
    複数のCSVファイルを読み込み、縦方向の結合(concat)、キーに基づく横方向の結合(merge)、そして列演算・合計値の算出までを学びます。

  • この記事の概要
    サンプルコードを行(またはブロック)単位で解説し、初心者がつまずきやすい「列指定の二重角括弧」やmergeの考え方、確認に便利なメソッド(head/info/shape/isnaなど)を紹介します。


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"]
print(sample_join_data["price"].sum())
print(sample_transaction["price"].sum())

行ごと・ブロックごとの簡潔な説明

  1. import pandas as pd
    → 分析の定番ライブラリpandasを読み込みます。

  2. pd.read_csv(...transaction_data1/2...)
    → 取引(ヘッダ:transaction_id, payment_date, customer_id など想定)のCSVを2分割で読み込みます。

  3. pd.concat([...], ignore_index=True)
    → 2つの取引テーブルを縦に結合し、連番の新しいインデックスを振ります。これで「全期間の取引」sample_transactionが完成。

  4. pd.read_csv(...transaction_detail1/2...)concat
    → 明細(transaction_idごとのitem_idquantityなど想定)も同様に縦結合し、sample_transaction_detailにまとめます。

  5. pd.merge(sample_transaction_detail, sample_transaction[["transaction_id", "payment_date", "customer_id"]], on='transaction_id', how="left")
    → 明細に対して、取引のメタ情報(支払日・顧客ID)をtransaction_idで左結合。
     ポイントsample_transaction[[...]]の二重角括弧は「複数列をDataFrameのまま選ぶ」ため(後述)。

  6. pd.read_csv(...sample_file.csv...)merge(..., on="customer_id", how="left")
    → 顧客マスタを読み込み、customer_idで左結合。顧客の属性(例:氏名・区分など)を付与します。

  7. pd.read_csv(...sample_item_list.csv...)merge(..., on="item_id", how="left")
    → 商品マスタを読み込み、item_idで左結合。商品名や単価(item_price)を付与します。

  8. sample_join_data["price"] = sample_join_data["quantity"] * sample_join_data["item_price"]
    → 行単位の売上金額(数量×単価)を新列priceに計算して格納。

  9. print(sample_join_data["price"].sum())
    → 明細ベースで集計した総売上(計算列)を合計して出力。

  10. print(sample_transaction["price"].sum())
    → もし取引テーブル側に取引合計price列があるなら、その合計値も出力(突合せチェックに有用)。

実行結果例

例:

1254300
1254300

上2行はそれぞれ
1行目:明細から計算した総売上(合計)
2行目:取引テーブルに既に存在するprice合計(同額だと突合せクリア)
となります。両者が一致すれば、明細→取引の整合が取れているサインです。


3. エラーと確認のポイント

  • 代表的なエラー文と対処

    1. KeyError: 'transaction_id' / KeyError: 'customer_id' など
      原因:CSV側のカラム名が想定と違う、あるいは全角半角・大小文字が異なる。
      対処:読み込み直後にカラムを確認し、必要ならリネーム。
    print(sample_transaction.columns)
    print(sample_transaction_detail.columns)
    # 例:列名を正規化
    sample_transaction.columns = sample_transaction.columns.str.strip().str.lower()
    
    1. ValueError: You are trying to merge on object and int64 columns
      原因:結合キーの型不一致(例:customer_idが片方は文字列、片方は数値)。
      対処:読み込み時にdtypeを揃える、またはastypeで統一。
    sample_transaction = pd.read_csv(..., dtype={"customer_id": "string", "transaction_id": "string"})
    sample_transaction_detail["transaction_id"] = sample_transaction_detail["transaction_id"].astype("string")
    
    1. ParserError(CSVの区切りやエンコーディング起因)
      原因:区切り文字・引用符・文字コードの不一致。
      対処encoding="utf-8-sig"sep=";"の指定、quotecharの調整など。
    pd.read_csv(path, encoding="utf-8-sig")  # BOM付きCSV対策の一例
    

よく使う確認メソッドや出力例

最低限、以下を実施すると安心です。

  1. 形状・件数の確認(件数の増減を追う)
sample_transaction.shape       # 例: (1200, 6)
sample_transaction_detail.shape# 例: (3400, 5)
sample_join_data.shape         # 例: (3400, 12)
  1. 先頭・型・概要の確認
sample_join_data.head(3)
sample_join_data.info()
sample_join_data.dtypes
  1. 欠損値の把握(結合ミス検知)
sample_join_data.isna().sum().sort_values(ascending=False)
# 例: customer_name    10
#     item_price       3
# → キー漏れやマスタ未整備の可能性
  1. キーの重複や一意性の確認(期待に応じて)
sample_transaction["transaction_id"].duplicated().sum()  # 0が理想(一意)
sample_item_list["item_id"].duplicated().sum()
  1. mergeの検証(想定外の重複結合を検出)
pd.merge(
    sample_transaction_detail, 
    sample_transaction[["transaction_id", "payment_date", "customer_id"]],
    on="transaction_id", 
    how="left", 
    validate="m:1"  # 明細:取引 = 多対1 を期待
)
  1. 列選択の二重角括弧について(今回の重要ポイント)
     sample_transaction[["transaction_id", "payment_date", "customer_id"]] のように二重角括弧を使うと、複数列をDataFrameとして選択できます。
     一方、sample_transaction["transaction_id"](一重角括弧)はSeries(1列) になり、mergeに渡すとキーや引数の想定と合わない場合があります。結合相手にはDataFrameを渡すのが安全です。

4. まとめ

  • できるようになったこと(3点)

    • 複数CSVを縦結合(concat し、期間や分割ファイルを1つの表にまとめられる。
    • 外部キーに基づく横結合(merge で、「明細+取引+顧客+商品」の多段ジョインが組める。
    • 計算列の追加(quantity * item_price)と合計の比較により、突合せチェックまで行える。

Discussion