Code-Nik10/Hospital-Analysis
1
1 2import io3import pandas as pd4import seaborn as sns5import matplotlib.pyplot as plt6from PIL import Image7 8plt.switch_backend("Agg")9 10REQUIRED_COLUMNS = ["department", "patient_id", "visit_date"]11 12def load_data(file_obj) -> pd.DataFrame:13 df = pd.read_csv(file_obj)14 missing = [c for c in REQUIRED_COLUMNS if c not in df.columns]15 if missing:16 raise ValueError(f"Missing required columns: {missing}")17 df["department"] = df["department"].astype(str).str.strip()18 df["patient_id"] = df["patient_id"].astype(str).str.strip()19 df["visit_date"] = pd.to_datetime(df["visit_date"], errors="coerce")20 df = df.dropna(subset=["department", "patient_id", "visit_date"])21 return df22 23def department_counts(df: pd.DataFrame) -> pd.DataFrame:24 counts = df.groupby("department")["patient_id"].nunique().reset_index(name="patient_count")25 return counts.sort_values("patient_count", ascending=False)26 27def percentage_split(counts_df: pd.DataFrame) -> pd.DataFrame:28 total = counts_df["patient_count"].sum()29 counts_df["percentage"] = (counts_df["patient_count"] / total * 100).round(2)30 return counts_df31 32def bar_chart(counts_df: pd.DataFrame):33 fig, ax = plt.subplots(figsize=(8, 5), dpi=120)34 sns.barplot(data=counts_df, x="department", y="patient_count", ax=ax,35 palette="Blues", hue=None, legend=False)36 ax.set_title("Patient count per department")37 ax.set_xlabel("Department")38 ax.set_ylabel("Patients")39 ax.tick_params(axis="x", rotation=30)40 fig.tight_layout()41 buf = io.BytesIO()42 fig.savefig(buf, format="png", bbox_inches="tight")43 plt.close(fig)44 buf.seek(0)45 return Image.open(buf)46 47def stats_report(df: pd.DataFrame, counts_df: pd.DataFrame) -> str:48 total_patients = df["patient_id"].nunique()49 total_visits = len(df)50 unique_departments = df["department"].nunique()51 top = counts_df.iloc[0] if not counts_df.empty else None52 lines = [53 f"Total patients: {total_patients}",54 f"Total visits: {total_visits}",55 f"Unique departments: {unique_departments}"56 ]57 if top is not None:58 lines.append(f"Top department: {top['department']} ({top['patient_count']} patients)")59 if "length_of_stay_days" in df.columns:60 avg_los = df["length_of_stay_days"].dropna().astype(float).mean()61 lines.append(f"Average length of stay (days): {avg_los:.2f}")62 return "\n".join(lines)63 64def end_to_end(file_obj):65 df = load_data(file_obj)66 counts = department_counts(df)67 counts = percentage_split(counts)68 chart_img = bar_chart(counts)69 stats = stats_report(df, counts)70 return counts, chart_img, stats