【Pandas】データの入出力(読み込み・書き出し)完全ガイド
実際のプロジェクトでは、データはコードの中に突然現れるわけではありません。CSVファイル、Excelスプレッドシート、データベース、APIエンドポイントなど、さまざまな場所から取得します。Pandasは20以上のIO関数を提供しており、1行のコードでさまざまな形式のデータを読み込み・保存できます。本章では、最もよく使われる4つの形式(CSV / Excel / JSON / SQL)と、エンコーディングや大容量ファイル処理の実践的なテクニックを解説します。
⚠️ 注意: 以下のコードはローカルのPython環境で実行してください。一部のサンプルではStringIOを使用してファイルの読み書きをシミュレートしています。
1. 本章で学ぶこと
- ❶ read_csv / to_csv の詳細な使い方
- ❷ read_excel / to_excel の複数シート処理
- ❸ read_json / to_json の形式処理
- ❹ read_sql / to_sql のデータベース連携
- ❺ エンコーディングの問題と大容量ファイルの戦略(chunksize)
2. ボブのエンコーディング悪夢
(1) 問題:CSVを開くと文字化けする
ボブが顧客データのCSVを受け取り、デフォルトのパラメータで読み込んだところ、中国語の文字がすべて文字化けしてしまいました:
PYTHON
import pandas as pd
# これは失敗するか、文字化けが発生します
# df = pd.read_csv('customers.csv') # UnicodeDecodeError!
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
原因:ファイルはGBKエンコーディングですが、PandasはデフォルトでUTF-8として読み込むためです。
(2) 解決策:encodingを指定する
▶ サンプル:エンコーディング処理(難易度 ⭐)
PYTHON
import pandas as pd
from io import StringIO
# GBKエンコーディングのCSVをシミュレート
csv_gbk = "name,age,city\nAlice,28,Beijing\nBob,34,Shanghai"
# 実際のシナリオ:pd.read_csv('file.csv', encoding='gbk')
# UTF-8(デフォルト)— 最新のファイルのほとんどに対応
csv_utf8 = "name,age,city\nAlice,28,New York\nBob,34,London"
df = pd.read_csv(StringIO(csv_utf8))
print(df)
# name age city
# 0 Alice 28 New York
# 1 Bob 34 London
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
(3) 効果:IO関数なら1行で完了
| シナリオ | 1行コード |
|---|---|
| CSVの読み込み | pd.read_csv('data.csv') |
| CSVの書き出し | df.to_csv('out.csv', index=False) |
| Excelの読み込み | pd.read_excel('data.xlsx') |
| SQLの読み込み | pd.read_sql('SELECT * FROM t', conn) |
3. CSVの読み込みと書き出し
(1) read_csvのよく使うパラメータ
▶ サンプル
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
:read_csvパラメータの詳細(難易度 ⭐⭐)
PYTHON
import pandas as pd
from io import StringIO
csv_data = """product_id,product_name,price,stock,category
P001,Laptop,999.99,50,Electronics
P002,Phone,699.99,120,Electronics
P003,Tablet,349.99,80,Electronics
P004,Monitor,449.99,35,Electronics
P005,Keyboard,79.99,200,Accessories"""
# 基本的な読み込み
df = pd.read_csv(StringIO(csv_data))
print(df.columns) # 1行目から自動検出
# 主要なパラメータ(シミュレートデータで説明)
# pd.read_csv('file.csv',
# encoding='utf-8', # ファイルのエンコーディング
# sep=',', # 区切り文字(デフォルトはカンマ)
# header=0, # 列名がある行番号
# index_col='product_id', # インデックスとして使用する列
# usecols=['product_name', 'price'], # これらの列のみ読み込む
# dtype={'price': float, 'stock': int}, # 型を強制指定
# na_values=['N/A', 'NULL'], # これらをNaNとして扱う
# parse_dates=['order_date'], # datetimeとして解析
# nrows=1000, # 先頭N行のみ読み込む
# chunksize=5000 # チャンク単位で繰り返し処理
# )
# 特定の列のみ選択(メモリ節約)
df_selected = pd.read_csv(StringIO(csv_data), usecols=['product_name', 'price'])
print(df_selected)
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
(2) to_csvで保存する
▶ サンプル
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
:to_csvでの保存(難易度 ⭐)
PYTHON
import pandas as pd
from io import StringIO
df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie'],
'age': [28, 34, 25],
'city': ['New York', 'London', 'Tokyo']
})
# CSV文字列に保存(ファイル出力をシミュレート)
output = StringIO()
df.to_csv(output, index=False) # index=False — 行番号を保存しない
print(output.getvalue())
# name,age,city
# Alice,28,New York
# Bob,34,London
# Charlie,25,Tokyo
# 実際のファイル:df.to_csv('output.csv', index=False, encoding='utf-8')
# 既存ファイルに追記
# df.to_csv('output.csv', mode='a', header=False, index=False)
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
4. Excelの読み込みと書き出し
(1) read_excelで複数シートを扱う
▶ サンプル
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
:Excel複数シートの読み込み(難易度 ⭐⭐)
PYTHON
import pandas as pd
from io import BytesIO
# メモリ内に複数シートのExcelファイルを作成
buffer = BytesIO()
df1 = pd.DataFrame({'name': ['Alice', 'Bob'], 'score': [85, 92]})
df2 = pd.DataFrame({'product': ['Laptop', 'Phone'], 'price': [999, 699]})
with pd.ExcelWriter(buffer) as writer:
df1.to_excel(writer, sheet_name='Students', index=False)
df2.to_excel(writer, sheet_name='Products', index=False)
buffer.seek(0)
# 特定のシートを読み込む
students = pd.read_excel(buffer, sheet_name='Students')
print(students)
# すべてのシートを辞書として読み込む
buffer.seek(0)
all_sheets = pd.read_excel(buffer, sheet_name=None) # DataFrameの辞書
print(all_sheets.keys()) # dict_keys(['Students', 'Products'])
# シートの位置で読み込む
buffer.seek(0)
second_sheet = pd.read_excel(buffer, sheet_name=1) # 0始まりのインデックス
print(second_sheet)
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
💡 ヒント: read_excelには追加のエンジンが必要です:
.xlsxにはpip install openpyxl、.xlsにはpip install xlrdをインストールしてください。Pandas 2.xではデフォルトでopenpyxlを使用します。
(2) to_excelで保存する
▶ サンプル
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
:Excelの保存と書式設定(難易度 ⭐)
PYTHON
import pandas as pd
from io import BytesIO
df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie'],
'salary': [75000, 92000, 68000]
})
# 単一シートに保存
buffer = BytesIO()
df.to_excel(buffer, sheet_name='Employees', index=False)
# 複数のDataFrameを別々のシートに保存
buffer2 = BytesIO()
with pd.ExcelWriter(buffer2) as writer:
df.to_excel(writer, sheet_name='Employees', index=False)
df.describe().to_excel(writer, sheet_name='Statistics')
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
5. JSONの読み込みと書き出し
(1) JSONの形式の種類
▶ サンプル
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
:JSONの複数形式での読み書き(難易度 ⭐⭐)
PYTHON
import pandas as pd
from io import StringIO
# orient='records'(APIで最も一般的)
json_records = '[{"name":"Alice","age":28},{"name":"Bob","age":34}]'
df = pd.read_json(StringIO(json_records), orient='records')
print(df)
# name age
# 0 Alice 28
# 1 Bob 34
# orient='columns'(列指向)
json_cols = '{"name":{"0":"Alice","1":"Bob"},"age":{"0":28,"1":34}}'
df2 = pd.read_json(StringIO(json_cols), orient='columns')
print(df2)
# orient='index'(行指向)
json_idx = '{"0":{"name":"Alice","age":28},"1":{"name":"Bob","age":34}}'
df3 = pd.read_json(StringIO(json_idx), orient='index')
print(df3)
# JSONに書き出す
output = df.to_json(orient='records', indent=2)
print(output)
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
(2) JSONのorient比較
| orient | 構造 | 用途 |
|---|---|---|
| records | [{col:val}, ...] |
APIレスポンス(最も一般的) |
| columns | {col:{idx:val}} |
列指向 |
| index | {idx:{col:val}} |
行指向 |
| split | {index:[], columns:[], data:[[]]} |
完全な分解 |
| values | [[v1,v2], ...] |
ラベルなしの生データ |
6. SQLの読み込みと書き出し
(1) read_sqlでデータベースにクエリする
▶ サンプル
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
:SQLデータベースとの連携(難易度 ⭐⭐)
PYTHON
import pandas as pd
import sqlite3
from io import StringIO
# メモリ内のSQLiteデータベースを作成(デモ用)
conn = sqlite3.connect(':memory:')
# データをSQLに書き込む
df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie'],
'department': ['Sales', 'Engineering', 'Marketing'],
'salary': [75000, 92000, 68000]
})
df.to_sql('employees', conn, if_exists='replace', index=False)
# テーブル全体を読み込む
df_read = pd.read_sql('SELECT * FROM employees', conn)
print(df_read)
# SQLクエリで読み込む
high_salary = pd.read_sql(
'SELECT name, salary FROM employees WHERE salary > 70000',
conn
)
print(high_salary)
# name salary
# 0 Alice 75000
# 1 Bob 92000
# パラメータ付きで読み込む(SQLインジェクション対策)
dept = 'Engineering'
result = pd.read_sql(
'SELECT * FROM employees WHERE department = ?',
conn,
params=[dept]
)
print(result)
conn.close()
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
💡 ヒント: read_sqlはSQLite / PostgreSQL / MySQL / SQL Serverなど、Python DB-API互換のすべてのデータベースをサポートしています。対応するドライバのインストールが必要です:
pip install psycopg2(PostgreSQL)、pip install pymysql(MySQL)。
7. 大容量ファイルの戦略
(1) chunksizeでチャンク単位に読み込む
▶ サンプル
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
:chunksizeによる大容量ファイル処理(難易度 ⭐⭐)
PYTHON
import pandas as pd
from io import StringIO
# 大容量CSVをシミュレート
csv_large = "id,value\n" + "\n".join([f"{i},{i*10}" for i in range(100)])
# 30行ずつチャンクで読み込む
chunks = pd.read_csv(StringIO(csv_large), chunksize=30)
total_sum = 0
total_count = 0
for chunk in chunks:
total_sum += chunk['value'].sum()
total_count += len(chunk)
print(f"総行数:{total_count}")
print(f"値の合計:{total_sum}")
# 別の方法:各チャンクを処理して保存
# for i, chunk in enumerate(chunks):
# chunk.to_csv(f'chunk_{i}.csv', index=False)
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
(2) 必要な列だけ読み込んでメモリを節約する
▶ サンプル
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
:列の選択的読み込み(難易度 ⭐)
PYTHON
import pandas as pd
from io import StringIO
csv_data = """id,name,age,salary,department,address,phone
1,Alice,28,75000,Sales,123 Main St,555-0100
2,Bob,34,92000,Engineering,456 Oak Ave,555-0200
3,Charlie,25,68000,Marketing,789 Pine Rd,555-0300"""
# 必要な列だけ読み込む
df = pd.read_csv(StringIO(csv_data), usecols=['name', 'salary', 'department'])
print(df)
# 位置指定も可能:usecols=[1, 3, 4]
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
(3) IO形式の比較
| 形式 | 読み込み | 書き出し | 速度 | サイズ | 最適な用途 |
|---|---|---|---|---|---|
| CSV | read_csv | to_csv | 中 | 中 | 汎用的なデータ交換 |
| Excel | read_excel | to_excel | 遅い | 大 | ビジネスレポート |
| JSON | read_json | to_json | 遅い | 大 | API / Web |
| SQL | read_sql | to_sql | 遅い | — | データベース |
| Parquet | read_parquet | to_parquet | 高速 | 小 | 大容量データの保存 |
| HDF5 | read_hdf | to_hdf | 高速 | 小 | 科学データ |
| Feather | read_feather | to_feather | 最速 | 小 | 一時保存 |
8. 総合サンプル:読み込み → クリーニング → 複数形式で書き出し
(5) ▶ IO判断ツリー
graph TB
A[データソース] --> B{ファイルサイズは?}
B -->|小| C[CSV / Excel / JSON]
B -->|中| D[CSV + chunksize]
B -->|大| E[Parquet / Feather]
A --> F{データベースが必要?}
F -->|はい| G[read_sql / to_sql]
F -->|いいえ| H{APIが必要?}
H -->|はい| I[read_json]
H -->|いいえ| J[read_csv]
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
▶ サンプル
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
:完全なIOパイプライン(難易度 ⭐⭐⭐)
PYTHON
import pandas as pd
import sqlite3
from io import StringIO, BytesIO
# ============================================
# 総合サンプル:完全なIOパイプライン
# CSV読み込み → クリーニング → CSV/Excel/JSON/SQLで書き出し
# ============================================
# 1. CSVから読み込む
csv_data = """name,age,salary,department,hire_date
Alice,28,75000,Sales,2022-03-15
Bob,34,92000,Engineering,2019-08-01
Charlie,25,NaN,Marketing,2023-01-10
Carol,30,88000,Sales,2020-06-20
David,45,105000,Management,2015-11-01"""
df = pd.read_csv(StringIO(csv_data), na_values=['NaN'])
# 2. データをクリーニングする
df['salary'] = df['salary'].fillna(df['salary'].median())
df['hire_date'] = pd.to_datetime(df['hire_date'])
print("=== クリーニング済みデータ ===")
print(df)
# 3. CSVに書き出す
csv_out = StringIO()
df.to_csv(csv_out, index=False)
print(f"\n✅ CSV書き出し:{len(csv_out.getvalue())} 文字")
# 4. Excelに書き出す
excel_out = BytesIO()
with pd.ExcelWriter(excel_out) as writer:
df.to_excel(writer, sheet_name='Employees', index=False)
df.describe().to_excel(writer, sheet_name='Stats')
print(f"✅ Excel書き出し:{len(excel_out.getvalue())} バイト、2シート")
# 5. JSONに書き出す
json_out = df.to_json(orient='records', indent=2, date_format='iso')
print(f"✅ JSON書き出し:{len(json_out)} 文字")
# 6. SQLに書き出す
conn = sqlite3.connect(':memory:')
df.to_sql('employees', conn, if_exists='replace', index=False)
df_from_sql = pd.read_sql('SELECT * FROM employees', conn)
print(f"✅ SQLラウンドトリップ:{len(df_from_sql)} 行")
conn.close()
TEXT
> 出力: ローカルのPython環境(pandas 2.x)で実行してください。Pistonサーバーにはpandasがプリインストールされていません。ローカルにインストール(`pip install pandas`)してから実行してください。実際の値はpandasのバージョンによって若干異なる場合があります。
❓ よくある質問
Q CSVのエンコーディングエラーにはどう対処すればよいですか?
A よく使われるエンコーディングには、UTF-8(最新のデフォルト)、GBK/GB2312(中国語Windows)、ISO-8859-1(西ヨーロッパ)があります。まず
encoding='utf-8'を試してください。失敗した場合はencoding='gbk'を使用します。万能なフォールバックはencoding='latin1'です(エラーは出ませんが、文字化けする可能性があります)。また、chardetライブラリでエンコーディングを自動検出することもできます。Q read_excelには追加のライブラリが必要ですか?
A はい。
.xlsxファイルにはpip install openpyxl、.xlsファイルにはpip install xlrdが必要です。Pandas 2.xではデフォルトでopenpyxlエンジンを使用します。「Missing optional dependency」エラーが表示された場合は、対応するライブラリをインストールしてください。Q JSONの形式は何種類ありますか?
A orientモードは5種類あります。records(APIで最も一般的)、columns(列指向)、index(行指向)、split(完全な分解)、values(生データ)です。APIとの連携にはrecordsを、Pandas内部の保存にはcolumnsまたはsplitを使用してください。
Q chunksizeの使い方を教えてください。
A
pd.read_csv(path, chunksize=N)はTextFileReaderオブジェクトを返します。繰り返し処理のたびにN行のDataFrameが取得されます。利用可能なメモリを超えるファイルに最適で、チャンクごとに処理・集計・保存できます。注意:chunksizeモードはランダムアクセスに対応しておらず、順次読み込みのみです。Q 特定の列だけを読み込むにはどうすればよいですか?
A
usecolsパラメータを使用します:pd.read_csv(path, usecols=['col1', 'col3'])で列名を指定、またはusecols=[0, 2, 4]で位置を指定します。必要な列だけを読み込むことで、メモリ使用量を大幅に削減できます。特に列数が多いテーブル(100列以上あるが5列しか必要ない場合)に効果的です。Q ParquetとCSVの違いは何ですか?
A Parquetは列指向の保存形式で、CSVより5〜50倍高速に読み込め、ファイルサイズも50〜80%小さくなります(内蔵の圧縮機能による)。ただし、Parquetはプレーンテキストではないため(
pip install pyarrowが必要)、人が直接確認するのには向きません。推奨:生データの交換にはCSV、処理済みデータの保存にはParquetを使用してください。Q to_csvのindex=Falseとはどういう意味ですか?
A デフォルトでは、to_csvはDataFrameのインデックスを最初の列として書き出します。多くの場合、デフォルトのRangeIndex(0,1,2,...)を保存する必要はないため、
index=Falseで省略します。インデックスに意味のあるラベル(日付など)が含まれている場合は、index=Trueで保持できます。📖 まとめ
- read_csvは最もよく使われるIO関数です。主要なパラメータ:encoding / sep / usecols / dtype / parse_dates
- to_csvで保存する際は、index=Falseを使用して意味のない行番号の書き出しを避けましょう
- Excelの読み書きにはopenpyxlが必要で、複数シートの操作に対応しています(sheet_nameパラメータを使用)
- JSONには5つのorientモードがあり、APIとの連携にはrecordsを使用します
- SQLの読み書きはDB-API接続を通じて行い、パラメータ付きクエリでインジェクションを防止できます
- 大容量ファイルには、chunksizeによるチャンク読み込みとusecolsによる列の選択的読み込みを組み合わせましょう
- Parquet/HDF5/FeatherはCSVより5〜50倍高速で、大容量データの保存に最適です
📝 練習問題
- 基礎(難易度 ⭐):StringIOでCSVファイルをシミュレートし、read_csvで読み込み(dtypeとusecolsを指定)、to_csvで保存(index=False)してください。
- 応用(難易度 ⭐⭐):2つのDataFrameを作成し、ExcelWriterを使用して同じExcelファイルの別々のシートに書き込んでください。その後、read_excelのsheet_name=Noneですべてのシートを読み戻してください。
- チャレンジ(難易度 ⭐⭐⭐):1000行のCSVをシミュレートし(NaN値と日付列を含む)、以下を完了してください:read_csv(na_values/parse_dates/dtypeを指定)→ 欠損値の補完 → 3形式で書き出し:to_csv/to_json/to_sql → read_jsonで読み戻して整合性を確認してください。



