Rozeeeee commited on
Commit
9849bd6
·
verified ·
1 Parent(s): 701428c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +54 -103
app.py CHANGED
@@ -1,109 +1,60 @@
1
  import streamlit as st
2
- import pandas as pd
3
  import requests
 
4
  import plotly.express as px
5
- import matplotlib.pyplot as plt
6
- import io
7
-
8
- # 設置顏色主題
9
- theme = px.colors.qualitative.Bold
10
-
11
- # 下載並載入 CSV 數據
12
- def download_and_load_csv(url):
13
- response = requests.get(url)
14
- response.encoding = 'utf-8'
15
- df = pd.read_csv(io.StringIO(response.text), encoding='utf-8')
16
- df = df.fillna(0) # 避免 NaN 錯誤
17
- return df
18
-
19
- # 美化圖表
20
- def beautify_chart(fig):
21
- fig.update_layout(
22
- font_family="Arial",
23
- font_color="#444",
24
- title_font_family="Arial",
25
- title_font_color="#000",
26
- legend_title_font_color="#000",
27
- plot_bgcolor='rgba(0,0,0,0)',
28
- paper_bgcolor='rgba(0,0,0,0)',
29
- )
30
- fig.update_xaxes(showline=True, linewidth=2, linecolor='lightgray', gridcolor='lightgray')
31
- fig.update_yaxes(showline=True, linewidth=2, linecolor='lightgray', gridcolor='lightgray')
32
- return fig
33
-
34
- # **生成 Matplotlib 圖表**
35
- def generate_matplotlib_plot(df, selected_columns):
36
- fig, ax = plt.subplots()
37
- for col in selected_columns:
38
- ax.plot(df["公司名稱"], df[col], label=col)
39
- ax.set_xlabel("公司名稱")
40
- ax.set_ylabel("排放量")
41
- ax.set_title("Matplotlib 折線圖")
42
- ax.legend()
43
- st.pyplot(fig)
44
-
45
- # **生成 Plotly 圖表**
46
- def generate_plots(df, df_name, selected_columns, chart_type):
47
- selected_columns = list(selected_columns) # 確保是列表
48
-
49
- # 🛠️ 確保選擇的欄位存在
50
- existing_columns = set(df.columns)
51
- valid_selected_columns = [col for col in selected_columns if col in existing_columns]
52
-
53
- if not valid_selected_columns:
54
- st.error(f"❌ 選擇的欄位無法在數據中找到,請檢查欄位名稱!\n\n📋 可用欄位: {list(existing_columns)}")
55
- return
56
-
57
- df = df.dropna(subset=["公司名稱"] + valid_selected_columns) # **移除 NaN 確保長度相同**
58
- df[valid_selected_columns] = df[valid_selected_columns].apply(pd.to_numeric, errors='coerce')
59
 
60
- with st.expander(f"📊 顯示 {df_name} 圖表"):
61
- st.subheader(f"{df_name} - {chart_type} 圖")
62
- fig = None # 預設圖表為 None
63
-
64
- if chart_type == "折線圖":
65
- fig = px.line(df, x="公司名稱", y=valid_selected_columns, title=f"{df_name} - 折線圖", color_discrete_sequence=theme)
66
- elif chart_type == "長條圖":
67
- fig = px.bar(df, x="公司名稱", y=valid_selected_columns, title=f"{df_name} - 長條圖", color_discrete_sequence=theme)
68
- elif chart_type == "餅圖":
69
- total_emissions = df.groupby("公司名稱")[valid_selected_columns].sum().reset_index()
70
- total_emissions = total_emissions.melt(id_vars=["公司名稱"], value_vars=valid_selected_columns, var_name="排放類型", value_name="總排放量")
71
- fig = px.pie(total_emissions, values='總排放量', names='公司名稱', title=f"{df_name} - 餅圖", color_discrete_sequence=theme, hole=0.3)
72
- fig.update_traces(textposition='inside', textinfo='percent+label')
73
-
74
- if fig:
75
- fig = beautify_chart(fig)
76
- st.plotly_chart(fig, use_container_width=True)
77
 
