PythonでExcelの表から空白行と空の列を削除して詰める手順|何も入っていない行だけを取り除く
Excelの表の途中にある、何も入っていない行と列だけを、pandasのdropna(how="all")で取り除く手順を解説します。一部だけ空の行を残す方法と、空白の文字や見出しだけの列でつまずく点を、架空の明細で試しました。
目次
この記事でわかること
- 表の途中にある、何も入っていない行だけを取り除く方法(dropnaのhow="all")
- 一部のセルだけが空の行を、消さずに残す理由と書き方
- 値の入っていない列を取り除く方法と、残したい列の守り方
- 空白の文字だけが入ったセルや、飛んだ行の番号の直し方
Excelの明細に、何も入っていない行が途中にはさまっていたり、使っていない列が残っていたりすると、並べ替えや集計の前に1行ずつ消すことになります。この記事では、pandasで表を読み込み、すべてのセルが空の行と列だけを取り除いて、詰めた表を別のファイルに書き出すまでを、手元で動かした結果とあわせて説明します。
調べたのは、pandas 3.1.0の公式の資料(DataFrame.dropna、pandas.read_excel、DataFrame.replace、DataFrame.reset_index、DataFrame.isna)で、2026年11月3日に原文にあたりました。品名や数量は、試すために作った架空の仕入れの明細のものです。
先に結論: dropnaにhow="all"を付けて、行と列に1回ずつ使う
dropna(how="all")で、すべてのセルが空の行だけを取り除きます。 列にも同じ考え方を使うときは、axis="columns"を付けてもう1回呼びます。howを付けずに呼ぶと、1つでも空のセルがある行まで消えるので、表の途中の空の行を詰めたいときは、必ずhow="all"を付けます。
| 目的 | 書き方 | 試した明細では |
|---|---|---|
| 空白の文字だけのセルを空にする | replace(r"^\s*$", 空の値, regex=True) | 品名が空白だけの1行が空の行になる |
| すべて空の行を取り除く | dropna(how="all", ignore_index=True) | 10行から6行へ |
| すべて空の列を取り除く | dropna(axis="columns", how="all") | 6列から4列へ |
dropnaのhowとaxisのしくみ
dropnaは、空の値(NaN・NaT・None)を含む行や列を取り除きます。pandasの資料によると、howには2つの決め方があります。"any"は空の値が1つでもあればその行を取り除き、"all"はすべての値が空のときだけ取り除きます。何も指定しないときは"any"です。
axisは、取り除く向きを決めます。0(または"index")が行、1(または"columns")が列で、初めの設定は行です。1回の呼び出しで決められる向きは1つだけなので、行と列の両方を詰めるときは2回に分けて呼びます。
空と見なされるセル、見なされないセル
read_excelは、空のセルを空の値(NaN)として読み込みます。資料では、初めの設定で空と読む文字として、空の文字列のほか「#N/A」「NULL」「NaN」などを挙げています。
ただし、スペースだけが入ったセルは空として読まれません。isnaの資料でも、空の文字列のような文字は空の値に入らないとしています。見た目は空でも、スペースが1つ入っていれば、その行はhow="all"では消えません。そこで、replaceに正規表現の「^\s*$」(空白の文字だけ、または何もない)を渡し、先に空の値へ置きかえておきます。
手順: 仕入れの明細から空の行と列を取り除いて書き出す
次のコードは、架空の仕入れの明細 shiire.xlsx を読み込み、すべてのセルが空の行と列を取り除いた表を shiire_cleaned.xlsx に書き出します。shiire.xlsx には何も書き込みません。読み込むファイルの名前は、自分の明細に合わせて直してから動かします。
import pandas as pd
# shiire.xlsx は読むだけで、上書きしない
shiire = pd.read_excel("shiire.xlsx")
print("読み込んだ表:", shiire.shape)
# 空白の文字だけが入ったセルも、空のセルとして扱う
shiire = shiire.replace(r"^\s*$", float("nan"), regex=True)
# すべてのセルが空の行を取り除き、行の番号を0から振り直す
cleaned = shiire.dropna(how="all", ignore_index=True)
# すべてのセルが空の列を取り除く
cleaned = cleaned.dropna(axis="columns", how="all")
print("空の行と列を取り除いた表:", cleaned.shape)
print("取り除いた行:", len(shiire) - len(cleaned))
print("取り除いた列:", [c for c in shiire.columns if c not in cleaned.columns])
cleaned.to_excel("shiire_cleaned.xlsx", index=False)
shapeは(行の数, 列の数)の組です。取り除く前と後の数、取り除いた列の名前を画面に出しておくと、消えたものが想定どおりかを書き出す前に見比べられます。pandasでxlsxのファイルを読み書きするには、openpyxlも入れておきます。
試した結果
日付・品名・数量・単価の4列に、見出しの無い列と「備考」の列(どちらも値は空)を加えた、6列の架空の明細で動かしました。データの行は10行で、3行はすべて空、1行は品名にスペースを2つだけ入れ、付箋の行は日付と品名だけ、ホチキスの針の行は数量を0にしました。
- 「読み込んだ表: (10, 6)」と表示されました。見出しの無い列は「Unnamed: 4」という名前で読み込まれていました
- 「空の行と列を取り除いた表: (6, 4)」「取り除いた行: 4」と出ました。すべて空の3行と、スペースだけの1行です
- 「取り除いた列: ['Unnamed: 4', '備考']」と表示されました
- 日付と品名だけの付箋の行は、数量と単価が空のまま残りました
- 数量が0のホチキスの針の行も残りました。0は空の値ではないためです
- shiire_cleaned.xlsx は4列・6行で、品名はコピー用紙から封筒まで元の順に並んでいました
- 表の下に書式だけを付けた空のセルを置いておきましたが、その行は読み込んだ表に入りませんでした
- 実行の後に元の shiire.xlsx のハッシュ値を計り直すと、前と変わっていませんでした
手元のMacで動かし、pandasは3.1.0、openpyxlは3.1.5、Pythonは3.12.15でした。Excelのアプリでは開かず、書き出したファイルの中身はopenpyxlで読み直して見ました。
自分で取り除いてよいか、相談するかの判断
目安は、「空の行が、ただの入れ忘れや区切りか」です。見やすくするために空けた行や、コピーのときにできた空の行なら、上のコードで詰めてかまいません。
空の行が「ここから別の月」「ここから別の店」のような区切りの印になっている明細では、詰めると区切りがわからなくなります。また、空の列が、後で誰かが書き込むための欄として用意されていることもあります。明細を作っている人に、空の行や列に意味があるかを先に確かめます。詰めた表は別のファイルに書き出し、元のファイルは残しておきます。
つまずきやすいところ
- howを付けずに呼んで、全部の行が消える: dropna()だけで呼ぶと、試した明細では10行すべてが消えて0行になりました。値の空の列(Unnamed: 4と備考)があるため、どの行にも空のセルがあったからです。空の列を先に取り除いても、付箋の行が消えて5行になりました。途中の空の行だけを詰めたいときは、how="all"を付けます
- スペースだけのセルがある行が残る: replaceで置きかえずにdropna(how="all")を使うと、品名にスペースだけが入った行は消えず、7行が残りました。見た目では見分けられないので、取り除いた行の数を画面に出して確かめます
- 行の番号が飛んだままになる: ignore_indexを付けないと、残った行の番号は0, 1, 3, 4, 7, 8, 9のように元の位置のままでした。ignore_index=Trueを付けると0から5に振り直されます。reset_index(drop=True)でも、番号を0からの連番に戻せます
- 見出しの付いた空の列まで消える: axis="columns"のdropnaは、見出しがあっても値がすべて空なら取り除くので、備考の列も消えました。残したい列があるときは、列のdropnaの代わりに drop(columns=["Unnamed: 4"]) のように消す列を名前で指定します。試したときは、備考を含む5列が残りました
- 数量が「5.0」のような小数になる: 空のセルがある数の列は、読み込んだ時点で小数の列になり、空の行を取り除いた後も5.0のように表示されました。値そのものは変わっていません
- 空欄がどこにあるかを先に知りたい: 空のセルを行と列で一覧にする方法は、PythonでExcelの表の空欄を見つけて一覧にする手順で紹介しています
- 残した行の空欄を埋めたい: 付箋の行の数量のように、残った空欄を決めた値で埋める方法は、PythonでExcelの表の空欄を決めた値で埋める手順にまとめています
- 表の上にタイトル、下に合計の行がある: 表の外にある行を読み込む時点で飛ばす方法は、PythonでExcelの表の上や下に余計な行があるシートを読み込む手順が参考になります
まとめ
- 表の途中の空の行は、dropna(how="all")で、すべてのセルが空の行だけを取り除きます
- 列を詰めるときはaxis="columns"を付けてもう1回呼び、残したい列は名前で守ります
- スペースだけのセルは空と見なされないので、replaceで先に空の値へ置きかえます
- ignore_index=Trueで行の番号を振り直し、取り除いた行と列を画面で確かめてから書き出します
よくある質問
空の行を取り除いた結果は、元のExcelのファイルに書き込まれますか?
書き込まれません。記事のコードは仕入れの明細を読むだけで、詰めた表は別のファイルの shiire_cleaned.xlsx に保存します。試したときも、実行の前後で元の shiire.xlsx のハッシュ値に違いはありませんでした。
品名が空の行だけを取り除きたいときは、どうしますか?
dropnaのsubsetに列の名前を渡すと、その列だけを見て取り除く行を決めます。dropna(subset=["品名"])とすると、品名が空の行が消えます。試した明細では、空白の文字を空に直した後で、品名の入った6行が残りました。
値がいくつ以上入っている行だけを残す、という決め方はできますか?
できます。pandasの資料では、threshに数を渡すと、空でない値がその数だけある行を残すとしています。howと一緒には使えません。試した明細でthresh=3にすると、日付と品名の2つだけが入った付箋の行も消え、5行になりました。
inplace=Trueを付けて、元の表を書きかえてもよいですか?
pandas 3.1.0の資料では、dropnaのinplaceは使わないほうへ移っていて、pandas 4.0で無くなる予定と書かれています。試したときも、inplace=Trueを付けると警告(Pandas4Warning)が出て、戻り値はNoneでした。記事のコードのように、結果を変数に入れ直します。
取り除く前に、すべて空の行がいくつあるかを数えられますか?
数えられます。isnaで空かどうかの表を作り、行ごとにすべて空かを all(axis=1) で調べて、sum で数えます。試した明細では、そのまま数えると3行、空白の文字だけのセルを空に直してから数えると4行でした。