見出し画像

データ分析の最初の敵!Pandasで汚いカラムをクリーンにする五大魔法 #68

そのデータ、そのままじゃ使えない!「形式」じゃなくて「中身」が地獄だった 😩📊

データ分析を始めようと意気込んだ僕が、最初に手に入れた武器はPandasでした。前の記事に戦いの様子を記載しています。気になる方は、後述の参考記事を見てください。

「まずはデータを読み込むところからだ!」と、pd.read_csvとかpd.read_excelとか、ファイル形式に合わせて呪文を唱える練習はバッチリ。無事、画面にデータフレーム(df)の表示がエラー内容もなくできたときは、「これで俺もパイソニストだ!」と本気で思いましたね。

ところが、現実は甘くなかった…。

読み込ませたデータを結合しようと次のデータ処理を走らせたら、やつらがきましたよ。

Python画面「KeyError: '商品ID'」

「ぇ?……『商品ID』がない?ちゃんと読み込んだのに!?」

確認すると、読み込んだ元ファイルのカラム名を見たら、全角半角はバラバラ謎の空白記号が混入している。そして、結合処理に必要なはずのカラムが、名前の不一致で**「ない」**と怒られたんです。

「あれ?このデータ、俺が手作業で整えるの…?」と、Pythonを使う意味を見失うほどのイジイジ作業に直面したんです。

めんどくさっ…。

ここでふと思ったんです。「読み込み形式にばかり気を取られて、データの中身(カラム)を整えることをPythonに任せられていないんじゃないか?」「もしかして、俺、Pythonを使いこなせてないんじゃね?!


第1章:カラム名の呪いにかかった日 😩

僕がデータ分析で最初に学んだのは――「カラム名を信用するな」という真理でした。

画面に現れたエラーはおなじみのこれ。

KeyError: '商品ID'

「いや、あるじゃん!」と思って確認すると、実際のカラム名は

  • 全角と半角が混ざっている

  • 謎のスペースが入っている

  • 記号がなぜか含まれている

……Pythonから見れば全部“別モノ”扱い。
つまり、僕の戦いは数式やグラフの前に、カラム名の掃除から始まったんです。


第2章:カラム整形の五大魔法を授かった日 ✨

絶望のKeyErrorに沈む僕に、Pythonの精霊はささやいた。
「勇者よ、カラムの呪いを解くには“技”を習得せよ」と…。

そして僕は、ひとつずつ技を学んでいった。


🪄 技その1:索敵の術(カラム確認)

まずは敵の正体を暴くこと。

print(df.columns)

👉 これを唱えると、隠れていた全角半角・謎の空白まで丸見えになる。
**「敵は見た目じゃなく“コード上の名前”だ!」**と知った瞬間。


🪄 技その2:変身の術(renameで置換)

ピンポイントで名前を変える魔法。

df = df.rename(columns={" 商品ID ": "product_id"})

👉 「お前はもう product_id だ!」と名前を与える。


🪄 技その3:浄化呪文(一括整形)

まとめて汚れを祓う大技。

df.columns = df.columns.str.strip().str.replace(" ", "_")

👉 空白や半角全角を一気に修正!
これを唱えたときの爽快感ときたら…。


🪄 技その4:覇王魔法(強制上書き)

元の名前なんて関係ない!強制的に新しい名を与える究極奥義。

df.columns = ["product_id", "sales_yen", "date"]

👉 「今日からお前らはこう呼ばれるんだ!」と覇気でねじ伏せる。


🪄 技その5:逃げの術(行ベース処理)

どうしてもカラムが信用できないときの裏技。

df.iloc[0]

👉 カラムを無視して行単位で突破する。
「戦わずして勝つ」感覚に震えた。


こうして僕は、カラム整形の五大魔法を一通り習得した。

第3章:後輩の逆襲 ― 五大魔法はまだ入口だった

五大魔法を手に入れた僕は、すっかり調子に乗っていた。
「これで俺はカラムマスター!KeyError?もう怖くないね!」

そのとき隣の席から、後輩の冷静な声が飛んできた。

後輩:「ぇ? 先輩、それで全部だと思ってるんですか?」

……えっ。


3-1.後輩の冷静な追加授業 📝

🔹 並び替えの技(順番を整える)

後輩:「データ分析ではカラムの順番を変えることも多いですよ。これで見やすさも一気に変わります」

ワイ:「おぅ、、、ありがとうな……」
(いやいやw なんで俺が五大魔法覚えた途端に急に教えてくんの!?むしろ最初に教えてくれよw)

後輩:「先輩?聞いてます?」
ワイ:「はい。先生。」

df = df[["date", "product_id", "sales_yen"]]

🔹 削除の技(不要な列を消す)

