Python Excel操作 逆引き集 | 空白列を削除しつつ読み込む

Python Python
スポンサーリンク

「最初からいらない列は読まない」という発想を持つ

現場のExcelには、なぜか「空白の列」「名前が付いていない列」「スペースだけの列」が平気で混ざっています。
それをそのまま read_excel で読むと、Unnamed: 3 みたいな謎の列が大量にできて、後の処理が一気に見づらくなります。

usecols=lambda x: x.strip() != '' は、
「列名が空(もしくは空白だけ)の列は、そもそも読み込まないでくれ」というフィルターです。
つまり、「空白列を削除する」のではなく、「最初から読み込まない」という、とても賢い入口の工夫です。


基本形:usecols=lambda x: x.strip() != ” の挙動を理解する

最小コードとイメージ

import pandas as pd

df = pd.read_excel(
    "report.xlsx",
    usecols=lambda x: x.strip() != ''
)

print(df.columns)
print(df.head())
Python

ここで usecols に渡しているのは「関数」です。
pandas は、Excelの各列の「列名」を1つずつこの関数に渡し、
戻り値が True の列だけを読み込みます。

lambda x: x.strip() != '' は、
「列名 x から前後の空白を取り除いて、それが空文字でなければ True」
つまり、「実質的に名前が空じゃない列だけ読む」という条件になっています。

ここが一番大事なポイントです。


どんな列が「読み飛ばされる」のか

具体例でイメージする

例えば、Excelのヘッダー行がこんな感じだとします。

A列B列C列D列
日付売上備考

C列はヘッダーが空欄です。
この状態で usecols=lambda x: x.strip() != '' を使うと、
C列は「列名が空なので False」と判定され、読み込まれません。

結果として、DataFrame の列は ["日付", "売上", "備考"] だけになります。

もしヘッダーがスペースだけ(" ")でも、strip() で空文字になり、同じく除外されます。
「見た目は何か書いてあるように見えるけど、実はスペースだけ」という地味に厄介な列も、きれいに落とせます。


lambda を使う usecols の仕組みを一度整理する

普段の usecols と何が違うのか

usecols には、ふつうはこういう指定をします。

usecols=["日付", "売上"]
usecols="A:C"
usecols=[0, 1, 3]
Python

これは「この列だけ読みたい」という“列の指定”です。
一方、usecols=lambda x: 条件 は、「列名に対するフィルター関数」です。

pandas は内部でこんなことをしています(イメージ):

  1. Excelのヘッダー行から列名を1つずつ取り出す
  2. その列名を lambda x: ... に渡す
  3. 戻り値が True の列だけ残す

つまり、「列名を見て、読むかどうかを決める関数」を渡している、というイメージを持ってください。


実務での使いどころ

パターン1:帳票系Excelで「謎の空白列」が混ざる

帳票出力されたExcelには、見た目を整えるための空白列がよく入っています。

A列B列C列D列E列
日付売上原価

このとき、何も考えずに読むと Unnamed: 2, Unnamed: 4 のような列が増えます。

import pandas as pd

df = pd.read_excel(
    "report.xlsx",
    usecols=lambda x: x.strip() != ''
)

print(df.columns)
Python

これで、実質的に名前のない列は最初から消えた状態で読み込めます。
後から drop するより、入口で落としてしまう方がスッキリです。

パターン2:ヘッダー行に「スペースだけ」の列が紛れている

人間の目には「何もない列」と「スペースだけの列」は区別がつきませんが、
pandas にとっては " " は立派な文字列です。

x.strip() != '' としておくことで、
スペースだけの列名も「空」とみなして除外できます。


他の引数との組み合わせ方

header と一緒に使うときの注意

usecols=lambda x: ... で渡される x は、「ヘッダーとして認識された列名」です。
つまり、header の指定によって、どの行が列名として使われるかが変わると、
x の中身も変わります。

例えば、こんな構造のExcelを考えます。

1行目: タイトル
2行目: 空白列を含むヘッダー
3行目以降: データ

この場合は、こう書きます。

import pandas as pd

