クリック3回でグラフ爆誕!CSV/Excelを即座に可視化するPython GUIスクリプト #12
Pythonでデータ解析や可視化を繰り返す中で、「毎回Plotlyのコードを手で書くのが面倒」と感じていました。そこで、ファイルを選ぶだけで瞬時にグラフ化できる便利なPythonスクリプトを作成しました。今回は、そのスクリプトの構成や使い方を共有します。
なぜこのツールを作ったのか?
データ分析やレポート作成のたびに毎回Plotlyでコードを書き直すのは非効率です。特に以下の作業がストレスでした。
CSVやExcelをいちいち読み込むコードを書く
X軸やY軸の設定を都度調整
グラフタイプを手動で変更
「ファイルを選ぶだけでサクッとグラフ化したい!」そんな欲望を叶えるために開発しました。
コンセプトとゴール
本ツールの目標は以下の通りです。
GUI(Tkinter)でファイルを直感的に選択
pandasでCSV/Excelを柔軟に読み込み
Plotlyで折れ線/散布図を瞬時に表示
キャッシュ機能で巨大ファイルも高速再読込
使ったライブラリと環境
Python:3.10以上
pandas:データフレーム操作
Tkinter:ファイル選択GUI
plotly:インタラクティブなグラフ描画
pickle:データキャッシュ
スクリプトの動作イメージ
スクリプトは次の手順で動作します。
ファイル選択ダイアログ(CSV/Excelを選択)
pandasでデータフレーム生成(自動キャッシュ保存)
Plotlyで複数軸のグラフを即座に表示(X/Y軸自由切替、折れ線/散布図切替可能)