後輩:「カラム名を直すだけじゃなく、要らないカラムは潔く消しましょう」

df = df.drop(columns=["不要な列"])

🔹 変換の技(mapで一括処理)

後輩:「全部大文字にしたいとか、ルールで変換したいときはこれです」

df.columns = df.columns.map(str.upper)

ワイ:「……あ、確かにこれは便利……」
後輩:「五大魔法? あれ入門ですから。実務だとここからが本番ですよ」

ワイ:「お前、こんなの全部覚えてんの!?すげーな!」
後輩:「そんなわけないでしょw コピペですよ。コ・ピ・ペw
後輩:「覚えてるのは、“こんなことしたなぁ〜”とか、“もっと楽にできないかなぁ”って感覚だけです。あとは検索して探すんですよ」

第4章 データ形式の呪いに気づいた日

後輩:「……で、一応聞きますけど。カラム名だけじゃなくて、データ形式も整えてますよね?
ワイ:「……ん?」

ここで後輩が黒板に書き始める。

後輩:「先輩、Pandasが扱うデータ型はざっくりこんな感じですよ」

Pandasで扱う主なデータ型まとめ

ワイ:「……うわ、めっちゃ種類あるじゃん!」
後輩:「はい。で、これを知らずに計算すると、TypeErrorの地獄に落ちるんですよ」
ワイ:「また呪いかよ……」


4-1.型を確認する呪文

後輩:「まずは“敵の正体”を見抜きましょう」

# 各カラムのデータ型を確認
print(df.dtypes)

# まとめて型情報を見る
df.info()

👉 object と表示されていたら、それは「文字列(str)」扱い。
👉 datetime64 や int64 と出ていれば、正しい型になっている。


4-2.型変換の魔法

後輩:「だから言ったじゃないですか。型を整えないと、計算も比較もできませんよ

数値型に変換する

df["売上"] = df["売上"].astype(int)

日付型に変換する

df["日付"] = pd.to_datetime(df["日付"])

👉 こうすることで、初めて「日付ごとに集計」「売上の合計」みたいな処理がスムーズにできる。


4-3. データ形式の三大呪文

  1. df.dtypes / df.info() : 型を確認する(索敵の術)

  2. astype() : カラムを指定の型に変換する

  3. pd.to_datetime() : 日付文字列をDatetime型に変換

  4. pd.to_numeric() : 数値っぽい文字列を数値に変換(変換不可はNaNにできる)


4-4.後輩のトドメ

後輩:「先輩、カラム名は入口。本当の戦いはデータ型との格闘ですよ」
ワイ:「……また戦いが増えた……」

こうして僕は、カラム名に続いてデータ形式という新たな呪いに挑むことになった。
でも不思議なもので、ここを理解した瞬間、Pythonが一気に“味方”になった気がする。

第5章:【賢者の助言】汚れたデータとの戦いを終わらせる最終秘策 🛡️ ― 診断魔法で問題を括って、前処理は五大魔法で浄化せよ

後輩:「先輩、カラムと型の呪いは、個別に対処するだけじゃダメですよ。真のデータ戦士は、戦いを未然に防ぐ仕組みを作ります」

僕:「え?戦いを防ぐ…?また新しい魔法があるのか?」

後輩:「魔法じゃないです。複合呪文です。複数の呪文を組み合わせ、どんなデータが来ても自動で基準に合わせるルーチンを組むんですよ。でも、今回は診断部分を独立させて、前処理は五大魔法や追加技でやる流れにします。まず、問題を『診断魔法』で括って検知し、そこから五大魔法で浄化するんです」

💡 データ処理の鉄則:確認と結合の黄金律

後輩:「実務で複数のファイルを扱う際、先輩が目指すべき理想のフローはこれです。」

  1. マスターファイル(基準)と対象ファイルの読み込み

  2. 診断魔法でカラム名・データ型の差異を括って検知

  3. 問題あり → 五大魔法や追加技で前処理(浄化)

  4. 問題なし → 結合や集計へGO!

後輩:「診断で問題を一括把握したら、前処理は五大魔法(索敵、変身、浄化、覇王、逃げ)や追加の並び替え・削除・変換で対処。これが最短ルートです。ファイルが固定されていて、処理が決まっている状況では、ここまでの準備をしておかないと何もできません。」

僕:「なるほど、診断で括って問題を特定したら、五大魔法で浄化するのか!」

後輩:「ただし、この処理の前提は、『ゴール(結合・分析)の形が決まっていること』ですよ。
そのため、準備が必要です。前回の記事で習得したpd.read_csvを使いこなし、『マスターファイル(基準)』『処理対象ファイル』の2つを用意した状態から始めます。いいですか?」

ワイ:「お、おう」
💎 Tip 1:診断呪文:『差異検出の術(サイケンスツノジュツ)』

