import streamlit as st import pandas as pd import plotly.express as px from dataclasses import dataclass, field from typing import Dict, Tuple, Any # 📥 讀取 Google 試算表函數 def read_google_sheet(sheet_id, sheet_number=0): """📥 從 Google Sheets 讀取數據""" url = f'https://docs.google.com/spreadsheets/d/{sheet_id}/export?format=csv&gid={sheet_number}' try: df = pd.read_csv(url) return df except Exception as e: st.error(f"❌ 讀取失敗:{str(e)}") return None # 📊 Google Sheets ID sheet_id = "1Wc15DZWq48MxL7nXAsROJ6sRvH5njSa1ea0aaOGUOVk" gid = "1168424766" @dataclass class SurveyMappings: """📋 問卷數據對應""" gender: Dict[str, int] = field(default_factory=lambda: {'男性': 1, '女性': 2}) education: Dict[str, int] = field(default_factory=lambda: { '國小(含)以下': 1, '國/初中': 2, '高中/職': 3, '專科': 4, '大學': 5, '研究所(含)以上': 6}) frequency: Dict[str, int] = field(default_factory=lambda: { '第1次': 1, '2-3次': 2, '4-6次': 3, '6次以上': 4, '經常來學習,忘記次數了': 5}) class SurveyAnalyzer: """📊 問卷分析類""" def __init__(self): self.mappings = SurveyMappings() self.satisfaction_columns = [ '1. 示範場域提供多元的數位課程與活動', '2.示範場域的數位課程與活動對我的生活應用有幫助', '3. 示範場域的服務人員親切有禮貌', '4.示範場域的服務空間與數位設備友善方便', '5.在示範場域可以獲得需要的協助', '6.對於示範場域的服務感到滿意' ] def generate_report(self, df: pd.DataFrame) -> Dict[str, Any]: """📝 生成問卷調查報告""" return { '基本統計': { '總受訪人數': len(df), '性別分布': df['1. 性別'].value_counts().to_dict(), '教育程度分布': df['3.教育程度'].value_counts().to_dict(), '平均年齡': f"{pd.to_numeric(df['2.出生年(民國__年)'], errors='coerce').mean():.1f}歲" }, '滿意度統計': { '整體平均滿意度': f"{df['6.對於示範場域的服務感到滿意'].mean():.2f}", '最高分項目': df[self.satisfaction_columns].mean().idxmax(), '最低分項目': df[self.satisfaction_columns].mean().idxmin() } } def plot_satisfaction_correlation(self, df: pd.DataFrame): """🔥 滿意度相關性熱力圖""" correlation_matrix = df[self.satisfaction_columns].corr() fig = px.imshow(correlation_matrix, text_auto=True, color_continuous_scale='viridis', title='🔥 滿意度項目相關性熱力圖') # ✅ 放大圖表 fig.update_layout( font=dict(size=20), title_font=dict(size=26, family="Arial Black"), width=1000, height=800, coloraxis_colorbar=dict(title="相關性"), ) st.plotly_chart(fig, use_container_width=True) def plot_gender_distribution(self, df: pd.DataFrame): """🟠 性別分佈圓餅圖""" gender_counts = df['1. 性別'].value_counts().reset_index() gender_counts.columns = ['性別', '人數'] fig = px.pie(gender_counts, names='性別', values='人數', title='🟠 受訪者性別分布', color_discrete_sequence=px.colors.sequential.Sunset) st.plotly_chart(fig, use_container_width=True) # 🎨 Streamlit UI def main(): st.set_page_config(page_title="問卷調查分析", layout="wide") st.title("📊 問卷調查分析報告") st.write("本頁面展示問卷調查數據的分析結果,包括統計信息與視覺化圖表。") # 讀取數據 df = read_google_sheet(sheet_id, gid) if df is not None: analyzer = SurveyAnalyzer() # 📌 基本統計數據 st.sidebar.header("📌 選擇數據分析") selected_analysis = st.sidebar.radio("選擇要查看的分析", ["📋 問卷統計報告", "🔥 滿意度相關性熱力圖", "🟠 性別分佈"]) if selected_analysis == "📋 問卷統計報告": st.header("📋 問卷統計報告") report = analyzer.generate_report(df) for category, stats in report.items(): with st.expander(f"🔍 {category}"): for key, value in stats.items(): st.write(f"**{key}**: {value}") elif selected_analysis == "🔥 滿意度相關性熱力圖": st.header("🔥 滿意度相關性熱力圖") analyzer.plot_satisfaction_correlation(df) elif selected_analysis == "🟠 性別分佈": st.header("🟠 性別分佈") analyzer.plot_gender_distribution(df) if __name__ == "__main__": main()