404 Not Found

404 Not Found


nginx

【Pandas】データの入出力(読み込み・書き出し)完全ガイド

実際のプロジェクトでは、データはコードの中に突然現れるわけではありません。CSVファイル、Excelスプレッドシート、データベース、APIエンドポイントなど、さまざまな場所から取得します。Pandasは20以上のIO関数を提供しており、1行のコードでさまざまな形式のデータを読み込み・保存できます。本章では、最もよく使われる4つの形式(CSV / Excel / JSON / SQL)と、エンコーディングや大容量ファイル処理の実践的なテクニックを解説します。

⚠️ 注意: 以下のコードはローカルのPython環境で実行してください。一部のサンプルではStringIOを使用してファイルの読み書きをシミュレートしています。

1. 本章で学ぶこと



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判断ツリー

100%
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で保持できます。

📖 まとめ


📝 練習問題

  1. 基礎(難易度 ⭐):StringIOでCSVファイルをシミュレートし、read_csvで読み込み(dtypeとusecolsを指定)、to_csvで保存(index=False)してください。
  2. 応用(難易度 ⭐⭐):2つのDataFrameを作成し、ExcelWriterを使用して同じExcelファイルの別々のシートに書き込んでください。その後、read_excelのsheet_name=Noneですべてのシートを読み戻してください。
  3. チャレンジ(難易度 ⭐⭐⭐):1000行のCSVをシミュレートし(NaN値と日付列を含む)、以下を完了してください:read_csv(na_values/parse_dates/dtypeを指定)→ 欠損値の補完 → 3形式で書き出し:to_csv/to_json/to_sql → read_jsonで読み戻して整合性を確認してください。

← 前へ:データの選択 · 次へ:欠損値の処理 →

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%