財務データの可視化とインタラクティブなダッシュボード構築 - Day 5
これまでに整備した財務データを可視化し、インタラクティブなダッシュボードを構築していきます。StreamlitとPlotlyを使って、誰でも簡単に財務分析ができる環境を作ります。
メインの処理フロー
データの流れ
BigQueryからの財務データ取得(月次収益・経費データ)
Pandasデータフレームへの変換と加工(利益・利益率の計算)
部門別・月次での集計処理
画面構成の生成(StreamlitとPlotly)
ダッシュボードタイトル表示
部門別メトリクス表示(総収益・総利益・利益率)
トレンドチャート生成(Plotlyによる可視化)
部門間相関ヒートマップ生成
詳細データテーブル(オプション表示)
Streamlitの特徴
Pythonスクリプトを直接Webアプリケーション化できるフレームワークです。コードの実行順序がそのままUI要素の配置順序になり、直感的な開発が可能です。
環境準備
pip install streamlit plotly pandas google-cloud-bigquery
プログラム一式
import streamlit as st
import plotly.express as px
import plotly.graph_objects as go
from google.cloud import bigquery
from google.oauth2 import service_account
import pandas as pd
from datetime import datetime, timedelta
# BigQuery設定
credentials = service_account.Credentials.from_service_account_file('your-key.json')
client = bigquery.Client(credentials=credentials, project='taki-sample001-202402')
def load_data():
"""財務データの読み込み"""
query = """
WITH monthly_summary AS (
SELECT
DATE_TRUNC(accounting_date, MONTH) as month,
department_name,
SUM(CASE
WHEN credit_account LIKE '5%' THEN amount
WHEN debit_account LIKE '5%' THEN -amount
ELSE 0
END) as revenue,
SUM(CASE
WHEN debit_account LIKE '6%' THEN -amount
WHEN credit_account LIKE '6%' THEN amount
ELSE 0
END) as expenses
FROM `accounting.journal_entries`
GROUP BY 1, 2
)
SELECT *,
revenue + expenses as profit,
CASE WHEN revenue != 0
THEN ROUND((revenue + expenses) / revenue * 100, 2)
ELSE 0
END as profit_margin
FROM monthly_summary
ORDER BY month, department_name
"""
return client.query(query).to_dataframe()
def create_department_metrics():
"""部門別メトリクスの表示"""
st.subheader("部門別業績サマリー")
# 部門選択
selected_dept = st.selectbox(
"部門を選択してください",
df['department_name'].unique()
)
# 選択部門のデータ
dept_data = df[df['department_name'] == selected_dept].copy()
# メトリクス表示
col1, col2, col3 = st.columns(3)
with col1:
total_revenue = dept_data['revenue'].sum()
st.metric("総収益", f"¥{total_revenue:,.0f}")
with col2:
total_profit = dept_data['profit'].sum()
st.metric("総利益", f"¥{total_profit:,.0f}")
with col3:
avg_margin = dept_data['profit_margin'].mean()
st.metric("平均利益率", f"{avg_margin:.1f}%")
def create_trend_chart():
"""トレンドチャートの作成"""
st.subheader("月次推移")
# グラフ種類の選択
metric = st.radio(
"表示する指標を選択してください",
["revenue", "profit", "profit_margin"],
format_func=lambda x: {
"revenue": "収益",
"profit": "利益",
"profit_margin": "利益率"
}[x]
)
# Plotlyでグラフ作成
fig = px.line(
df,
x='month',
y=metric,
color='department_name',
title="月次推移分析"
)
fig.update_layout(
xaxis_title="月",
yaxis_title="金額(円)" if metric != "profit_margin" else "利益率(%)",
legend_title="部門"
)
st.plotly_chart(fig, use_container_width=True)
def create_heatmap():
"""部門間相関ヒートマップの作成"""
st.subheader("部門間相関分析")
# 部門別の月次データをピボット
pivot_df = df.pivot(
index='month',
columns='department_name',
values='profit'
)
# 相関係数計算
corr = pivot_df.corr()
# ヒートマップ作成
fig = go.Figure(data=go.Heatmap(
z=corr,
x=corr.columns,
y=corr.columns,
colorscale='RdBu',
zmin=-1,
zmax=1
))
fig.update_layout(
title="部門間の利益相関",
height=500
)
st.plotly_chart(fig, use_container_width=True)
def main():
st.title("財務分析ダッシュボード")
global df
df = load_data()
create_department_metrics()
create_trend_chart()
create_heatmap()
# データテーブル表示(オプション)
if st.checkbox("詳細データを表示"):
st.dataframe(df)
if __name__ == "__main__":
main()
実行方法
streamlit run finance_dashboard.py
主要機能の実装解説
データ読み込み(load_data関数)
BigQueryから取得したデータを加工し、分析に必要な指標を計算します。このデータが他の全ての表示の基礎となります。
WITH句で月次サマリーを作成し、1回のクエリで効率的にデータ取得
CASE文で収益・費用を正負で区別
計算済み指標(利益率など)もSQLで事前計算
部門別メトリクス(create_department_metrics関数)
選択された部門の主要な財務指標をダッシュボード形式で表示します。直感的な部門パフォーマンスの把握が可能です。
st.selectboxで部門選択UIを実装
st.columns(3)で3カラムレイアウトを構成
st.metricで指標を視覚的に表示
f文字列でフォーマット(通貨表示)
トレンドチャート(create_trend_chart関数)
時系列での推移を可視化し、部門間の比較や傾向分析を可能にします。
st.radioで指標切り替えを実装
Plotly Expressで対話的グラフ生成
format_funcで表示名を日本語化
カラーコーディングで部門を区別
相関ヒートマップ(create_heatmap関数)
部門間の関係性を視覚化し、事業構造の理解を深めることができます。
pandas.pivotでデータ形式を変換
corr()で相関係数を計算
Plotly.go.Heatmapで可視化
RdBu(赤青)カラースケールで相関を表現
まとめと次のステップ
今回の実装により、財務データの動的な分析が可能になりました。明日は財務指標の自動計算と分析レポート生成機能を実装していきます。
#Python #Streamlit #DataVisualization #FinancialAnalysis #AdventCalendar