Spaces:
Sleeping
Sleeping
import pandas as pd | |
from bs4 import BeautifulSoup | |
import requests | |
import streamlit as st | |
import plotly.express as px | |
import io | |
import tempfile | |
# Function to send messages and images via LINE | |
def send_line_message(channel_access_token, user_id, df, img_paths): | |
line_bot_api = LineBotApi(channel_access_token) | |
# Send DataFrame as a text message | |
text_message = TextSendMessage(text=df.to_string()) | |
line_bot_api.push_message(user_id, text_message) | |
# Send images | |
for img_path in img_paths: | |
image_message = ImageSendMessage(original_content_url=img_path, preview_image_url=img_path) | |
line_bot_api.push_message(user_id, image_message) | |
def fetch_table_data(url, table_id, has_header=True, rename_columns=None, drop_columns=None, custom_columns=None): | |
response = requests.get(url) | |
soup = BeautifulSoup(response.text, "html.parser") | |
table = soup.find("table", {"id": table_id}) | |
if not table: | |
st.warning(f"在 {url} 中找不到 ID 為 {table_id} 的表格") | |
return pd.DataFrame() | |
rows = table.find_all("tr") | |
if not rows: | |
st.warning(f"在 {url} 中,ID 為 {table_id} 的表格中找不到任何行") | |
return pd.DataFrame() | |
if has_header: | |
columns = [th.text.strip() for th in rows[0].find_all("th")] | |
data = [] | |
for row in rows[1:]: | |
row_data = [td.text.strip() for td in row.find_all("td")] | |
if row_data: | |
data.append(row_data) | |
else: | |
columns = custom_columns | |
data = [] | |
for row in rows: | |
row_data = [td.text.strip() for td in row.find_all("td")] | |
if row_data: | |
data.append(row_data) | |
if not data: | |
st.warning(f"在 {url} 中,ID 為 {table_id} 的表格中找不到任何資料行") | |
return pd.DataFrame() | |
if len(columns) > 0: | |
for i, row in enumerate(data): | |
if len(row) != len(columns): | |
st.warning(f"資料行 {i+1} 的列數與標題列數不一致:{len(row)} vs {len(columns)}") | |
return pd.DataFrame() | |
df = pd.DataFrame(data, columns=columns) | |
if rename_columns: | |
df = df.rename(columns=rename_columns) | |
if drop_columns: | |
df = df.drop(columns=drop_columns) | |
return df | |
def calculate_stats(df): | |
df["病床數"] = pd.to_numeric(df["病床數"], errors='coerce') | |
df["佔床數"] = pd.to_numeric(df["佔床數"], errors='coerce') | |
df["空床數"] = df["病床數"] - df["佔床數"] | |
total_beds = df["病床數"].sum() | |
occupied_beds = df["佔床數"].sum() | |
occupancy_rate = (occupied_beds / total_beds) * 100 if total_beds > 0 else 0 | |
return total_beds, occupied_beds, occupancy_rate | |
def main(): | |
st.title("👩🍼🚑台南醫院病床狀態查詢🐇") | |
url1 = "https://www.tmh.org.tw/tmh2016/ImpBD.aspx?Kind=2" | |
url2 = "https://www.chimei.org.tw/%E4%BD%94%E5%BA%8A%E7%8E%87%E6%9F%A5%E8%A9%A2/%E4%BD%94%E5%BA%8A%E7%8E%87%E6%9F%A5%E8%A9%A2.aspx?ihospital=10&ffloor=" | |
url3 = "https://web.hosp.ncku.edu.tw/nckm/Bedstatus/BedStatus.aspx" | |
table_id1 = "ctl00_ContentPlaceHolder1_GV_Bed" | |
table_id2 = "DG1" | |
table_id3 = "GV_EmgInsure" | |
df1 = fetch_table_data(url1, table_id1, rename_columns={'床位別數':'病床數', '住院人數':'佔床數'}, drop_columns=['佔床率']) | |
df2 = fetch_table_data(url2, table_id2, has_header=False, custom_columns=["病床類別", "病床數", "佔床數", "空床數", "佔床率"], drop_columns=['佔床率']) | |
df3 = fetch_table_data(url3, table_id3) | |
if not df1.empty: | |
df1 = df1.rename(columns={'病床種類':'病床類別'}) | |
df1['醫院'] = '台南市立醫院' | |
if not df2.empty: | |
df2 = df2.drop(index=0) | |
df2['醫院'] = '奇美醫院' | |
if not df3.empty: | |
df3['醫院'] = '成大醫院' | |
combined_df = pd.concat([df for df in [df1, df2, df3] if not df.empty], ignore_index=True) | |
hospital_choice = st.selectbox( | |
"選擇醫院或顯示合併數據", | |
("台南市立醫院", "奇美醫院", "成大醫院", "三間醫院合併顯示") | |
) | |
def plot_hospital_data(df, hospital_name): | |
total_beds, occupied_beds, occupancy_rate = calculate_stats(df) | |
st.subheader(hospital_name) | |
st.write(f"總病床數: {total_beds}") | |
st.write(f"佔床數: {occupied_beds}") | |
st.write(f"佔床率: {occupancy_rate:.2f}%") | |
df_long = df.melt(id_vars=["病床類別"], value_vars=["病床數", "佔床數", "空床數"], | |
var_name="類型", value_name="數量") | |
fig = px.bar(df_long, x="病床類別", y="數量", color="類型", barmode="group", | |
title=f"{hospital_name}病床狀況") | |
st.write(df) | |
st.plotly_chart(fig) | |
if hospital_choice == "台南市立醫院" and not df1.empty: | |
plot_hospital_data(df1, "台南市立醫院") | |
elif hospital_choice == "奇美醫院" and not df2.empty: | |
plot_hospital_data(df2, "奇美醫院") | |
elif hospital_choice == "成大醫院" and not df3.empty: | |
plot_hospital_data(df3, "成大醫院") | |
elif hospital_choice == "三間醫院合併顯示" and not combined_df.empty: | |
total_beds, occupied_beds, occupancy_rate = calculate_stats(combined_df) | |
st.subheader("合併後的數據") | |
st.write(f"總病床數: {total_beds}") | |
st.write(f"佔床數: {occupied_beds}") | |
st.write(f"佔床率: {occupancy_rate:.2f}%") | |
combined_df_long = combined_df.melt(id_vars=["醫院", "病床類別"], | |
value_vars=["病床數", "佔床數", "空床數"], | |
var_name="類型", value_name="數量") | |
fig = px.bar(combined_df_long, x="醫院", y="數量", color="類型", barmode="group", | |
title="合併後的病床狀況") | |
st.write(combined_df) | |
st.plotly_chart(fig) | |
# 新增三個按鈕並排放置,並放大圓餅圖尺寸 | |
col1, col2, col3 = st.columns(3) | |
with col1: | |
if st.button("顯示圓餅圖:病床數"): | |
fig_pie = px.pie(combined_df, names="醫院", values="病床數", title="合併後各醫院病床總數分布") | |
fig_pie.update_layout(width=600, height=600) # 調整圓餅圖的尺寸 | |
st.plotly_chart(fig_pie) | |
with col2: | |
if st.button("顯示圓餅圖:佔床數"): | |
fig_pie2 = px.pie(combined_df, names="醫院", values="佔床數", title="合併後各醫院佔床總數分布") | |
fig_pie2.update_layout(width=600, height=600) # 調整圓餅圖的尺寸 | |
st.plotly_chart(fig_pie2) | |
with col3: | |
if st.button("顯示圓餅圖:空床數"): | |
fig_pie3 = px.pie(combined_df, names="醫院", values="空床數", title="合併後各醫院空床總數分布") | |
fig_pie3.update_layout(width=600, height=600) # 調整圓餅圖的尺寸 | |
st.plotly_chart(fig_pie3) | |
if __name__ == "__main__": | |
main() | |