後輩:「まずは、この『差異検出の術』でマスターと対象ファイルのズレを明確にするんすよ。以下のコードのように、まずは確認するんすよ。」

Python

import pandas as pd

def diagnose_dataframe_differences(df_master, **target_dfs):
    """
    マスターDFと複数の対象DFのカラム名とデータ形式の差異を診断し表示する。
    """
    master_name = 'df_master'
    print(f"==================================================")
    print(f"🔮 診断開始: マスターは '{master_name}' です。")
    print(f"==================================================")

    # 1. マスターのカラム名とデータ形式を抽出
    master_cols = df_master.columns.tolist()
    master_dtypes = df_master.dtypes.apply(lambda x: x.name).to_dict()

    print(f"\n[Master Information] ({master_name})")
    print(f"   カラム数: {len(master_cols)}")
    print(f"   カラム名: {master_cols}")
    print(f"   データ型: {master_dtypes}")
    print("-" * 50)


    for target_name, df_target in target_dfs.items():
        
        target_cols = df_target.columns.tolist()
        target_dtypes = df_target.dtypes.apply(lambda x: x.name).to_dict()
        
        # 2. カラム名の差異をチェック (setを使うと正確)
        diff_cols_master_only = set(master_cols) - set(target_cols)
        diff_cols_target_only = set(target_cols) - set(master_cols)
        
        # 3. データ形式の差異をチェック
        dtype_differences = {}
        for col, master_dtype in master_dtypes.items():
            # ノイズを無視するため、厳密な文字列比較で不一致を検出
            if col in target_dtypes and target_dtypes[col] != master_dtype:
                 dtype_differences[col] = (master_dtype, target_dtypes[col])

        # 4. 結果の表示
        print(f"\n▶︎ 処理対象: {target_name} ({len(target_cols)} カラム)")
        
        # カラム名の問題
        if diff_cols_master_only or diff_cols_target_only:
            print("   ❌ カラム名 不一致 (KeyErrorの原因!)")
            if diff_cols_target_only:
                print(f"      - 不要な/名前が違うカラム: {diff_cols_target_only}")
            if diff_cols_master_only:
                print(f"      - マスターにしか無い/見つからない: {diff_cols_master_only}")
            # 💡 魔法を唱えるべき!:『カラム差分吸収の術』の出番

        else:
            print("   ✅ カラム名: OK!")

        # データ形式の問題
        if dtype_differences:
            print("   ❌ データ形式 不一致 (TypeErrorの原因!)")
            for col, (m_type, t_type) in dtype_differences.items():
                print(f"      - '{col}': Master={m_type} / Target={t_type}")
            # 💡 魔法を唱えるべき!:『型変換の魔法』の出番
        else:
            print("   ✅ データ形式: OK!")
            
    print("\n==================================================")
    print("診断終了。❌が付いた箇所に魔法を唱えましょう。")
    print("==================================================")

5-1.診断後のアクション(処理の決定)

後輩:「前処理とは、まさにこのことです。この診断結果に伴って、必要な部分にだけ五大魔法を唱える。たとえば、カラム名不一致なら『浄化呪文』や『変身の術』で一括修正。データ型不一致なら『astype()』や『pd.to_datetime()』で変換。診断で括って問題を特定したら、前処理は五大魔法で浄化 ― これで戦いは終わります。」

僕:「どのファイルにどんな問題があるか分かれば、あとは五大魔法で対処するだけか!」

5-2.後輩のトドメ

後輩:「その通りです!先輩は今、戦いを始める前に勝利を確信する術を覚えました。診断魔法で差異を括り、前処理を五大魔法に任せる ― これがデータ戦士の道ですよ!!」

おわりに:Pythonは味方、呪いはチャンス

この戦いを通じて、汚れたデータは「敵」ではなく、あなたのPythonの力を引き出す「チャンス」だと気づいたはずです。

今回の記事で学んだことは、データ分析における前処理の鉄則そのものです。

  1. 診断魔法で問題を特定し、

  2. 五大魔法(および複合呪文)で、必要な箇所にだけ処理を施す。

このフローさえあれば、あなたはもう、KeyErrorやTypeErrorといった予期せぬ呪いに怯えることはありません。

✍️ 最後に、データ戦士へ

この記事は、私自身が「こんなガイドがあれば良かったのに」という思いで書いています。あなたが実務で試してみて、データの前処理が劇的に楽になることを願っています。

記事が「面白い」「ためになった」と感じていただけたら、いいねフォローをいただけると、次の戦いのエネルギーになります!

関連記事

いいなと思ったら応援しよう!

KITAcore|キタコレ@ログプレイヤー よろしければ応援お願いします! いただいたチップはクリエイターとしての活動費に使わせていただきます!