PythonでNA文字を欠損として扱う入門 — na_values=[‘NA’,’-‘]
Excel帳票では「NA」「—」「不明」「-」などの文字が、実質的に“欠損”を意味していることがあります。pandas.read_excel の na_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 を使うとNaNはpd.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が定番。最初に欠損を正しく揃えると、後続の集計・可視化が安定します。

