「これは空欄と同じだよ」と教えてあげる発想
Excelの現場データには、本当は「値がない」だけなのに、いろんな書き方が混ざります。
NA-なし未入力
人間は「これは空欄みたいなものだな」とすぐわかりますが、pandas はそうはいきません。
そのまま読むと、これらは全部「普通の文字列」として扱われてしまいます。
na_values=['NA', '-'] は、
「この文字が来たら、空欄(欠損値=NaN)として扱ってね」と pandas に教えるためのスイッチです。
基本形:na_values=[‘NA’,’-‘] の挙動を理解する
最小コードと動きのイメージ
import pandas as pd
df = pd.read_excel(
"sales.xlsx",
na_values=["NA", "-"]
)
print(df.head())
print(df.isna().sum())
Pythonここで na_values=["NA", "-"] と指定すると、
セルに "NA" や "-" と書かれているところは、読み込み時に自動的に NaN(欠損値)に変わります。
重要なのは、「空欄だけが欠損ではない」ということを、自分で定義できる点です。
現場の「なんとなくの記号」を、ちゃんと「欠損」という意味に揃えてあげるイメージです。
どんなときに na_values を使うべきか
「NA」「-」が混ざっていて集計が変になるパターン
例えば、こんなデータを想像してください。
| 商品 | 数量 |
|---|---|
| りんご | 10 |
| みかん | NA |
| バナナ | – |
na_values を指定しないと、"NA" と "-" は文字列として扱われます。
その状態で df["数量"].sum() をしようとすると、型が混ざってエラーになったり、
列全体が object 型になってしまって数値として扱いづらくなります。
na_values=["NA", "-"] を指定しておけば、NA と - は最初から NaN になり、数量 列は素直に数値列として扱いやすくなります。
import pandas as pd
df = pd.read_excel(
"qty.xlsx",
na_values=["NA", "-"]
)
print(df)
print(df["数量"].dtype)
print(df["数量"].sum())
Python全列に一括で適用するパターン
ファイル全体で「この文字は欠損」と決めてしまう
na_values は、何も工夫しなければ「全列」に対して適用されます。
import pandas as pd
df = pd.read_excel(
"survey.xlsx",
na_values=["NA", "-", "なし"]
)
print(df.isna().sum())
Pythonこの例では、どの列に出てきても "NA", "-", "なし" はすべて欠損として扱われます。
アンケート結果やログデータのように、「いろんな列に同じ記号が出てくる」場合は、この一括指定がシンプルです。
列ごとに違う NA 表現を指定するパターン
列ごとに辞書で指定する
列によって「NAの書き方」が違う場合は、辞書で列ごとに指定できます。
import pandas as pd
df = pd.read_excel(
"mixed_na.xlsx",
na_values={
"数量": ["NA", "-"],
"備考": ["なし", "未入力"]
}
)
print(df.isna().sum())
Pythonここでは、
数量列では "NA" と "-" を欠損扱い
備考列では "なし" と "未入力" を欠損扱い
というルールを読み込み時に埋め込んでいます。
「列ごとに文化が違う」ようなファイルでは、この書き方がとても役に立ちます。
na_values と型変換をセットで考える
欠損を揃えてから数値化する
na_values で「変な記号」を欠損に変えたあと、to_numeric で数値に変換するのが定番パターンです。
import pandas as pd
df = pd.read_excel(
"sales.xlsx",
usecols=["商品", "数量", "金額"],
na_values=["NA", "-"]
)
df["数量"] = pd.to_numeric(df["数量"], errors="coerce")
df["金額"] = pd.to_numeric(df["金額"], errors="coerce")
print(df.dtypes)
print(df.isna().sum())
Pythonここでの流れは、
"NA"や"-"を欠損(NaN)に変える- 文字列や混在型になっている列を、数値に変換する(変換できないものは NaN にする)
という二段構えです。na_values を使うことで、「変な記号」を最初から欠損として扱えるので、数値化がスムーズになります。
実践テンプレートでイメージを固める
テンプレ1:売上データで「NA」「-」を欠損にしてから月次集計
import pandas as pd
df = pd.read_excel(
"sales.xlsx",
usecols=["日付", "金額"],
na_values=["NA", "-"],
parse_dates=["日付"]
)
df["金額"] = pd.to_numeric(df["金額"], errors="coerce")
monthly = (
df.assign(month=df["日付"].dt.to_period("M"))
.groupby("month", as_index=False)["金額"].sum()
)
print(monthly)
Pythonこのテンプレートでは、
日付をパースNA と - を欠損にする
金額を数値にする
月次集計をする
という流れを一気に書いています。na_values がないと、金額列に文字列が混ざっていて、集計前に余計な前処理が必要になりがちです。
テンプレ2:アンケート結果で「未回答」を欠損にする
import pandas as pd
df = pd.read_excel(
"survey.xlsx",
na_values={
"年齢": ["NA", "-"],
"性別": ["未回答"],
"満足度": ["未回答", "NA"]
}
)
print(df.isna().sum())
Pythonこのテンプレートは、「列ごとに違う未回答表現」を読み込み時に揃える例です。
後で「未回答を除いて平均を出す」「未回答を別カテゴリとして扱う」などの処理がやりやすくなります。
つまずきやすいポイントと注意点
本当は意味のある「-」まで欠損にしてしまう
例えば、増減を表す列で -10 や -5 のような値がある場合、
安易に na_values=["-"] としてしまうと、"-" 単体だけでなく、
場合によっては意図しないところに影響が出ることがあります。
基本的には、「セルの中身が完全に "-" のときだけ欠損にする」ので問題ないのですが、
どんな値が実際に入っているか、一度 df["列名"].unique() などで確認してから na_values を決めると安心です。
文字列として残しておきたい「NA」まで欠損にしてしまう
ときどき、「NA という文字そのものに意味がある」ケースもあります。
その場合は、その列だけ na_values の対象から外すか、
列ごとの辞書指定で「この列では NA を欠損にしない」と決める必要があります。
小さな練習問題
練習1:qty.xlsx の「数量」列で NA と - を欠損にして合計を出す
条件は次の通りです。
na_values=["NA", "-"]を指定して読み込む数量列をto_numeric(errors="coerce")で数値にする数量の合計を計算して表示する
自分で書いてみて、df["数量"] の中に NaN が入っていることと、合計値が直感と合うかを確認してみてください。
練習2:survey.xlsx で「未回答」「NA」「-」を列ごとに欠損扱いにする
条件は次の通りです。
- 年齢列では
NAと-を欠損にする - 性別列では
未回答だけを欠損にする - 満足度列では
未回答とNAを欠損にする - 各列の欠損数を
isna().sum()で表示する
ここまでできると、「現場の曖昧な記号を、ちゃんと欠損として定義し直す」という感覚がかなり身についてきます。
最後に
na_values=['NA','-'] は、
「この文字は、実質的には『値がない』ってことだよ」と pandas に教えるための仕組みです。
これを読み込み時にきちんと設計しておくと、
集計で変な値に邪魔されない
数値変換がスムーズになる
欠損の扱いを自分でコントロールできる
という、とても大きなメリットが手に入ります。
あなたの手元のExcelに、どんな「なんとなくの記号」が紛れ込んでいるか、
一度眺めてみて、「これは欠損扱いにしたいな」と思うものを na_values に落とし込んでみてください。
そこから、データが一段クリアに見え始めます。

