CHAPTER 6 ・ pandas を一歩進める / Lesson 22

欠損値・型・表記ゆれを整える

空欄、文字になった数字、全角半角や社名の揺れ。分析の前に必ずやる「下ごしらえ」です。

目安 25分 ・ インストール不要

このレッスンが終わったら

「分析の前に、欠損・型・表記ゆれを整える。errors='coerce' で変換できないものを見つけられる」と言える。

STEP 1

こんな場面、ありませんか?

別のシステムから出力したCSVを、そのまま集計しようとして、エラーで止まってしまった。経理や総務の仕事では、よくある場面です。ここに、10月の売上を10行だけ記録した messy.csv(「散らかったCSV」という意味の名前です)があります。

messy.csvサンプルファイル
日付,得意先名,商品,数量,金額
2025/10/01,アオイ電機(株),ノートPC,1,"120,000"
2025/10/02,株式会社 ミドリ商事,モニター,2,"70,000"
2025-10-03,ミドリ商事株式会社,モニター,2,"70,000"
2025/10/04,サクラ印刷,業務ソフト,1,48000
2025/10/05, サクラ印刷 ,業務ソフト,,48000
2025/10/06,タチバナ工業,保守サービス,1,
2025/10/07,アオイ電機(株),ノートPC,1,"120,000"
2025/10/08,ヒマワリ食品,ミネラルウォーター,10,"15,000"
2025/10/08,ヒマワリ食品,ミネラルウォーター,10,"15,000"
2025/10/09,スミレ運輸,モニター,1,不明

普通の売上表に見えますが、よく見ると、金額に「120,000」のカンマ、「不明」の文字、空欄、全角の「2」、同じ会社の書き方のばらつきが混ざっています。まず pandas で読み込んで、各列の型を見てみましょう。

messy.csv を読み込んで、型を見るpandas・サンプルファイル付き
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます

「金額」も「数量」も、object(文字の列)になっています。基礎編の orders.csv では、金額は最初から数字として読めましたが、今回は文字が混ざっているので、列全体が文字として扱われました。この状態で合計を出すと、どうなるでしょうか。

文字のまま、合計を出そうとするpandas・サンプルファイル付き
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます

TypeError(型が合わない)と出ました。文字と数字を足そうとして、止まっています。分析の前に、データを整える下ごしらえが必要です。この回では、その手順を順番に学びます。

STEP 2

欠損を数えて、金額を数字にする

最初にやるのは、どこに何が欠けているかを数えることです。空欄は、pandas では 欠損値(NaN)として読み込まれます。isna() は「欠けているか」を調べ、sum() で数えます。

列ごとの欠損の数pandas・サンプルファイル付き
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます

数量と金額に1つずつ、欠損があります。info() は、列ごとの「欠けていない数」と型をまとめて表示します。Non-Null Count が 10 より小さい列が、欠けのある列です。

次に、金額を数字にします。カンマを取ってから、数字に変換します。

金額を数字にするpandas・サンプルファイル付き
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます

金額が数字になり、合計も出せました。空欄と「不明」は nan になっています。nan が混ざる列は、float64(小数を含む数字)の型になります。合計では、nan は無視されます。

STEP 3

仕組みを読む

金額を数字にした1行は、3つの部品でできています。

pd.to_numeric(df["金額"].str.replace(",", ""), errors="coerce") の部品
pd.to_numeric(文字を数字に変える
df["金額"]対象の列
.str.replace(",", "")文字の列に使う:カンマを空に置き換える
errors="coerce"変換できないものは NaN にする
)閉じる
1行ずつ日本語にしてみる
df["金額"].str金額の列を、1つずつ「文字」として扱う入り口(文字の道具を使えるようにする)
.replace(",", "")カンマを、何もない文字に置き換える。「120,000」は「120000」になる
pd.to_numeric(...)文字になっている数字を、数字に変換する
errors="coerce"変換できなかったもの(「不明」など)は、エラーにせず、欠損値(NaN)にする
df["金額"] = ...できた数字の列で、金額の列を置き換える

日本語にすると

金額の列から、カンマを取り除き、数字に変換してください。数字にできないものは、エラーにせず「欠けている」ことにしてください。

errors="coerce"(コーズ:無理にでも変換する、の意味)の効果は、止まらずに、どれが変換できなかったかを残せることです。付けなかった場合は、最初に見つけた変換できない文字で止まります。