df = pd.read_excel(
    "report.xlsx",
    header=1,  # 2行目をヘッダーにする
    usecols=lambda x: x.strip() != ''
)

print(df.columns)
Python

header=1 で「2行目を列名として使う」と決めた上で、
その列名に対して strip() != '' を適用している、という順番です。

dtype や parse_dates とも普通に併用できる

import pandas as pd

df = pd.read_excel(
    "report.xlsx",
    header=1,
    usecols=lambda x: x.strip() != '',
    parse_dates=["日付"],
    dtype={"店舗": "string"}
)

print(df.dtypes)
Python

usecols は「どの列を読むか」を決めるだけなので、
残った列に対しては、これまで通り parse_datesdtype を使えます。


実践テンプレート

テンプレ1:空白列を落としてから、日付と金額で集計する

import pandas as pd

df = pd.read_excel(
    "sales_report.xlsx",
    header=1,
    usecols=lambda x: x.strip() != ''
)

df["日付"] = pd.to_datetime(df["日付"], errors="coerce")
df["金額"] = pd.to_numeric(df["金額"], errors="coerce")

monthly = (
    df.assign(month=df["日付"].dt.to_period("M"))
      .groupby("month", as_index=False)["金額"].sum()
)

print(df.columns)
print(monthly)
Python

ここでは、

2行目をヘッダーにする
空白列を最初から読み込まない
日付と金額を整える
月次集計をする

という流れを一気に書いています。

テンプレ2:空白列を落としつつ、特定列だけ型を指定して読む

import pandas as pd

df = pd.read_excel(
    "customer_report.xlsx",
    header=0,
    usecols=lambda x: x.strip() != '',
    dtype={
        "顧客ID": "string",
        "郵便番号": "string"
    }
)

print(df.columns)
print(df.dtypes)
Python

このテンプレートは、「帳票に紛れた空白列を落としつつ、ID系の列を文字列で読む」という、
かなり実務的なパターンです。


つまずきやすいポイントと注意点

列名が NaN の場合の扱い

ヘッダー行が完全に空欄だと、その列名は NaN になることがあります。
x.strip() を呼ぶ前に、x が文字列かどうかを確認した方が安全な場合もあります。

より堅牢に書くなら、こうです。

usecols=lambda x: isinstance(x, str) and x.strip() != ''
Python

これなら、「列名が NaN(float)」の列も安全に除外できます。

本当に必要な列まで落としていないか確認する

usecols=lambda x: x.strip() != '' は、「名前が空の列」を全部落とします。
もし「名前は空だけど、実は意味のある列」がある場合は、その列も消えてしまいます。

最初は一度 usecols なしで読み込んで df.columns を確認し、
「本当に空白列だけを落としていいか?」を目で見て判断してから、このフィルターを導入するのがおすすめです。


小さな練習問題

練習1:空白列を含む report.xlsx を usecols なし/ありで読み比べる

条件は次の通りです。

  1. df1 = pd.read_excel("report.xlsx", header=1)
  2. df2 = pd.read_excel("report.xlsx", header=1, usecols=lambda x: x.strip() != '')
  3. それぞれの df.columns を表示して、違いを確認する

「どの列が消えたか」を意識してみてください。

練習2:sales_report.xlsx で空白列を落とし、日付と金額を整えて月次集計する

条件は次の通りです。

  1. header を適切に指定する
  2. usecols=lambda x: x.strip() != '' を使う
  3. 日付を to_datetime、金額を to_numeric で整える
  4. 月次合計を計算して表示する

最後に

usecols=lambda x: x.strip() != '' は、
「Excelの“見た目調整用の空白列”を、最初から相手にしない」ための小さなフィルターです。

これを入口に一行足すだけで、

謎の Unnamed: n 列が消える
後の処理で余計な列を気にしなくてよくなる
DataFrame の構造がシンプルになる

という、地味だけど効き目の大きい効果が得られます。

あなたの手元のExcelで、「この空白列、正直いらないんだよな」と思うものがあったら、
一度この usecols=lambda x: x.strip() != '' を試してみてください。
データが、少しだけあなたの味方になります。

タイトルとURLをコピーしました