コードのポイント解説(3つのポイント)
① キャッシュ機能
一度読み込んだファイルをpickleで保存
再読み込み時はキャッシュを選択可
② GUI操作(Tkinter)
「filedialog」でファイルを選ぶだけ
非エンジニアでも簡単操作
③ Plotlyで柔軟可視化
X軸、Y軸の変更がドロップダウンで可能
「折れ線」と「散布図」をワンクリックで切り替え
実際に使ってみた感想
このツールを使うようになり、データ分析の下準備が大幅に短縮されました。特にキャッシュ機能のおかげで、数十万行の巨大CSVファイルでも再読み込みが一瞬で終わります。
まとめ
手間がかかる作業はスクリプトで自動化することで、大幅な効率化につながります。本記事のスクリプトをベースに、皆さんも自分だけの自動化ツールを作ってみてはいかがでしょうか?
使ってみた感想や改善案など、お気軽にお寄せください!
作成スクリプト
#作成したスクリプト
import os
import pickle
import pandas as pd
from datetime import datetime
import tkinter as tk
from tkinter import filedialog, simpledialog, messagebox
import plotly.graph_objects as go
#データフレームの作成
# ▼ キャッシュファイルのパス
CACHE_PATH = "df_cache.pkl"
# ▼ Tk初期化(ウィンドウは表示しない)
root = tk.Tk()
root.withdraw()
# ▼ キャッシュを使うか確認(かつ元ファイル名表示)
use_cache = False
if os.path.exists(CACHE_PATH):
with open(CACHE_PATH, "rb") as f:
cache_obj = pickle.load(f)
cached_path = cache_obj.get("file_path", "(不明)")
cache_time = datetime.fromtimestamp(os.path.getmtime(CACHE_PATH))
use_cache = messagebox.askyesno(
title="キャッシュ確認",
message=(
f"前回のデータ({cache_time})があります。\n"
f"元ファイル: {cached_path}\n\nキャッシュから読み込みますか?"
)
)
if use_cache:
# キャッシュ読み込み
df = cache_obj["df"]
print("✅ キャッシュからDataFrameを読み込みました")
print(f"📂 元ファイル: {cache_obj.get('file_path', '(不明)')}")
print(f"📅 最終保存日時: {datetime.fromtimestamp(os.path.getmtime(CACHE_PATH))}")
else:
# ファイル選択して読み込み
file_path = filedialog.askopenfilename(
title="CSVまたはExcelファイルを選択してください",
filetypes=[("CSV files", "*.csv"), ("Excel files", "*.xlsx *.xls")]
)
if not file_path:
print("⛔ ファイル選択がキャンセルされました。")
exit()
# ファイル形式に応じて読み込み
if file_path.endswith(".csv"):
df = pd.read_csv(file_path)
elif file_path.endswith((".xlsx", ".xls")):
df = pd.read_excel(file_path)
else:
messagebox.showerror("エラー", "対応していないファイル形式です")
raise ValueError("対応していないファイル形式です")
# 辞書でキャッシュ保存
cache_obj = {
"df": df,
"file_path": file_path
}
with open(CACHE_PATH, "wb") as f:
pickle.dump(cache_obj, f)
print(f"📁 新規読み込み完了 → キャッシュ保存済: {CACHE_PATH}")
print(f"📝 元ファイル: {file_path}")
# ▼ カラム一覧取得
columns = df.columns.tolist()
x_init = columns[0] if len(columns) > 0 else None
y_candidates = [col for col in columns if col != x_init]
# ▼ Figure生成:Y列を全て表示
fig = go.Figure()
for y_col in y_candidates:
fig.add_trace(go.Scatter(
x=df[x_init],
y=df[y_col],
mode='lines', # 折れ線
# mode='markers' # 散布図
name=y_col,
line=dict(width=2)
))
# ▼ X軸切替のドロップダウン
x_buttons = []
for x_col in columns:
# すべてのY列について、Xを更新(Traceの数だけ繰り返し)
x_args = {"x": [df[x_col] for _ in y_candidates]}
layout_args = {"xaxis": {"title": x_col}}
x_buttons.append(dict(label=x_col, method="update", args=[x_args, layout_args]))
# ▼ Layout
fig.update_layout(
title="X軸切替 + 複数Y系列表示(凡例で制御可能)",
xaxis=dict(title=x_init, tickfont=dict(size=12)),
yaxis=dict(title="値", tickfont=dict(size=12)),
legend=dict(font=dict(size=12)),
margin=dict(l=40, r=40, t=60, b=40),
template="simple_white",
updatemenus=[
dict(
buttons=x_buttons,
direction="down",
x=0.1, y=1.2,
xanchor="left", yanchor="top",
showactive=True,
pad={"r": 10}
)
]
)
fig.show()
#指定データの可視化
# ▼ カラム一覧取得(自動)
columns = df.columns.tolist()
x_init = columns[0] if len(columns) > 0 else None
y_init = columns[1] if len(columns) > 1 else None
# ▼ Plotlyで折れ線グラフ(初期は x=0列, y=1列)
fig = go.Figure()
fig.add_trace(go.Scatter(
x=df[x_init],
y=df[y_init],
mode='lines', # 初期表示は折れ線グラフ
name=f"{x_init} vs {y_init}",
line=dict(width=2)
))
# ▼ X軸選択ドロップダウン
x_buttons = [
dict(label=col, method='update',
args=[{'x': [df[col]]},
{'xaxis': {'title': col}}])
for col in columns
]
# ▼ Y軸選択ドロップダウン
y_buttons = [
dict(label=col, method='update',
args=[{'y': [df[col]]},
{'yaxis': {'title': col}}])
for col in columns
]
# ▼ グラフタイプ切替のドロップダウン(折れ線 or 散布図)
graph_type_buttons = [
dict(label="折れ線", method="restyle", args=[{"mode": "lines"}]),
dict(label="散布図", method="restyle", args=[{"mode": "markers"}])
]
# ▼ レイアウト(X/Y軸のタイトルも初期化)
fig.update_layout(
title="X/Y軸切替 & グラフタイプ切替(折れ線 / 散布図)",
xaxis=dict(title=x_init, tickfont=dict(size=12)),
yaxis=dict(title=y_init, tickfont=dict(size=12)),
legend=dict(font=dict(size=12)),
margin=dict(l=40, r=40, t=60, b=40),
template="simple_white",
updatemenus=[
dict(
buttons=x_buttons,
direction="down",
x=0.1, y=1.2,
xanchor="left", yanchor="top",
showactive=True,
pad={"r": 10}
),
dict(
buttons=y_buttons,
direction="down",
x=0.4, y=1.2,
xanchor="left", yanchor="top",
showactive=True
),
dict(
buttons=graph_type_buttons,
direction="down",
x=0.7, y=1.2,
xanchor="left", yanchor="top",
showactive=True
)
]
)
# ▼ 軸フォーマット調整(必要な場合アンコメント)
# Y軸:小数1桁
# fig.update_yaxes(tickformat=".1f")
# Y軸:単位つき
# fig.update_yaxes(tickformat=",d", ticksuffix=" 秒")
# ▼ 軸範囲(必要に応じて有効化)
# fig.update_xaxes(range=[0, 100])
# fig.update_yaxes(range=[0, 500])
fig.show()本記事の内容が役に立った、または「いいね!」と思っていただけましたら、ぜひ100円の応援サポートをよろしくお願いします!
頂いたサポートは、次の便利ツールの開発や情報共有の励みになります。
応援やフィードバックをいただけると、とても嬉しいです!
ここから先は
¥ 100
よろしければ応援お願いします! いただいたチップはクリエイターとしての活動費に使わせていただきます!
