Python Excel操作 逆引き集 | NA文字を指定して欠損扱いにする

Python
スポンサーリンク

PythonでNA文字を欠損として扱う入門 — na_values=[‘NA’,’-‘]

Excel帳票では「NA」「—」「不明」「-」などの文字が、実質的に“欠損”を意味していることがあります。pandas.read_excelna_values を使えば、これらを読み込み時点で一括して NaN(欠損)に変換できます。初心者向けに、動くコード・テンプレート・つまずき対策をまとめました。


基本の使い方

import pandas as pd

# "NA" と "-" を欠損として読み込む
df = pd.read_excel("survey.xlsx", na_values=["NA", "-"])

print(df.head())
print(df.isna().sum())  # 欠損の件数を列ごとに確認
Python
  • 効果: 指定した文字列を NaN に置き換え、集計や数値変換がスムーズになります。
  • 確認: isna()info() で、どの列に欠損があるかをチェックすると良いです。

よく使うオプションの組み合わせ

import pandas as pd

df = pd.read_excel(
    "report.xlsx",
    na_values=["NA", "-", "不明", "—"],  # 欠損扱いにしたい文字を並べる
    keep_default_na=True,               # 既定の欠損(空白、"NaN" など)も有効
)
Python
  • na_values: 任意の文字列を欠損に。表に特有の「記号・注記」をまとめて指定。
  • keep_default_na=True: 既定の欠損解釈(空セル、”NaN” など)も維持。帳票で「NA」を使っていない場合でも、通常の欠損扱いが効きます。
  • keep_default_na=False: 空白や標準の “NA” を欠損扱いしたくない特殊ケースで使います(おすすめはしません)。

欠損指定と型変換の相性

import pandas as pd

df = pd.read_excel(
    "orders.xlsx",
    usecols=["OrderID", "Qty", "Amount"],
    dtype={"OrderID": "string", "Qty": "Int64"},   # 欠損に強い整数型(nullable)
    na_values=["-", "NA", "不明"]
)

# 金額は読み込み後に数値化(カンマ混入対策)
df["Amount"] = pd.to_numeric(df["Amount"], errors="coerce")
print(df.dtypes)
Python
  • 文字列固定: コード・ID"string" が安全。欠損も扱えて先頭ゼロが保持されます。
  • 整数の欠損: “Int64″(nullable整数) を使うと NaN と共存可能。通常の int は欠損を許容しません。
  • 数値化: 文字列からの数値化は pd.to_numeric(..., errors="coerce") を使うと不正値を NaN にできます。

クリーニングが必要なときは converters を併用

import pandas as pd

def clean_amount(x):
    if pd.isna(x):
        return None
    s = str(x).replace(",", "").replace("円", "").strip()
    return float(s) if s else None

df = pd.read_excel(
    "japan_sales.xlsx",
    na_values=["-", "—", "不明", "NA"],
    converters={"金額(円)": clean_amount},
    dtype={"商品コード": "string"}
)
Python
  • ポイント: 単位文字やカンマが混在する列は、na_values で欠損を揃えつつ、converters でクリーニングしてから型へ。

欠損の扱い方(読み込み後の定番処理)

  • 欠損を集計・確認する: # 列ごとの欠損件数 print(df.isna().sum()) # 行合計で欠損が多いレコードを探す print((df.isna()).sum(axis=1).value_counts().head())
  • 欠損を補完する: df["Qty"] = df["Qty"].fillna(0) # 数量の欠損を 0 に df["Amount"] = df["Amount"].fillna(df["Amount"].median()) # 金額は中央値で補完
  • 欠損を除外する: df = df.dropna(subset=["Date", "Product"]) # 重要列が欠損の行は落とす
  • 置換で微調整する: df = df.replace({"—": None, "N/A": None}) # 読み込み後に追加の欠損化も可能

つまずきやすいポイントと回避策

  • 全角と半角で文字が違う:
    回避: 欠損候補は両方指定(例: “-” と “-”、”—”)。読み込み後に str.strip() で空白も除去。
  • 空白だけのセルが欠損にならない:
    回避: keep_default_na=True を維持しつつ、必要なら後処理で df.replace(r"^\s*$", pd.NA, regex=True) を適用。
  • 「0」や「0.0」を欠損にしたくない:
    注意: na_values に “0” を含めると本当にゼロの値まで欠損になります。安易に入れない。
  • na_filter=False を使うと欠損検出自体が無効化される:
    注意: 欠損化したいなら na_filter は触らない(既定は True)。
  • 読み込み後に文字型へ戻したら NaN が “nan” 文字になることがある:
    回避: 文字列化は "string" dtype を使うと NaNpd.NA のまま扱える。

実践テンプレート

帳票特有の記号・注記を欠損化してから集計

import pandas as pd

df = pd.read_excel(
    "monthly_report.xlsx",
    usecols=["Date", "Product", "Revenue"],
    parse_dates=["Date"],
    na_values=["-", "—", "不明", "NA"]
)
df["Revenue"] = pd.to_numeric(df["Revenue"], errors="coerce")

monthly = (
    df.assign(month=df["Date"].dt.to_period("M"))
      .groupby("month", as_index=False)["Revenue"].sum()
)
print(monthly)
Python

コード列の先頭ゼロを守り、欠損は欠損のまま

import pandas as pd

df = pd.read_excel(
    "customers.xlsx",
    usecols=["CustomerID", "ZipCode", "Prefecture"],
    dtype={"CustomerID": "string", "ZipCode": "string"},
    na_values=["NA", "-", ""]
)
print(df.dtypes)
print(df.head())
Python

追加の欠損文字を後からまとめて置換

import pandas as pd

df = pd.read_excel("survey.xlsx", na_values=["NA", "-"])
df = df.replace({"未回答": pd.NA, "該当なし": pd.NA})
print(df.isna().sum())
Python

ミニ例題(練習用)

  • 例題1: 欠損指定+件数確認
import pandas as pd
df = pd.read_excel("sales.xlsx", na_values=["NA", "-", "—"])
print(df.isna().sum())
Python
  • 例題2: 欠損指定+数値化して合計
import pandas as pd
df = pd.read_excel("report.xlsx", usecols=["Amount"], na_values=["-", "不明"])
df["Amount"] = pd.to_numeric(df["Amount"], errors="coerce")
print("合計:", df["Amount"].sum())
Python
  • 例題3: 空白セルも欠損にしてからフィルタ
import pandas as pd
df = pd.read_excel("survey.xlsx", na_values=["NA", "-"])
df = df.replace(r"^\s*$", pd.NA, regex=True)  # 空白だけのセルを欠損化
print(df.dropna(subset=["Email"]).head())
Python

次の一歩

  • 欠損として扱いたい文字の一覧(例: “-“, “—”, “未回答” など)と、対象列を教えてください。 あなたの帳票に合わせた最短の na_values 指定と、その後の補完・除外テンプレートを作ります。
  • 型指定と併用が鍵。 コードやIDは "string"、数量は "Int64"、金額は to_numeric が定番。最初に欠損を正しく揃えると、後続の集計・可視化が安定します。
タイトルとURLをコピーしました