78
- # 額外顯示 Matplotlib 圖表
79
- st.subheader("📉 Matplotlib 折線圖")
80
- generate_matplotlib_plot(df, valid_selected_columns)
81
-
82
- # **下載數據**
83
- urls = [
84
- "https://mopsfin.twse.com.tw/opendata/t187ap46_L_1.csv",
85
- "https://mopsfin.twse.com.tw/opendata/t187ap46_O_2.csv",
86
- "https://mopsfin.twse.com.tw/opendata/t187ap46_L_6.csv"
87
- ]
88
-
89
- dfs = [download_and_load_csv(url) for url in urls]
90
- combined_df = pd.concat(dfs, ignore_index=True).fillna(0) # 合併數據並填充 NaN 值
91
-
92
- # **Streamlit UI**
93
- st.title("📊 台灣企業 ESG 數據分析")
94
-
95
- st.subheader("📂 數據預覽")
96
- st.dataframe(combined_df)
97
-
98
- # **選擇數據欄位**
99
- emission_columns = [col for col in ["範疇一排放量(噸CO2e)", "範疇二排放量(噸CO2e)", "範疇三排放量(噸CO2e)"] if col in combined_df.columns]
100
- selected_columns = st.multiselect("選擇要顯示的排放類別", emission_columns, default=emission_columns[:1] if emission_columns else [])
101
-
102
- # **選擇圖表類型**
103
- chart_type = st.selectbox("選擇圖表類型", ["折線圖", "長條圖", "餅圖"])
104
-
105
- # **生成圖表**
106
- if selected_columns:
107
- generate_plots(combined_df, "綜合數據", selected_columns, chart_type)
108
  else:
109
- st.write("⚠️ 請選擇至少一個排放類別來顯示圖表。")
 
1
  import streamlit as st
 
2
  import requests
3
+ import pandas as pd
4
  import plotly.express as px
5
+ import matplotlib as mpl
6
+ import matplotlib.font_manager as fm
7
+ import os
8
+ from io import StringIO
9
+
10
+ def install_custom_font():
11
+ font_path = "TaipeiSansTCBeta-Regular.ttf"
12
+ if not os.path.exists(font_path):
13
+ font_url = "https://drive.google.com/uc?id=1eGAsTN1HBpJAkeVM57_C7ccp7hbgSz3_&export=download"
14
+ font_response = requests.get(font_url)
15
+ with open(font_path, "wb") as font_file:
16
+ font_file.write(font_response.content)
17
+ fm.fontManager.addfont(font_path)
18
+ mpl.rc('font', family='Taipei Sans TC Beta')
19
+
20
+ install_custom_font()
21
+
22
+ st.title("📊 台股財報數據可視化")
23
+
24
+ # 直接讀取固定 URL 的 CSV 檔案
25
+ url = "https://mopsfin.twse.com.tw/opendata/t187ap46_L_1.csv"
26
+ response = requests.get(url)
27
+ response.encoding = "utf-8"
28
+
29
+ df = pd.read_csv(StringIO(response.text))
30
+ df_cleaned = df.fillna(0) # 填補缺失值
31
+
32
+ st.subheader("📌 數據預覽")
33
+ st.write(df_cleaned.head())
34
+
35
+ # 讓用戶篩選數據
36
+ st.subheader("🔍 數據篩選")
37
+ filter_col = st.selectbox("選擇要篩選的欄位", df_cleaned.columns)
38
+ unique_values = df_cleaned[filter_col].unique()
39
+ selected_value = st.selectbox("選擇篩選值", unique_values)
40
+ filtered_df = df_cleaned[df_cleaned[filter_col] == selected_value]
41
+
42
+ st.write(filtered_df.head())
43
+
44
+ # 讓用戶選擇數值欄位
45
+ numeric_cols = filtered_df.select_dtypes(include=['number']).columns
46
+ if len(numeric_cols) > 0:
47
+ col_choice = st.selectbox("選擇要視覺化的數值欄位", numeric_cols)
 
 
 
 
 
 
 
 
 
 
 
48
 
49
+ if st.button("生成圖表"):
50
+ # 長條圖
51
+ st.subheader("📊 長條圖")
52
+ fig_bar = px.bar(filtered_df.head(10), x=filtered_df.index[:10], y=col_choice, title=f"{col_choice} 長條圖")
53
+ st.plotly_chart(fig_bar)
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
+ # 圓餅圖
56
+ st.subheader("🥧 圓餅圖")
57
+ fig_pie = px.pie(filtered_df.head(10), names=filtered_df.index[:10], values=col_choice, title=f"{col_choice} 圓餅圖")
58
+ st.plotly_chart(fig_pie)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  else:
60
+ st.warning(" 沒有數值型欄位可供選擇")