Pandasデータ前処理の基本|読み込み後に確認する順番と欠損・型・重複の選び方

CSVやExcelを読み込んだ後、すぐに欠損値を埋めたり行を削除したりしていませんか。Pandasのデータ前処理で大切なのは、決まった処理をすべて行うことではありません。DataFrameの状態を確認し、問題がある列だけを直して、処理後にもう一度確認することです。

この記事では、Google Colabでそのまま実行できる小さな売上データを使い、分析前の確認から空白・型・欠損値・重複候補の判断、集計へ進むまでの流れを解説します。

この記事でわかること

  • 読み込み後に最初に確認する項目
  • 空白、数値文字列、欠損値、重複候補の見分け方
  • to_numeric()astype()fillna()dropna()を選ぶ基準
  • 前処理後に集計・可視化へ進む目安

先に結論:前処理は「確認→選択→再確認」で進めます

読み込み直後に行うことは、データを一律にきれいにすることではありません。まずinfo()で状態を確認し、問題がある列だけを処理します。

確認で見つかった状態選ぶ処理処理しない判断処理後に確認する項目
前後空白があるstr.strip()空白に意味がある場合値がそろったか
数値列が文字列to_numeric()IDなど文字列で保持すべき列dtypeと変換後のNaN
欠損値がある保持・fillna()dropna()欠損が重要な情報の場合件数、補完値、行数
重複候補があるduplicated()で確認判定列や残す基準が未確定候補行と行数

1. 実行前のデータを用意する

商品名の前後空白、数値ではない売上、欠損した担当者、重複候補の注文IDを持つ店舗売上データです。実データでも、元データを残して作業用のDataFrameを作ると安全です。

import pandas as pd
from IPython.display import display

raw_df = pd.DataFrame({
    '注文ID': [1001, 1002, 1002, 1003, 1004],
    '商品名': [' ノート ', 'ペン', 'ペン', 'ノート', '消しゴム'],
    '売上': ['1200', '不明', '1500', '900', ''],
    '購入日': ['2026-09-01', '2026-09-01', '2026-09-01', '2026-09-02', '2026-09-02'],
    '担当者': ['佐藤', None, None, '田中', '鈴木']
})
df = raw_df.copy()
display(df)

2. まずinfo()で列・型・欠損値を診断する

実行目的:行数、列名、データ型、欠損値がある列を一度に確認します。出力で見る場所Non-Null Countが行数より少ない列は欠損を含みます。見た目が数字でもobject型の売上は、計算前に内容を確認します。

