0814_HOSPITAL / app.py
Roberta2024's picture
Update app.py
3edc535 verified
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()