業務では Excel ファイルでデータをやり取りする機会が多いです。pandas は Excel ファイルの読み書きに対応していますが、内部で使うライブラリによって機能や挙動が異なります。ここでは openpyxl を使った Excel 連携を解説します。
必要なライブラリ
pandas 単体では Excel を扱えません。読み書きには追加のライブラリが必要です。
# インストール
# pip install openpyxl
import pandas as pd
# openpyxl がインストールされていれば自動的に使われる
df = pd.read_excel('data.xlsx')
Excel 関連のライブラリは複数あり、用途によって使い分けます。
| ライブラリ | 対応形式 | 用途 |
|---|---|---|
| openpyxl | .xlsx | 読み書き両対応、書式設定可 |
| xlrd | .xls | 古い形式の読み込み専用 |
| xlsxwriter | .xlsx | 書き込み専用、高機能 |
現在は openpyxl が最も汎用的で、pandas のデフォルトエンジンにもなっています。
基本的な読み込み
import pandas as pd
# 基本の読み込み
df = pd.read_excel('data.xlsx')
# シートを指定
df = pd.read_excel('data.xlsx', sheet_name='Sheet1')
# シート番号で指定(0始まり)
df = pd.read_excel('data.xlsx', sheet_name=0)
複数シートを一度に読み込むこともできます。
# 全シートを辞書で取得
all_sheets = pd.read_excel('data.xlsx', sheet_name=None)
print(all_sheets.keys())
# dict_keys(['Sheet1', 'Sheet2', 'Sheet3'])
# 特定の複数シートを読み込み
sheets = pd.read_excel('data.xlsx', sheet_name=['Sheet1', 'Sheet3'])
読み込みオプション
実務の Excel ファイルは、1 行目がヘッダーでないことも多いです。さまざまなオプションで対応できます。
# ヘッダー行を指定(0始まり)
df = pd.read_excel('data.xlsx', header=2) # 3行目がヘッダー
# ヘッダーなし
df = pd.read_excel('data.xlsx', header=None)
# 読み込む行をスキップ
df = pd.read_excel('data.xlsx', skiprows=5) # 最初の5行をスキップ
# 特定の行をスキップ(リストで指定)
df = pd.read_excel('data.xlsx', skiprows=[0, 2, 4])
# 読み込む行数を制限
df = pd.read_excel('data.xlsx', nrows=100)
列の指定も柔軟にできます。
# 特定の列のみ読み込み
df = pd.read_excel('data.xlsx', usecols='A:C') # A〜C列
df = pd.read_excel('data.xlsx', usecols='A,C,E') # A, C, E列
df = pd.read_excel('data.xlsx', usecols=[0, 2, 4]) # インデックス指定
# 列名で指定
df = pd.read_excel('data.xlsx', usecols=['名前', '金額'])
データ型の指定
Excel から読み込むと、意図しない型変換が起きることがあります。dtype パラメータで明示的に指定できます。
# 型を指定して読み込み
df = pd.read_excel('data.xlsx', dtype={
'社員番号': str, # 先頭ゼロを保持
'金額': float,
'フラグ': bool
})
日付列は自動認識されますが、うまくいかない場合は parse_dates を使います。
# 日付列を指定
df = pd.read_excel('data.xlsx', parse_dates=['登録日', '更新日'])
# 複数列を結合して日付に
df = pd.read_excel('data.xlsx', parse_dates={'日時': ['日付', '時刻']})
便利だが、文字列の数字が数値になったり、先頭ゼロが消えたりする
意図した型で読み込める。特に ID やコードは str 指定が安全
基本的な書き込み
import pandas as pd
df = pd.DataFrame({
'名前': ['田中', '佐藤', '鈴木'],
'点数': [85, 92, 78]
})
# 基本の書き込み
df.to_excel('output.xlsx', index=False)
# シート名を指定
df.to_excel('output.xlsx', sheet_name='成績表', index=False)
index=False を指定しないと、DataFrame のインデックスが A 列に出力されます。多くの場合は不要なので False にします。
複数シートへの書き込み
複数の DataFrame を別々のシートに書き込むには ExcelWriter を使います。
import pandas as pd
df1 = pd.DataFrame({'A': [1, 2, 3]})
df2 = pd.DataFrame({'B': [4, 5, 6]})
with pd.ExcelWriter('output.xlsx', engine='openpyxl') as writer:
df1.to_excel(writer, sheet_name='データ1', index=False)
df2.to_excel(writer, sheet_name='データ2', index=False)
既存ファイルにシートを追加する場合は mode='a' を指定します。
# 既存ファイルにシートを追加
with pd.ExcelWriter('output.xlsx', engine='openpyxl', mode='a') as writer:
df3.to_excel(writer, sheet_name='データ3', index=False)
書式設定との連携
pandas の to_excel は書式設定に限界があります。細かい書式が必要な場合は、openpyxl を直接使います。
import pandas as pd
from openpyxl import load_workbook
from openpyxl.styles import Font, Alignment, PatternFill
# まず pandas で基本データを書き込み
df = pd.DataFrame({
'商品': ['りんご', 'みかん', 'バナナ'],
'価格': [150, 100, 200]
})
df.to_excel('output.xlsx', index=False)
# openpyxl で書式を追加
wb = load_workbook('output.xlsx')
ws = wb.active
# ヘッダーに書式を設定
for cell in ws[1]:
cell.font = Font(bold=True, color='FFFFFF')
cell.fill = PatternFill('solid', fgColor='4472C4')
cell.alignment = Alignment(horizontal='center')
# 列幅を調整
ws.column_dimensions['A'].width = 15
ws.column_dimensions['B'].width = 10
wb.save('output.xlsx')
テンプレートへの書き込み
業務では、書式設定済みのテンプレートにデータを流し込むことが多いです。
from openpyxl import load_workbook
import pandas as pd
# テンプレートを開く
wb = load_workbook('template.xlsx')
ws = wb.active
# DataFrame を準備
df = pd.DataFrame({
'名前': ['田中', '佐藤'],
'金額': [10000, 20000]
})
# 特定のセルからデータを書き込み
start_row = 5 # 5行目から
for i, row in df.iterrows():
ws.cell(row=start_row + i, column=2, value=row['名前'])
ws.cell(row=start_row + i, column=3, value=row['金額'])
wb.save('output.xlsx')
シンプルなデータ出力に最適。書式は最低限のみ。
細かい書式設定、テンプレート活用、セル結合などが必要な場合に使う。
パフォーマンスの注意点
Excel ファイルの読み書きは CSV に比べて遅いです。大量データを扱う場合は注意が必要です。
import pandas as pd
import time
# 大きなデータ
df = pd.DataFrame({'A': range(100000), 'B': range(100000)})
# Excel書き込み
start = time.time()
df.to_excel('large.xlsx', index=False)
print(f"Excel: {time.time() - start:.2f}秒")
# CSV書き込み
start = time.time()
df.to_csv('large.csv', index=False)
print(f"CSV: {time.time() - start:.2f}秒")
# Excel: 5.23秒
# CSV: 0.15秒
大量データは CSV で処理し、最終的な出力のみ Excel にするのが効率的です。