STEP 4

変えて、試す

① 変換できなかった行を、捨てる前に確かめる。 「不明」と書かれていた行は、変換後に NaN になるので、もともとの空欄と区別がつきません。変換の前の値と見比べて、「何かが書いてあったのに、変換できなかった行」だけを抜き出します。

変換できなかった行を抜き出すpandas・サンプルファイル付き
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます

amount.isna()(変換後に欠けている)と df["金額"].notna()(変換前は欠けていない)を &(かつ)でつなぎました。該当するのは、スミレ運輸の「不明」の1行です。空欄のタチバナ工業の行は、もともと空欄なので、ここには入りません。元の伝票を調べて、金額を確かめる行はどちらなのか、一覧で分かります。

② 全角の数字は、先に半角にそろえる。 数量に、全角の「2」があります。そのまま変換するとどうなるでしょうか。

全角の「2」を、そのまま変換するpandas・サンプルファイル付き
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます

全角の「2」が nan になってしまいました。エラーも出ないので、気づきにくい落とし穴です。Lesson 02 で学んだ NFKC(全角を半角にそろえる変換)を、列全体にかけてから変換します。pandas では .str.normalize("NFKC") と書きます。

半角にそろえてから、数字にするpandas・サンプルファイル付き
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます

「2」が 2.0 になりました。残る nan は、もともと空欄だった1行です。

③ 会社名の表記ゆれをそろえる。 「アオイ電機(株)」「株式会社 ミドリ商事」「ミドリ商事株式会社」のように、同じ会社が別の書き方になっていると、会社ごとの集計がばらばらになります。「株式会社」と「(株)」を取り除き、前後の空白(全角空白も)を取り除きます。

得意先名をそろえるpandas・サンプルファイル付き
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます

nunique() は、種類の数です。整える前は8種類、整えたあとは6社になりました。strip() は、全角の空白も取り除きます。

④ 重複を見つけて、除く。 ヒマワリ食品の10月8日の行が、2回入っています。duplicated() は、「上の行と全く同じ内容の行」に True を付けます。

重複した行を調べて、除くpandas・サンプルファイル付き
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます

keep=False は「重複している行を、全部表示する」指定です。drop_duplicates() で、1行目を残して2行目以降が除かれ、10行が9行になりました。

STEP 5

自分で書く

お題① messy.csv の金額を数字にして、合計を整数で表示してください。(nan の行は、合計に入りません)

お題①:金額の合計pandas・サンプルファイル付き
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます
ヒントを見る

pd.to_numeric(df["金額"].str.replace(",", ""), errors="coerce") で数字にし、.sum() で合計を出します。そのままでは 506000.0 と表示されるので、int(...) で囲みます。

答えの例を見る
import pandas as pd

df = pd.read_csv("messy.csv")
amount = pd.to_numeric(df["金額"].str.replace(",", ""), errors="coerce")
print(int(amount.sum()))

お題② 金額が数字にできなかった(NaN になった)行の「得意先名」を、リストで表示してください。(空欄の行も、「不明」の行も含めます)

お題②:金額が欠けている行の得意先pandas・サンプルファイル付き
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます
ヒントを見る

df[df["金額"].isna()] で、欠けている行を取り出します。その得意先名の列を .tolist() でリストにして、print します。

答えの例を見る
import pandas as pd

df = pd.read_csv("messy.csv")
df["金額"] = pd.to_numeric(df["金額"].str.replace(",", ""), errors="coerce")
print(df[df["金額"].isna()]["得意先名"].tolist())

お題③ 重複した行を除いた表の、行数を表示してください。

お題③:重複を除いた行数pandas・サンプルファイル付き
Ctrl / ⌘ + Enter でも実行

この欄では、サンプルファイルが使えます。実行のたびに、ファイルは最初の状態に戻ります。

結果
▶ 実行を押すと、ここに結果が出ます
ヒントを見る

df.drop_duplicates() で重複を除いた表ができます。その行数を len(...) で数えます。

答えの例を見る
import pandas as pd

df = pd.read_csv("messy.csv")
print(len(df.drop_duplicates()))
STEP 6

仕事ならどう使う?

理解チェックpd.to_numeric(列, errors="coerce") を実行したとき、「不明」という文字はどうなりますか?

理解チェック金額が欠けている行を、fillna(0) で 0円 にしてから集計しました。どんな問題が起きるでしょうか?