print('行数・列数:', df.shape)
print('
列名:', df.columns.tolist())
print('
--- df.info() の出力 ---')
df.info()
print('
列ごとの欠損数:')
display(df.isna().sum().rename('欠損数').to_frame())

この例では担当者に2件の欠損があります。一方、売上の空文字はまだ欠損値として数えられません。詳しい読み方はpandas info()の使い方を参照してください。

3. 空白と数値文字列を、対象列だけ整える

商品名の前後空白を除き、売上を計算できる数値へ変換します。不明や空文字は0円とは限らないため、0を入れず、数値に変換できない値をNaNとして確認します。

df['商品名_clean'] = df['商品名'].str.strip()
df['売上_数値'] = pd.to_numeric(df['売上'], errors='coerce')

display(df[['商品名', '商品名_clean', '売上', '売上_数値']])
print('売上_数値のdtype:', df['売上_数値'].dtype)
print('売上_数値の欠損数:', df['売上_数値'].isna().sum())

sales_problem_rows = df.loc[df['売上_数値'].isna(), ['注文ID', '売上', '売上_数値']]
display(sales_problem_rows)

結果の読み方 ノート ノートにそろい、不明と空文字はNaNになります。errors='coerce'はコードが止まらない一方、変換に失敗した元の値を必ず確認する必要があります。

数値以外の文字が混ざる可能性があるならto_numeric()、すでに正しい値を目的の型へそろえるならastype()が目安です。IDや郵便番号のように文字そのものに意味がある列は数値化しません。詳しくはpandas to_numeric()の使い方pandas astype()の使い方を参照してください。

4. 欠損値は「何を意味するか」で選ぶ

担当者の欠損は未確認であることを明示する文字列に置き換えます。一方、売上のNaNを0にすると、未確認の売上を0円と誤解させるため補完しません。

df['担当者_clean'] = df['担当者'].fillna('担当者未確認')
display(df[['注文ID', '担当者', '担当者_clean', '売上', '売上_数値']])
print('担当者_cleanの欠損数:', df['担当者_clean'].isna().sum())
print('売上_数値の欠損数:', df['売上_数値'].isna().sum())

注意fillna(0)を売上へ使うと、未確認の売上が集計へ混ざります。反対にdropna()で行を削除すると、担当者だけが欠損した売上まで失う可能性があります。欠損の列・意味・件数を見てから選んでください。pandas fillna()の使い方Pandas dropna()・drop_duplicates()の使い方も参照してください。

5. 重複候補は、削除する前に判定列を決める

注文IDが1002の行は2つあります。ただし売上が異なるため、二重登録か修正履歴かは確定できません。まず候補を表示し、何を同一観測とみなすかを決めます。

duplicate_order_rows = df.loc[
    df.duplicated(subset=['注文ID'], keep=False),
    ['注文ID', '商品名_clean', '売上', '売上_数値', '購入日']
]
display(duplicate_order_rows)
print('注文IDが重複している候補行数:', len(duplicate_order_rows))

ここでは削除しません。更新日時・明細番号・取消区分などを確認してから、drop_duplicates()の対象列とkeepを選びます。詳しくはpandas duplicated()の使い方を参照してください。

6. 処理後の状態を再確認して集計へ進む

今回は売上が数値として確認できた行だけを別のDataFrameへ取り出します。元データは削除せず、未確認の売上と重複候補は残します。

sales_ready = df.loc[df['売上_数値'].notna()].copy()
print('元データの行数:', len(df))
print('売上を集計できる行数:', len(sales_ready))
print('売上を集計できない行数:', df['売上_数値'].isna().sum())
sales_ready.info()
display(sales_ready[['注文ID', '商品名_clean', '売上_数値', '担当者_clean']])

この例では集計できる行は3行です。集計結果は「数値として確認できた売上」のみであり、未確認の売上は含まれません。この前提を説明できる状態になってから次へ進みます。

7. 整えたデータを集計へつなげる

product_sales = (
    sales_ready.groupby('商品名_clean', as_index=False)['売上_数値']
    .sum()
    .sort_values('売上_数値', ascending=False)
)
display(product_sales)

結果はノートが2,100、ペンが1,500です。ただし未確認の売上は含みません。グループ別集計はpandas groupby・aggの使い方へ進んでください。日付ごとに分析したい場合はto_datetime().dtresample()を使います。

まとめ

  • info()で列・型・欠損を確認する。
  • 空白、型、欠損、重複のうち問題があるものだけを処理する。
  • 元の値、行数、欠損数、dtypeを処理後に再確認する。
  • 前提を理解したうえで集計・可視化へ進む。

関連記事

▲ ページトップへ戻る

欠損値はすべて埋めるべきですか?

いいえ。欠損が何を意味するか、補完すると集計や判断がどう変わるかで決めます。

to_numeric()とastype()はどちらを使えばよいですか?

変換できない値を確認したい場合はto_numeric()、正しい値を目的のdtypeへそろえる場合はastype()が目安です。

重複行はすぐに削除してよいですか?

いいえ。何を同一観測とみなすかを先に決め、duplicated(..., keep=False)で候補を確認してから判断します。

どこまで確認したら集計へ進めますか?

集計に使う列の型、欠損値、対象外にした行数、重複候補の扱いを説明できる状態になったら進みます。

コメント

タイトルとURLをコピーしました