pandas.DataFrame を受け取り、同じデータを CSV / JSON / HTML にまとめて出力する汎用関数を作ります。
使い勝手の良さ(出力フォルダ生成、タイムスタンプ、圧縮、エンコーディング、HTML の簡易スタイリング、ロギング連携など)に配慮した実装を下に置きます。コピーしてすぐ使えます。
完成コード(そのまま使える)
import os
import json
from datetime import datetime
from pathlib import Path
import logging
import pandas as pd
# --- 簡単なロガー設定(必要ならプロジェクトの logging に差し替えてください) ---
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
def _safe_basename(name: str) -> str:
"""ファイル名に使えるように簡易サニタイズ(空白→_、危険文字削除)"""
keep = "-_.() abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
cleaned = "".join(c if c in keep else "_" for c in name)
return "_".join(cleaned.split())
def save_dataframe_outputs(
df: pd.DataFrame,
basename: str = "report",
outdir: str = "output",
to_csv: bool = True,
to_json: bool = True,
to_html: bool = True,
timestamp: bool = True,
date_format: str | None = None, # pandas.to_csv / to_json date_format parameter if needed
index: bool = False,
json_orient: str = "records", # "records","split","index","columns","values"
compress: bool = False,
compress_format: str = "gzip", # if compress True, e.g. 'gzip' or 'bz2' (pandas supports)
encoding: str = "utf-8",
html_table_class: str = "table table-striped table-bordered",
html_title: str | None = None,
pretty_json: bool = True
) -> dict:
"""
DataFrame を CSV / JSON / HTML に同時出力するユーティリティ。
Parameters
----------
df : pd.DataFrame
出力したい DataFrame
basename : str
出力ファイルのベース名(例: 'sales' -> sales.csv / sales.json / sales.html)
outdir : str
出力先フォルダ(存在しなければ作成される)
to_csv, to_json, to_html : bool
それぞれの形式を出力するか
timestamp : bool
True のときファイル名にタイムスタンプを付ける(例: report_20251105_172000.csv)
date_format : str or None
日付書式(必要に応じて pandas の to_csv/to_json に渡す)
index : bool
CSV/HTML に index を含めるか
json_orient : str
pandas.DataFrame.to_json の orient
compress : bool
圧縮して保存(CSV/JSONのみ対応)。pandas の to_csv/to_json の compression パラメータを使う。
compress_format : str
'gzip' や 'bz2' など。pandas がサポートするものを指定。
encoding : str
ファイルのエンコーディング
html_table_class : str
HTML 出力の table に付与するクラス(Bootstrap 風)
html_title : str or None
HTML にタイトルを付ける
pretty_json : bool
True のとき JSON を人間向けにインデント付きで書く(pandas.to_json ではなく json.dump を利用)
Returns
-------
dict
出力したファイルパスの辞書(存在しない出力は None)
"""
# 準備
outdir_path = Path(outdir)
outdir_path.mkdir(parents=True, exist_ok=True)
safe_name = _safe_basename(basename)
ts = datetime.now().strftime("%Y%m%d_%H%M%S") if timestamp else ""
base = f"{safe_name}_{ts}" if timestamp else safe_name
results = {"csv": None, "json": None, "html": None}
# --- CSV ---
if to_csv:
csv_name = f"{base}.csv"
if compress:
csv_name += f".{compress_format}"
compression_arg = compress_format
else:
compression_arg = None
csv_path = outdir_path / csv_name
logging.info(f"Writing CSV -> {csv_path}")
# pandas to_csv supports compression argument
df.to_csv(csv_path, index=index, encoding=encoding, date_format=date_format, compression=compression_arg)
results["csv"] = str(csv_path.resolve())
# --- JSON ---
if to_json:
json_name = f"{base}.json"
if compress:
json_name += f".{compress_format}"
compression_arg = compress_format
else:
compression_arg = None
json_path = outdir_path / json_name
logging.info(f"Writing JSON -> {json_path}")
# pretty_json が True のときは pandas 的に一旦 dict/list にして json.dump を使う(ensure_ascii=False に注意)
data_obj = None
if pretty_json:
# orient によって DataFrame からの変換方法を変える
if json_orient == "records":
data_obj = df.to_dict(orient="records")
else:
# それ以外は pandas にまかせて文字列を取得し、パースする
# ただし pandas.to_json は ensure_ascii=True なので、ここでは pandas のUTF-8対応が必要な場合に注意
# 簡単化のため、使用者が records を推奨
data_obj = json.loads(df.to_json(orient=json_orient, date_format="iso"))
# 書き込み(圧縮or通常)
if compression_arg:
# pandas の内部 compression を使えばよいが、pretty_json の場合ここでは gzip 例を実装
if compression_arg == "gzip":
import gzip
with gzip.open(json_path, "wt", encoding=encoding) as f:
json.dump(data_obj, f, ensure_ascii=False, indent=2)
else:
# 簡易的に非 gzip 圧縮は pandas に任せる(または拡張可)
with open(json_path, "w", encoding=encoding) as f:
json.dump(data_obj, f, ensure_ascii=False, indent=2)
else:
with open(json_path, "w", encoding=encoding) as f:
json.dump(data_obj, f, ensure_ascii=False, indent=2)
else:
# pretty_json False -> pandas に任せる(高速)
df.to_json(json_path, orient=json_orient, force_ascii=not (encoding.lower().startswith("utf")), date_format=date_format, compression=compression_arg)
results["json"] = str(json_path.resolve())
# --- HTML ---
if to_html:
html_name = f"{base}.html"
html_path = outdir_path / html_name
logging.info(f"Writing HTML -> {html_path}")
# DataFrame.to_html でテーブル本体を作る
table_html = df.to_html(index=index, classes=html_table_class, justify="left", border=0, escape=False)
# 簡易 HTML テンプレート(Bootstrap CSS を使いたければリンクを追加)
title = html_title or safe_name
html_doc = f"""<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>{title}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Optional: include Bootstrap CDN for nicer table styles -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css">
<style>
body {{ padding: 1rem; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Noto Sans JP', sans-serif; }}
table {{ width: auto; }}
</style>
</head>
<body>
<h2>{title}</h2>
{table_html}
</body>
</html>"""
html_path.write_text(html_doc, encoding=encoding)
results["html"] = str(html_path.resolve())
logging.info("Export complete.")
return results
Python使い方(例)
import pandas as pd
# サンプル DataFrame を作る
df = pd.DataFrame({
"名前": ["Alice", "Bob", "Charlie"],
"年齢": [25, 31, 29],
"入社日": pd.to_datetime(["2020-01-15", "2019-07-01", "2021-09-10"])
})
# ファイルを出力する(output/report_YYYYMMDD_HHMMSS.csv など)
results = save_dataframe_outputs(
df,
basename="employee_report",
outdir="output/reports",
to_csv=True,
to_json=True,
to_html=True,
timestamp=True,
index=False,
json_orient="records",
compress=False,
html_title="社員一覧"
)
print("Saved files:")
print(results)
Python実行すると output/reports/employee_report_YYYYMMDD_HHMMSS.csv / .json / .html が生成されます。戻り値 results はそれらの絶対パスを持つ辞書です。
補足・設計メモ
- UTF-8 対応:
encoding="utf-8"にしているので日本語も安心(Excelで開くときは BOM の必要や Shift-JIS 変換を検討してください)。 - JSON のフォーマット:
json_orient="records"(リストの辞書)を推奨。API に渡すときや人間が読むときに扱いやすいです。 - 圧縮:
compress=Trueにすると.csv.gz/.json.gzのように保存する実装が可能。上のコードは gzip を例にしていますが、さらに拡張可能です。 - HTML の見た目:Bootstrap CDN を使う簡易テンプレートを入れてあります。社内レポートや共有ファイルとしてそのまま使えます。
- ログ:
loggingでどのファイルに書き出したかを出力します。プロジェクトではlogging.getLogger(__name__)を使うと良いです。 - 拡張案:
pandas.ExcelWriterを使って Excel(.xlsx)同時出力を追加- ファイルのローテーションや古い出力の自動削除
- DataFrame を複数シートで Excel 出力(レポート生成)


