sgps51204/Matplotlib_Pro
0
1import pandas as pd2import matplotlib.pyplot as plt3from io import BytesIO4import requests5import streamlit as st6import numpy as np7import seaborn as sns8 9import matplotlib10zhfont = matplotlib.font_manager.FontProperties(fname='./SourceHanSansTW-Regular.otf')11 12#st.set_option('deprecation.showPyplotGlobalUse', False)13 14# 標題15st.title("📊 資料視覺化平台(使用 matplotlib)")16 17"""18請上傳或輸入一個 CSV 檔案網址,選擇要繪製的欄位與圖表類型,即可使用 matplotlib 進行視覺化。19"""20 21# 🖼️ 主繪圖函數(matplotlib 版本)22def visualization(df, x_col, y_col, chart_type):23 fig, ax = plt.subplots(figsize=(8, 5))24 25 if chart_type == "折線圖(Line)":26 df.plot(x=x_col, y=y_col, ax=ax, marker='o', linestyle='-')27 ax.set_title("折線圖", fontproperties=zhfont, fontsize=16)28 ax.set_xlabel(x_col)29 ax.set_ylabel(y_col)30 31 elif chart_type == "長條圖(Bar)":32 df.plot(x=x_col, y=y_col, kind='bar', ax=ax)33 ax.set_title("長條圖", fontproperties=zhfont, fontsize=16)34 ax.set_xlabel(x_col)35 ax.set_ylabel(y_col)36 37 elif chart_type == "直方圖(Histogram)":38 ax.hist(df[y_col], bins=10, color='skyblue', edgecolor='black')39 ax.set_title("直方圖", fontproperties=zhfont, fontsize=16)40 ax.set_xlabel(y_col)41 # ax.set_ylabel("頻數", fontproperties=zhfont, fontsize=16)42 43 elif chart_type == "密度圖(Density)":44 sns.kdeplot(df[y_col], fill=True, ax=ax, color='purple', alpha=0.5)45 ax.set_title("密度圖", fontproperties=zhfont, fontsize=16)46 ax.set_xlabel(y_col)47 ax.set_ylabel("密度", fontproperties=zhfont, fontsize=16)48 49 st.pyplot(fig)50 plt.close(fig)51 52# 📥 選擇資料來源53option = st.radio("選擇資料來源:", ["上傳 CSV 檔", "輸入 CSV 網址"])54 55# 📊 圖表類型56chart_type = st.selectbox("請選擇圖表類型:", [57 "折線圖(Line)",58 "長條圖(Bar)",59 "直方圖(Histogram)",60 "密度圖(Density)"61])62 63data = None64 65# 📂 上傳檔案66if option == "上傳 CSV 檔":67 uploaded_file = st.file_uploader("請上傳 CSV 檔", type=["csv"])68 if uploaded_file:69 try:70 data = pd.read_csv(uploaded_file)71 st.success("✅ 成功讀取檔案")72 except Exception as e:73 st.error(f"❌ 讀取失敗:{e}")74 75# 🌐 輸入網址76else:77 url = st.text_input("請輸入 CSV 網址")78 if url:79 try:80 response = requests.get(url)81 response.raise_for_status()82 data = pd.read_csv(BytesIO(response.content))83 st.success("✅ 成功從網址載入資料")84 except Exception as e:85 st.error(f"❌ 無法讀取網址:{e}")86 87# 🎯 動態互動欄位選擇88if data is not None:89 st.write("🔍 資料預覽:")90 st.dataframe(data.head())91 92 # 欄位分類93 numeric_cols = data.select_dtypes(include='number').columns.tolist()94 categorical_cols = data.select_dtypes(exclude='number').columns.tolist()95 96 st.markdown("### 🧮 數值欄位")97 st.write(numeric_cols or "(無)")98 99 st.markdown("### 🔤 類別欄位")100 st.write(categorical_cols or "(無)")101 102 # Y 軸(數值欄位)103 y_col = st.selectbox("請選擇數值欄位作為 Y 軸", options=numeric_cols)104 105 # X 軸(類別欄位或 index)106 x_col_options = categorical_cols + ["index"]107 x_col = st.selectbox("請選擇類別欄位作為 X 軸(或 index)", options=x_col_options)108 109 # 若選 index 則加回去110 if x_col == "index":111 data = data.reset_index()112 113 # 執行繪圖114 if y_col:115 visualization(data, x_col, y_col, chart_type)116 