この記事でわかること

  • 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を使うと空になるので、先に文字として読みます
  • 桁数の決まりがはっきりしないときは、そろえる前に確かめます