0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

2つのcsvファイルの差分を分析するPythonプログラム例

0
Posted at

2つのcsvファイルの違いを読み取って,その差を分かりやすくファイル出力するプログラム

一般に,2つの.csvファイルの差分をチェックする場合,データの構成・特徴(同じ行数・列数の数値データか,行数やキーが異なるデータか)によって最適なアプローチが異なる.
ここでは,行の順番は考慮せず(行の順が異なっても,差異とはみなさない),1列目と2列目をキーとして,2つのファイルの差分が分かるようにcsv2diff.csvとして出力する例を示すこととする.

1.対象とする2つの異なるcsvファイルサンプルを生成

generate_csv2files.py
import pandas as pd

# --- file1.csv(比較元)の作成 ---
data1 = {
    'ID_Main': ['A001', 'A002', 'A003', 'A004', 'A005'],
    'ID_Sub':  ['Sub_1', 'Sub_1', 'Sub_2', 'Sub_1', 'Sub_3'],
    'Value_A': [100, 200, 300, 400, 500],
    'Value_B': ['Apple', 'Banana', 'Orange', 'Grape', 'Peach']
}
df1 = pd.DataFrame(data1)
df1.to_csv('file1.csv', index=False, encoding='utf-8')

# --- file2.csv(比較先)の作成 ---
data2 = {
    'ID_Main': ['A004', 'A001', 'A003', 'A006'],  # A002, A005(削除)、A006(追加)
    'ID_Sub':  ['Sub_1', 'Sub_1', 'Sub_2', 'Sub_1'],
    'Value_A': [400, 999, 300, 600],              # ← 修正:A001を 100 -> 999 に変更
    'Value_B': ['Grape', 'Banana', 'Orange', 'Melon'] # ← A001を 'Apple' -> 'Banana' に変更
}
df2 = pd.DataFrame(data2)
df2.to_csv('file2.csv', index=False, encoding='utf-8')

print("✅ 修正版 'file1.csv''file2.csv' を正常に作成しました。")

このPythonプログラムを実行すると,カレントディレクトリに,file1.csvとfile2.csvが生成される.

2.差分を出力するプログラム

csv2diff.py
import pandas as pd
import numpy as np

def check_csv_diff(file1_path, file2_path, output_path='csv2diff.csv'):
    # 1. CSVファイルを読み込み (列名がなくても自動で扱えるよう、明示的に読み込む)
    df1 = pd.read_csv(file1_path)
    df2 = pd.read_csv(file2_path)
    
    # 2. 1列目と2列目の列名を取得(インデックス基準)
    key1 = df1.columns[0]
    key2 = df1.columns[1]
    key_columns = [key1, key2]
    
    # 3. 1列目と2列目をキーにして外部結合(行の順番が違っても自動で位置を合わせます)
    # suffixesで、どっちのファイル由来のデータか区別(_left: file1, _right: file2)
    merged = pd.merge(df1, df2, on=key_columns, how='outer', suffixes=('_left', '_right'), indicator=True)
    
    # 4. 差分を判定するステータス列の作成
    status_list = []
    
    # キー以外の列(比較対象となる列)をリストアップ
    other_columns = [col for col in df1.columns if col not in key_columns]
    
    for idx, row in merged.iterrows():
        # _merge列には 'left_only', 'right_only', 'both' が入る
        if row['_merge'] == 'left_only':
            status_list.append('❌ file1にのみ存在 (file2で削除)')
        elif row['_merge'] == 'right_only':
            status_list.append('➕ file2にのみ存在 (file2で追加)')
        else:
            # 両方にキーが存在する場合、3列目以降に値の変更があるかチェック
            is_modified = False
            for col in other_columns:
                val_left = row[f'{col}_left']
                val_right = row[f'{col}_right']
                
                # NaN(欠損値)同士の比較を考慮して判定
                if pd.isna(val_left) and pd.isna(val_right):
                    continue
                if val_left != val_right:
                    is_modified = True
                    break
            
            if is_modified:
                status_list.append('⚠️ 値の変更あり')
            else:
                status_list.append('✅ 変更なし')
                
    # ステータス列を追加し、不要になったマージ用インジケータを削除
    merged['Status'] = status_list
    merged = merged.drop(columns=['_merge'])
    
    # 見やすさのため、Status列を3列目(キー列の直後)に移動
    cols = list(merged.columns)
    cols.insert(2, cols.pop(cols.index('Status')))
    merged = merged[cols]
    
    # 5. csv2diff.csvとして出力
    merged.to_csv(output_path, index=False, encoding='utf-8-sig')
    print(f'✅ 差分チェックが完了し、"{output_path}" を出力しました。')

3.実行手順

(1)2つの比較したいファイル(file1.csvとfile2.csv)があるディレクトリに移動する.

(2)上記のcsv2diff.pyファイルの最終行を必要に応じて修正する
check_csv_diff('file1.csv','file2.csv','csv2diff.csv')
の1つ目のファイル名,2つ目のファイル名,差分出力ファイル名

(3)Pythonプログラムを実行する.

python csv2diff.py

すると,その差異を示すcsv2diff.csvファイルが生成される.

4.結果

上記サンプルのcsv2diff.csvの中身
csv2diff.jpg

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?