PythonでExcelのコード番号の先頭の0を消さずに読み込む手順|dtypeで文字として読みzfillで桁をそろえる
Excelで「00456」と見える商品コードをPythonで読むと、456になってしまうことがあります。その理由と、pandasのdtypeで文字として読み、zfillで桁をそろえる手順を、架空の表で試して解説します。
目次
この記事でわかること
- Excelで「00456」と見えるコードが、Pythonでは456になる理由
- 0が消えるセルと、消えないセルの見分け方
- dtypeで文字として読み、zfillで桁をそろえる手順
- 数のままzfillすると空になる・CSV・符号のつまずき
商品コードや社員番号をPythonで読み込むと、先頭の0が消えることがあります。試した表でも、Excelで「00456」と見えていたコードが456になりました。ただ、0が消えたのはすべてのセルではありませんでした。この記事では、消える理由を確かめてから、桁をそろえて読み直す手順をまとめます。
調べたのは、pandas 3.1.0の公式の資料(read_excel、read_csv、Series.str.zfill)で、2026年11月1日に原文に当たりました。表の商品とコードは、確かめるために作った架空のものです。
先に結論: 文字として読み、足りない0をzfillで足す
read_excelのdtypeでコードの列を文字として読み、Series.str.zfillで決まった桁数まで左に0を足します。 dtypeだけでは、消えた0は戻りません。
| セルの中身 | そのまま読む | dtypeで文字 | zfill(5)の後 |
|---|---|---|---|
| 文字の「00123」 | 00123 | 00123 | 00123 |
| 数の456(5桁の書式) | 456 | 456 | 00456 |
| 文字の「A-001」 | A-001 | A-001 | A-001 |
0が消えるセルと、消えないセル
Excelでは、数の456に「00000」のような表示の書式を付けると、画面には「00456」と出ます。ただ、セルの中身は数の456のままです。試した表でも、このセルは書式が「00000」、中身は456でした。
pandasのread_excelが読むのは、この中身です。そのため、書式で0を見せていたセルは456として読まれます。一方で、セルに文字として「00123」と入っている場合は、文字のまま読まれ、0も残りました。
同じ列に文字と数が混ざると、その列は文字と数が入り交じった形(object)になります。試した表でも、商品コードの列は「00123」「456」「A-001」が混ざっていました。
dtypeとzfillのしくみ
read_excelの資料では、dtypeで列ごとにデータの型を指定できるとしています。{"商品コード": str}のように渡すと、その列を文字として読みます。ただし資料では、dtypeを指定しても空欄の扱いは変わらず、空として読まれるものはNaNのままだとしています。
Series.str.zfillは、文字の左に「0」を足して、指定した長さにそろえる機能です。資料では、指定した長さと同じか長い文字は変えないとしています。
手順: 商品コードの0を戻して書き出す
次のコードは、架空の表 items.xlsx(商品コード・商品名・在庫の3列)を読み、商品コードを5桁の文字にそろえて items_fixed.xlsx に書き出します。items.xlsx には書き込みません。5の数は、自分のコードの桁数に合わせます。
import pandas as pd
# 商品コードの列だけを文字として読む(元のファイルには書き込まない)
items = pd.read_excel("items.xlsx", dtype={"商品コード": str})
# 数として入っていたコードは0が消えているので、5桁になるまで左に0を足す
items["商品コード"] = items["商品コード"].str.zfill(5)
print(items)
items.to_excel("items_fixed.xlsx", index=False)
pandasのほかに、xlsxの読み書きのためにopenpyxlを入れておきます。
試した結果
架空の商品の表(5行)で動かしました。コードは、文字の「00123」、数の456に5桁の書式を付けたもの、英字入りの「A-001」、空欄、文字の「01200」です。
- 何も指定せずに読むと、コードは「00123」「456」「A-001」「(空)」「01200」でした。0が消えたのは、書式で0を見せていた行だけです
- 上のコードでは、「00123」「00456」「A-001」「(空)」「01200」になりました
- 空欄の行は、zfillの後も空のままでした
- items_fixed.xlsx のコードの列は、空欄の行を除く4行が、数ではなく文字のセルとして書き出されました
- 元の items.xlsx のハッシュ値は、実行の前後で同じでした
この検証には作業用のMacを使い、xlsxの読み込みと書き出しはpandas 3.1.0とopenpyxl 3.1.5、Python本体の版は3.12.15でした。ファイルをExcelのアプリで開いて、表示を見比べてはいません。
自分で直すか、相談するかの判断
目安は、「コードの桁数の決まりが1つに決まっているか」です。「商品コードは必ず5桁」のように決まっていれば、上のコードの5を合わせるだけで使えます。
部署や年代によって桁数が違う、英字や記号が混ざる、といった場合は、zfillで一律にそろえると別のコードと重なるおそれがあります。コードを決めた人に桁数の決まりを確かめ、そろえた後のコードに重なりがないかを数えてから使います。
つまずきやすいところ
- 数のままzfillを使う: 資料では、文字でない値はNaNになるとしています。試したときも、dtypeを付けずに読んだ列にzfillを使うと、数の456の行は「00456」ではなく空になりました
- CSVで0が消える: 試したときも、CSVに「00123」と書いてあっても、何も指定しないと123として読まれました。read_csvにもdtypeで文字の型を渡します
- マイナスの付いた値: zfillは、先頭の「-」や「+」を前に残したまま、その後ろに0を足します。試したときも「-12」は「-0012」になりました
- コードの前後に空白がある: 「00123 」のように空白が付いていると、別のコードとして扱われます。そろえ方は、PythonでExcelの表の文字の前後の空白と全角・半角をそろえる手順で紹介しています
- ほかの表とコードで結び付けたい: 0をそろえた後で別の表とつなぐ方法は、PythonでExcelの2つの表を共通の列で結合する手順にまとめています
- そろえた後に同じコードが2つある: 重なりの見つけ方は、PythonでExcelの重複データを見つける手順で紹介しています
まとめ
- Excelで「00456」と見えても、中身が数の456なら、Pythonでは456として読まれます
- read_excelのdtypeでコードの列を文字として読み、zfillで決まった桁数まで0を足します
- 数のままzfillを使うと空になるので、先に文字として読みます
- 桁数の決まりがはっきりしないときは、そろえる前に確かめます
よくある質問
Excelのセルに「00123」と文字で入っていても、0は消えますか?
試した表では消えませんでした。文字として入った「00123」は、dtypeを付けずに読んでも「00123」のままでした。0が消えたのは、セルの中身は数の456で、5桁で表示する書式によって「00456」と見えていた行です。
dtypeにstrを渡せば、それだけで0は戻りますか?
戻りません。dtypeで文字として読むと、数の456は「456」という文字になります。0を足して桁をそろえるには、続けてzfillを使います。
CSVのファイルでも同じですか?
CSVでは、ファイルの中に「00123」と書いてあっても、何も指定しないと数の123として読まれました。read_csvにdtypeで文字の型を渡すと、「00123」のまま読めます。CSVはzfillで戻す必要はありません。
コードの桁数が行によって違うときは?
zfillは、指定した桁数より短い文字だけに0を足し、同じか長い文字は変えません。桁数がそろっていない決まりのコードなら、zfillで一律にそろえず、元のExcelの書式やコードの決まりを先に確かめます。
書き出したファイルを開くと、0はどう見えますか?
試したときは、書き出したファイルのコードの列が、数ではなく文字のセルとして保存されていました。そのため、表示の書式に頼らず「00456」の形で入ります。Excelのアプリで開いた見た目は確かめていません。