KKingzor's picture
Create app.py
278eb2a verified
import pandas as pd
import requests
from io import StringIO
import chardet
import plotly.express as px
import streamlit as st
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
# 定義 URL 和文件描述
urls = {
'df1': "https://mopsfin.twse.com.tw/opendata/t187ap46_L_1.csv", # 溫室氣體排放
'df2': "https://mopsfin.twse.com.tw/opendata/t187ap46_O_2.csv", # 能源管理
'df3': "https://mopsfin.twse.com.tw/opendata/t187ap46_L_6.csv" # 董事會
}
def load_and_prepare_data(url):
response = requests.get(url)
if response.status_code == 200:
content = response.content
result = chardet.detect(content)
encoding = result['encoding']
data = StringIO(content.decode(encoding))
df = pd.read_csv(data, encoding=encoding)
df.fillna(0, inplace=True)
return df
else:
print(f"Failed to retrieve the data from {url}. Status code:", response.status_code)
return pd.DataFrame() # 返回空 DataFrame
# 下載並處理每個 CSV 文件
df1 = load_and_prepare_data(urls['df1'])
df2 = load_and_prepare_data(urls['df2'])
df3 = load_and_prepare_data(urls['df3'])
# 假設所有 DataFrame 中的公司名稱列名為 '公司名稱',根據實際情況調整列名
common_column = '公司名稱'
# 合併 DataFrame
merged_df = df1.merge(df2, on=common_column, how='outer').merge(df3, on=common_column, how='outer')
# 需要保留的列名
required_columns = [
'公司名稱',
'範疇一排放量(噸CO2e)',
'範疇二排放量(噸CO2e)',
'範疇三排放量(噸CO2e)',
'溫室氣體排放密集度(公噸CO₂e/百萬元營業額)',
'使用率(再生能源/總能源)',
'女性董事席次及比率-席',
'董事出席董事會出席率',
'董事進修時數符合進修要點比率'
]
# 保留需要的列
optimized_df = merged_df[required_columns]
# Streamlit 應用
st.title('台灣企業 ESG 揭露數據分析')
# 顯示數據表格
st.subheader('數據表格')
st.dataframe(optimized_df)
# 添加下拉選單,選項為 optimized_df 的列名(排除 '公司名稱')
columns_to_plot = [col for col in optimized_df.columns if col != '公司名稱']
selected_column = st.selectbox('選擇要顯示的數據', columns_to_plot)
# 繪製環形圖
st.subheader('環形圖')
fig_donut = px.pie(optimized_df, names='公司名稱', values=selected_column,
title=f'{selected_column} 的公司分佈', hole=0.3)
fig_donut.update_layout(width=800, height=600) # 設定圖表的寬度和高度
st.plotly_chart(fig_donut, use_container_width=True)
# 繪製折線圖
st.subheader('折線圖')
fig_line = px.line(optimized_df, x='公司名稱', y=selected_column,
title=f'{selected_column} 的公司趨勢')
fig_line.update_layout(width=800, height=600) # 設定圖表的寬度和高度
fig_line.update_xaxes(tickangle=45) # 調整 x 軸標籤的角度
st.plotly_chart(fig_line, use_container_width=True)
# K-means 聚類分析
st.subheader('K-means 聚類分析')
# 選擇兩個特徵進行聚類
feature1 = st.selectbox('選擇第一個特徵', columns_to_plot)
feature2 = st.selectbox('選擇第二個特徵', [col for col in columns_to_plot if col != feature1])
# 準備數據
X = optimized_df[[feature1, feature2]].dropna()
if len(X) > 0:
# 標準化數據
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 執行 K-means 聚類
n_clusters = st.slider('選擇聚類數量', min_value=2, max_value=10, value=3)
kmeans = KMeans(n_clusters=n_clusters, random_state=42)
clusters = kmeans.fit_predict(X_scaled)
# 將聚類結果添加到數據框中
clustered_df = X.copy()
clustered_df['Cluster'] = clusters
clustered_df['公司名稱'] = optimized_df.loc[X.index, '公司名稱']
# 繪製聚類散點圖
fig_cluster = px.scatter(clustered_df, x=feature1, y=feature2, color='Cluster',
hover_data=['公司名稱'],
title=f'基於 {feature1}{feature2} 的 K-means 聚類結果')
st.plotly_chart(fig_cluster)
else:
st.write("選擇的特徵中包含無效數據,無法執行聚類分析。")