From 9dd42861572ec704eb2c83de6d63799d6dfcfcdd Mon Sep 17 00:00:00 2001 From: Sarah Kota Date: Tue, 28 Apr 2026 16:27:31 -0400 Subject: [PATCH 01/11] deleting unnecessary files --- src/ertimes/democaligraphs1.py | 326 --------------------------------- src/ertimes/demotest.py | 36 ---- 2 files changed, 362 deletions(-) delete mode 100644 src/ertimes/democaligraphs1.py delete mode 100644 src/ertimes/demotest.py diff --git a/src/ertimes/democaligraphs1.py b/src/ertimes/democaligraphs1.py deleted file mode 100644 index 0b5f6cf..0000000 --- a/src/ertimes/democaligraphs1.py +++ /dev/null @@ -1,326 +0,0 @@ -import pandas as pd -import matplotlib.pyplot as plt -import numpy as np - - -def load_merged_data(filepath: str) -> pd.DataFrame: - """ - This function loads the merged hospital/demographic data dataset from a CSV file. - - Parameters - ---------- - filepath : str - This is the path to the merged CSV file. - - Returns - ------- - pd.DataFrame - This is a cleaned dataframe with standardized county names. - """ - df = pd.read_csv(filepath) - - # Standardize county names so grouping works even if capitalization/spaces differ. - df["county"] = ( - df["county"] - .astype(str) - .str.strip() - .str.lower() - .str.replace(" county", "", regex=False) - ) - - return df - - -def clean_numeric_column(df: pd.DataFrame, column: str) -> pd.Series: - """ - This function converts each column to numeric values, removing commas if needed. - - Parameters - ---------- - df : pd.DataFrame - Input dataframe. - column : str - Column name to clean. - - Returns - ------- - pd.Series - Numeric version of the column. - """ - return pd.to_numeric( - df[column].astype(str).str.replace(",", "", regex=False), - errors="coerce" - ) - - -def summarize_by_county(df: pd.DataFrame) -> pd.DataFrame: - """ - This function create sone row per county. - - Demographic variables are averaged or taken as first values because they are - county-level values repeated across hospital rows. Hospital variables are - averaged across hospitals/years within each county. - """ - - # Columns that should be numeric before aggregation. - numeric_cols = [ - "cfambelowpovperc", - "cpersbelowpovperc", - "aperclessHS", - "apercbachplus", - "bmedianfamincome", - "bmedianHHincome", - "dpercnonenglish", - "epop>65perc", - "fhispperc", - "fblackperc", - "fwhiteperc", - "fforbornperc", - "tot_ed_nmbvsts", - "visits_per_station", - "edstations", - ] - - # Make a copy so the original dataframe is not changed unexpectedly. - df = df.copy() - - # Clean all selected numeric columns. - for col in numeric_cols: - if col in df.columns: - df[col] = clean_numeric_column(df, col) - - # Group by county to create county-level data. - county_df = df.groupby("county", as_index=False).agg({ - # Demographic variables - "cfambelowpovperc": "first", - "cpersbelowpovperc": "first", - "aperclessHS": "first", - "apercbachplus": "first", - "bmedianfamincome": "first", - "bmedianHHincome": "first", - "dpercnonenglish": "first", - "epop>65perc": "first", - "fhispperc": "first", - "fblackperc": "first", - "fwhiteperc": "first", - "fforbornperc": "first", - - # Hospital shortage area categories - "mentalhealthshortagearea": "first", - "primarycareshortagearea": "first", - - # Hospital/ED variables - "tot_ed_nmbvsts": "mean", - "visits_per_station": "mean", - "edstations": "mean", - }) - - return county_df - - -def graph_boxplot_by_category( - county_df: pd.DataFrame, - numeric_col: str, - category_col: str, - x_label: str, - y_label: str, - title: str -) -> None: - """ - This makes a boxplot comparing a numeric demographic variable across a categorical - hospital shortage-area variable. - """ - - # Keep only needed columns and remove missing values. - plot_df = county_df[[numeric_col, category_col]].dropna().copy() - - # Converts the numeric column safely. - plot_df[numeric_col] = pd.to_numeric(plot_df[numeric_col], errors="coerce") - plot_df = plot_df.dropna() - - groups = [] - labels = [] - - # Creates one boxplot group for each shortage-area category. - for category in sorted(plot_df[category_col].unique()): - group = plot_df.loc[plot_df[category_col] == category, numeric_col] - if len(group) > 0: - groups.append(group) - labels.append(str(category)) - - plt.figure(figsize=(8, 6)) - plt.boxplot(groups, tick_labels=labels) - plt.xlabel(x_label) - plt.ylabel(y_label) - plt.title(title) - plt.tight_layout() - plt.show() - - -def graph_scatter( - county_df: pd.DataFrame, - x_col: str, - y_col: str, - x_label: str, - y_label: str, - title: str -) -> None: - """ - This makes a scatterplot comparing one demographic variable to one hospital variable. - - A simple trendline is added when there are at least two valid points. - """ - - # Keep only the columns needed for the graph. - plot_df = county_df[[x_col, y_col]].dropna().copy() - - # Convert both columns to numeric values. - plot_df[x_col] = pd.to_numeric(plot_df[x_col], errors="coerce") - plot_df[y_col] = pd.to_numeric(plot_df[y_col], errors="coerce") - plot_df = plot_df.dropna() - - plt.figure(figsize=(8, 6)) - plt.scatter(plot_df[x_col], plot_df[y_col]) - - # Add a linear trendline to make the overall relationship easier to see. - if len(plot_df) >= 2: - slope, intercept = np.polyfit(plot_df[x_col], plot_df[y_col], 1) - x_vals = np.linspace(plot_df[x_col].min(), plot_df[x_col].max(), 100) - y_vals = slope * x_vals + intercept - plt.plot(x_vals, y_vals) - - plt.xlabel(x_label) - plt.ylabel(y_label) - plt.title(title) - plt.tight_layout() - plt.show() - - -def graph_correlation_heatmap(county_df: pd.DataFrame) -> None: - """ - This makes a simple correlation heatmap for selected demographic and hospital variables. - """ - - selected_cols = [ - "cfambelowpovperc", - "cpersbelowpovperc", - "aperclessHS", - "apercbachplus", - "bmedianHHincome", - "dpercnonenglish", - "epop>65perc", - "fforbornperc", - "tot_ed_nmbvsts", - "visits_per_station", - "edstations", - ] - - # Keep only columns that are actually present. - selected_cols = [col for col in selected_cols if col in county_df.columns] - - # Create numeric-only correlation dataframe. - corr_df = county_df[selected_cols].apply(pd.to_numeric, errors="coerce").corr() - - plt.figure(figsize=(10, 8)) - plt.imshow(corr_df) - plt.colorbar(label="Correlation") - plt.xticks(range(len(corr_df.columns)), corr_df.columns, rotation=90) - plt.yticks(range(len(corr_df.columns)), corr_df.columns) - plt.title("Correlation Heatmap: Demographics vs. Hospital Variables") - plt.tight_layout() - plt.show() - - -if __name__ == "__main__": - # Load the merged dataset. - df = load_merged_data("merged_output.csv") - - # Summarize to one row per county so demographic data is not repeated by hospital row. - county_df = summarize_by_county(df) - - # Print a quick preview to confirm the county-level dataset was created. - print(county_df.head()) - print("\nCounty-level shape:", county_df.shape) - - # Graph: poverty vs mental health shortage area. - graph_boxplot_by_category( - county_df, - numeric_col="cfambelowpovperc", - category_col="mentalhealthshortagearea", - x_label="Mental Health Shortage Area", - y_label="Families Below Poverty (%)", - title="County Family Poverty vs. Mental Health Shortage Area" - ) - - # Graph: poverty vs visits per station. - graph_scatter( - county_df, - x_col="cfambelowpovperc", - y_col="visits_per_station", - x_label="Families Below Poverty (%)", - y_label="Average Visits per Station", - title="County Family Poverty vs. Average Visits per Station" - ) - - # Graph 1: household income vs visits per station. - graph_scatter( - county_df, - x_col="bmedianHHincome", - y_col="visits_per_station", - x_label="Median Household Income ($)", - y_label="Average Visits per Station", - title="Median Household Income vs. Average Visits per Station" - ) - - # Graph 2: percent non-English-speaking households vs ED visits. - graph_scatter( - county_df, - x_col="dpercnonenglish", - y_col="tot_ed_nmbvsts", - x_label="Non-English-Speaking Households (%)", - y_label="Average Total ED Visits", - title="Non-English-Speaking Households vs. Average ED Visits" - ) - - # Graph 3: percent with bachelor's degree or higher vs visits per station. - graph_scatter( - county_df, - x_col="apercbachplus", - y_col="visits_per_station", - x_label="Bachelor's Degree or Higher (%)", - y_label="Average Visits per Station", - title="Education Level vs. Average Visits per Station" - ) - - # Graph 4: percent age 65+ vs ED stations. - graph_scatter( - county_df, - x_col="epop>65perc", - y_col="edstations", - x_label="Population Age 65+ (%)", - y_label="Average Number of ED Stations", - title="Older Adult Population vs. ED Stations" - ) - - # Graph 5: percent foreign-born vs total ED visits. - graph_scatter( - county_df, - x_col="fforbornperc", - y_col="tot_ed_nmbvsts", - x_label="Foreign-Born Population (%)", - y_label="Average Total ED Visits", - title="Foreign-Born Population vs. Average ED Visits" - ) - - # Graph 6: personal poverty vs primary care shortage area. - graph_boxplot_by_category( - county_df, - numeric_col="cpersbelowpovperc", - category_col="primarycareshortagearea", - x_label="Primary Care Shortage Area", - y_label="People Below Poverty (%)", - title="County Poverty vs. Primary Care Shortage Area" - ) - - # Graph 7: correlation heatmap for selected demographic and hospital variables. - graph_correlation_heatmap(county_df) diff --git a/src/ertimes/demotest.py b/src/ertimes/demotest.py deleted file mode 100644 index 1bec19a..0000000 --- a/src/ertimes/demotest.py +++ /dev/null @@ -1,36 +0,0 @@ -import pandas as pd -from ertimes.demodata import download_data - -# Tests whether a dataset can be successfully downloaded and loaded, -# verifies it is a valid DataFrame, and prints basic structure and content checks -def test_data_reading(dataset: str) -> bool: - """"Tests the ability to read and clean the specified dataset, - printing out key information about the resulting DataFrame. - Returns True if successful, False otherwise.""" - try: - print(f"Attempting to read data for {dataset}...") - df = download_data(dataset) - - if isinstance(df, pd.DataFrame): - print("Success: Data is a valid Pandas DataFrame.") - print(f"Success: Found {len(df)} rows of data.") - print(f"Success: Found {len(df.columns)} columns.") - print("\nColumns:") - print(df.columns.tolist()) - print("\nFirst 5 rows:") - print(df.head()) - - if "county" in df.columns: - print("\nSuccess: 'county' column detected.") - else: - print("\nWarning: 'county' column not found.") - - return True - - except Exception as e: - print(f"Failed to read data: {e}") - return False - - -if __name__ == "__main__": - test_data_reading("calidemodata") From 776b05d77fa99577d5006f2c15ce82536e0870da Mon Sep 17 00:00:00 2001 From: Sarah Kota Date: Tue, 28 Apr 2026 16:33:47 -0400 Subject: [PATCH 02/11] created scripts folder, moved files there and replaced hard-coding --- .../create_sample_census_data.py | 0 .../median_income_demo.py | 19 ++++++++----------- 2 files changed, 8 insertions(+), 11 deletions(-) rename src/{ertimes => scripts}/create_sample_census_data.py (100%) rename src/{ertimes => scripts}/median_income_demo.py (81%) diff --git a/src/ertimes/create_sample_census_data.py b/src/scripts/create_sample_census_data.py similarity index 100% rename from src/ertimes/create_sample_census_data.py rename to src/scripts/create_sample_census_data.py diff --git a/src/ertimes/median_income_demo.py b/src/scripts/median_income_demo.py similarity index 81% rename from src/ertimes/median_income_demo.py rename to src/scripts/median_income_demo.py index 646a0c4..fd64b8d 100644 --- a/src/ertimes/median_income_demo.py +++ b/src/scripts/median_income_demo.py @@ -7,17 +7,14 @@ import sys import importlib.util -# Load the module directly without going through __init__.py -spec = importlib.util.spec_from_file_location("Median_income", "/Users/maggie29755/ertimes/src/ertimes/Median_income.py") -module = importlib.util.module_from_spec(spec) -spec.loader.exec_module(module) - -load_california_income_data = module.load_california_income_data -get_income_by_zip = module.get_income_by_zip -get_income_by_county = module.get_income_by_county -get_income_statistics = module.get_income_statistics -filter_by_income_range = module.filter_by_income_range -display_income_summary = module.display_income_summary +from ertimes.stats_analysis import ( + load_california_income_data, + get_income_by_zip, + get_income_by_county, + get_income_statistics, + filter_by_income_range, + display_income_summary, +) def main(): From 346e2b46dae63e73795857c9979324e909369b48 Mon Sep 17 00:00:00 2001 From: Sarah Kota Date: Tue, 28 Apr 2026 16:34:19 -0400 Subject: [PATCH 03/11] deleted unnecessary file --- src/ertimes/mental_health.py | 110 ----------------------------------- 1 file changed, 110 deletions(-) delete mode 100644 src/ertimes/mental_health.py diff --git a/src/ertimes/mental_health.py b/src/ertimes/mental_health.py deleted file mode 100644 index 343a393..0000000 --- a/src/ertimes/mental_health.py +++ /dev/null @@ -1,110 +0,0 @@ -import pandas as pd -import numpy as np -from clean import clean_data - - - -df = pd.read_csv("data/Emergency Department Volume and Capacity - Catalog - ED_COMBINE_AL.csv") - -df = clean_data(df) - -""" -This function highlights facilities that experience both an above-average burden (namely, a higher-than-normal demand relative to available resources) and a shortage of mental health resources, identifying them at high-risk. -""" - -def mental_health_shortage_analysis(df): - """Analyzes the emergency department data to identify facilities that are - at high risk due to a combination of high burden and mental health - resource shortages. - The function calculates a burden score for each facility, - determines the average burden, and flags facilities""" - - - # Creates a copy to prevent modifying original dataframe - df = df.copy() - - # Converts to numeric using the cleaned column names - df['tot_ed_nmb_vsts'] = pd.to_numeric(df['tot_ed_nmb_vsts'], errors='coerce') - df['ed_stations'] = pd.to_numeric(df['ed_stations'], errors='coerce').replace(0, 0.0001) - - # Calculates burden (# of visits/# of ED stations) + finds the burden average - df['burden_score'] = df['tot_ed_nmb_vsts'] / df['ed_stations'] - avg_burden = df['burden_score'].mean() - - # Identifies + filters high-risk areas, where high risk is defined as a facility being classified as a "mental health shortage area" and the burden score being above-average (namely, higher than the mean burden score for the data set) - df['high_risk'] = ( - (df['mental_health_shortage_area'] == 'Yes') & - (df['burden_score'] > avg_burden) - ) - - # Returns the facilities that are high risk - return df[df['high_risk'] == True] - -result = mental_health_shortage_analysis(df) -print(result) - -""" -Identifies high-risk facilities based on emergency department (ED) burden -and mental health resource shortages. - -A facility is classified as "high risk" if: -1. It is located in a mental health shortage area, AND -2. Its burden score (visits per station) exceeds the average burden - within its group (which in this instance is set to year). - -Parameters: - df (pd.DataFrame): Input dataset - visit_col (str): Column name for total ED visits - station_col (str): Column name for number of ED stations - shortage_col (str): Column indicating shortage status - shortage_value (str): Value indicating a shortage (e.g., "Yes") - group_col (str): Column used to compute group averages (e.g., year) - -Returns: - pd.DataFrame: Subset of the original DataFrame containing only - high-risk facilities, with additional columns: - - burden_score - - avg_burden - - high_risk (boolean) -""" - -def mental_health_shortage_analysis( - df, - visit_col="tot_ed_nmb_vsts", - station_col="ed_stations", - shortage_col="mental_health_shortage_area", - shortage_value="Yes", - group_col="year" -): - - # CALCULATION PREP (1): Convert key columns to numeric - # Ensures calculations work properly and prevents errors - df[visit_col] = pd.to_numeric(df[visit_col], errors="raise") - df[station_col] = pd.to_numeric(df[station_col], errors="raise") - - # CALCULATION PREP (2): Prevent division by zero - # Replace 0 stations with NaN - df[station_col] = df[station_col].replace(0, np.nan) - - # TYPE CHECKING: Ensure columns are numeric - if not np.issubdtype(df[visit_col].dtype, np.number): - raise TypeError(f"{visit_col} must be numeric") - if not np.issubdtype(df[station_col].dtype, np.number): - raise TypeError(f"{station_col} must be numeric") - - # BURDEN SCORE: ED visits per station - df["burden_score"] = df[visit_col] / df[station_col] - - # GROUP BENCHMARK: Average burden within group (e.g., year) - df["avg_burden"] = df.groupby(group_col)["burden_score"].transform("mean") - - # HIGH-RISK FLAG: - # 1. In mental health shortage area - # 2. Burden above group average - df["high_risk"] = ( - (df[shortage_col] == shortage_value) & - (df["burden_score"] > df["avg_burden"]) - ) - - # Returns the facilities that are high risk - return df[df['high_risk'] == True] \ No newline at end of file From 94ad881370b3f49559ad1ce192c3db51fc7c0ca1 Mon Sep 17 00:00:00 2001 From: Sarah Kota Date: Tue, 28 Apr 2026 16:45:02 -0400 Subject: [PATCH 04/11] cleaning up unnecessary functions from stats_analysis.py --- src/ertimes/stats_analysis.py | 110 ---------------------------------- 1 file changed, 110 deletions(-) diff --git a/src/ertimes/stats_analysis.py b/src/ertimes/stats_analysis.py index d1b8a3c..48b7367 100644 --- a/src/ertimes/stats_analysis.py +++ b/src/ertimes/stats_analysis.py @@ -439,100 +439,6 @@ def spike_frequency_pivot( return pivot -# Census data functions -CENSUS_API_KEY = os.getenv("CENSUS_API_KEY", "YOUR_API_KEY_HERE") -ACS_YEAR = 2024 -TABLE_ID = "S1903" -BASE_URL = f"https://api.census.gov/data/{ACS_YEAR}/acs/acs5" - - -def get_census_data_for_zipcode() -> pd.DataFrame | None: - """ - Fetch California median household income data by zip code from the Census API. - """ - if CENSUS_API_KEY == "YOUR_API_KEY_HERE": - print("Error: Census API key not set!") - print("Get a free API key at: https://api.census.gov/data/key_signup.html") - print("Then set it with: export CENSUS_API_KEY='your_key_here'") - return None - - variables = "S1903_C03_001E,NAME" - params = { - "get": variables, - "for": "zip code tabulation area:*", - "in": "state:06", - "key": CENSUS_API_KEY, - } - - try: - response = requests.get(BASE_URL, params=params) - response.raise_for_status() - data = response.json() - - if len(data) < 2: - print("No data returned from Census Bureau API") - return None - - headers = data[0] - rows = data[1:] - df = pd.DataFrame(rows, columns=headers) - - df = df.rename( - columns={ - "S1903_C03_001E": "median_income", - "NAME": "name", - "zip code tabulation area": "zip_code", - } - ) - - df["median_income"] = pd.to_numeric(df["median_income"], errors="coerce") - df = df[df["median_income"].notna()].copy() - - df["county"] = df["name"].str.extract( - r",\\s*([A-Za-z\\s]+)\\s+County,\\s+California", - expand=False, - ) - df["city"] = df["name"].str.extract(r"^(.*?),", expand=False) - - df = df[["zip_code", "median_income", "county", "city"]].copy() - df["median_income"] = df["median_income"].astype(int) - - return df - - except requests.exceptions.RequestException as e: - print(f"Error fetching data from Census API: {e}") - return None - except Exception as e: - print(f"Error processing Census data: {e}") - return None - - -def save_to_csv( - df: pd.DataFrame, - output_path: str = "data/california_median_income_by_zipcode.csv", -) -> None: - """ - Save the census data to a CSV file. - """ - Path(output_path).parent.mkdir(parents=True, exist_ok=True) - df.to_csv(output_path, index=False) - - -def display_statistics(df: pd.DataFrame) -> None: - """ - Display basic statistics about the income data. - """ - print("\\n" + "=" * 70) - print("CALIFORNIA MEDIAN INCOME STATISTICS") - print("=" * 70) - print(f"Total zip codes: {len(df)}") - print(f"Mean median income: ${df['median_income'].mean():,.2f}") - print(f"Median income: ${df['median_income'].median():,.2f}") - print(f"Min income: ${df['median_income'].min():,}") - print(f"Max income: ${df['median_income'].max():,}") - print(f"Counties: {df['county'].nunique()}") - print("=" * 70 + "\\n") - def load_california_income_data(filepath: Optional[str] = None) -> pd.DataFrame: """ @@ -652,19 +558,3 @@ def filter_by_income_range( (df["median_income"] >= min_income) & (df["median_income"] <= max_income) ].copy() - - -def display_income_summary(df: pd.DataFrame) -> None: - """ - Print a formatted summary of income data. - """ - print("\\n" + "=" * 60) - print("CALIFORNIA MEDIAN INCOME SUMMARY") - print("=" * 60) - print(f"Total zip codes: {len(df)}") - print(f"Mean income: ${df['median_income'].mean():,.2f}") - print(f"Median income: ${df['median_income'].median():,.2f}") - print(f"Min income: ${df['median_income'].min():,}") - print(f"Max income: ${df['median_income'].max():,}") - print(f"Counties: {df['county'].nunique()}") - print("=" * 60 + "\\n") \ No newline at end of file From ad757e795aa8e7327a4e4ecadd6efc82a73ec060 Mon Sep 17 00:00:00 2001 From: Sarah Kota Date: Tue, 28 Apr 2026 16:50:42 -0400 Subject: [PATCH 05/11] cleaning up modules --- src/ertimes/demographics.py | 46 ++++++++++++++++++++++++++++++++++- src/ertimes/stats_analysis.py | 45 ---------------------------------- tests/test_stats.py | 8 +++--- 3 files changed, 49 insertions(+), 50 deletions(-) diff --git a/src/ertimes/demographics.py b/src/ertimes/demographics.py index 18f6f93..01f6301 100644 --- a/src/ertimes/demographics.py +++ b/src/ertimes/demographics.py @@ -3,6 +3,7 @@ from pathlib import Path import pandas as pd +from typing import Optional DATA_URLS = { @@ -358,4 +359,47 @@ def merge_datasets(hospital_filepath: str | Path) -> pd.DataFrame: Prefer merge_with_demographics in new code. """ - return merge_with_demographics(hospital_filepath) \ No newline at end of file + return merge_with_demographics(hospital_filepath) + +def filter_by_income_range( + df: pd.DataFrame, + min_income: float, + max_income: float, +) -> pd.DataFrame: + """ + Filter zip codes by median income range. + """ + return df[ + (df["median_income"] >= min_income) + & (df["median_income"] <= max_income) + ].copy() + +def get_income_statistics( + df: pd.DataFrame, + group_by: Optional[str] = None, +) -> pd.DataFrame: + """ + Calculate median income statistics overall or by county/city. + """ + if group_by: + stats = df.groupby(group_by)["median_income"].agg( + [ + ("mean_income", "mean"), + ("median_income", "median"), + ("min_income", "min"), + ("max_income", "max"), + ("count", "count"), + ] + ).round(2) + else: + stats = pd.DataFrame( + { + "mean_income": [df["median_income"].mean()], + "median_income": [df["median_income"].median()], + "min_income": [df["median_income"].min()], + "max_income": [df["median_income"].max()], + "count": [len(df)], + } + ).round(2) + + return stats \ No newline at end of file diff --git a/src/ertimes/stats_analysis.py b/src/ertimes/stats_analysis.py index 48b7367..d7f08f7 100644 --- a/src/ertimes/stats_analysis.py +++ b/src/ertimes/stats_analysis.py @@ -513,48 +513,3 @@ def get_income_by_county(df: pd.DataFrame, county: str) -> pd.DataFrame: Get median income data for all zip codes in a county. """ return df[df["county"].str.lower() == county.lower()].copy() - - -def get_income_statistics( - df: pd.DataFrame, - group_by: Optional[str] = None, -) -> pd.DataFrame: - """ - Calculate median income statistics overall or by county/city. - """ - if group_by: - stats = df.groupby(group_by)["median_income"].agg( - [ - ("mean_income", "mean"), - ("median_income", "median"), - ("min_income", "min"), - ("max_income", "max"), - ("count", "count"), - ] - ).round(2) - else: - stats = pd.DataFrame( - { - "mean_income": [df["median_income"].mean()], - "median_income": [df["median_income"].median()], - "min_income": [df["median_income"].min()], - "max_income": [df["median_income"].max()], - "count": [len(df)], - } - ).round(2) - - return stats - - -def filter_by_income_range( - df: pd.DataFrame, - min_income: float, - max_income: float, -) -> pd.DataFrame: - """ - Filter zip codes by median income range. - """ - return df[ - (df["median_income"] >= min_income) - & (df["median_income"] <= max_income) - ].copy() diff --git a/tests/test_stats.py b/tests/test_stats.py index a5a690b..5738053 100644 --- a/tests/test_stats.py +++ b/tests/test_stats.py @@ -11,8 +11,8 @@ # Use this clean import now that 'pip install -e .' worked! from ertimes.io import download_emergency_data -from ertimes.stats_analysis import _bed_size_to_numeric, find_capacity_volume_mismatch, compute_capacity_pressure_score, spike_frequency_pivot, mental_health_shortage_analysis, calculate_growth, county_facility_counts -from ertimes.stats_reports import generate_county_report, per_category_burden_report, summarize_by_ownership, find_duplicates +from ertimes.stats_analysis import find_capacity_volume_mismatch, compute_capacity_pressure_score, spike_frequency_pivot, mental_health_shortage_analysis +from ertimes.stats_reports import generate_county_report, summarize_by_ownership from ertimes.stats_ranking import rank_counties_by_burden, rank_hospitals_by_visits_per_station from ertimes.stats_visualization import plot_facility_trend, plot_urban_rural_map @@ -412,8 +412,8 @@ def test_generate_county_report_missing_county(): #Median_Income Tests -from ertimes.stats_analysis import load_california_income_data, get_income_by_zip, get_income_statistics - +from ertimes.stats_analysis import load_california_income_data, get_income_by_zip +from ertimes.demographics import get_income_statistics def test_load_california_income_data(): # Test loading data from a valid file From 81aa683251fd26e177b557ee0b57e718ad4764b4 Mon Sep 17 00:00:00 2001 From: Sarah Kota Date: Tue, 28 Apr 2026 16:56:25 -0400 Subject: [PATCH 06/11] adding more pytests --- tests/test_stats.py | 103 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/tests/test_stats.py b/tests/test_stats.py index 5738053..9da6018 100644 --- a/tests/test_stats.py +++ b/tests/test_stats.py @@ -986,4 +986,105 @@ def test_calculate_growth_percent_multiple_groups(): # Group 2 expectations assert np.isnan(result.loc[(result["oshpd_id"] == 2) & (result["year"] == 2020), "growth"].iloc[0]) - assert result.loc[(result["oshpd_id"] == 2) & (result["year"] == 2021), "growth"].iloc[0] == -50 \ No newline at end of file + assert result.loc[(result["oshpd_id"] == 2) & (result["year"] == 2021), "growth"].iloc[0] == -50 + +def test_rank_counties_by_burden_bad_input_type(): + """rank_counties_by_burden should raise TypeError for non-DataFrame input.""" + with pytest.raises(TypeError, match="summary must be a pandas DataFrame"): + rank_counties_by_burden([1, 2, 3]) + + +def test_rank_counties_by_burden_custom_visits_column(): + """rank_counties_by_burden should support a custom burden column name.""" + summary = pd.DataFrame({ + "county": ["A", "B", "C"], + "burden": [5, 15, 10], + }) + + result = rank_counties_by_burden(summary, visits_col="burden") + + assert list(result["county"]) == ["B", "C", "A"] + + +def test_rank_counties_by_burden_resets_index(): + """rank_counties_by_burden should reset the index after sorting.""" + summary = pd.DataFrame({ + "county": ["A", "B", "C"], + "visits_per_station": [5, 15, 10], + }, index=[10, 20, 30]) + + result = rank_counties_by_burden(summary) + + assert list(result.index) == [0, 1, 2] + + +def test_rank_hospitals_by_visits_per_station_bad_input_type(): + """rank_hospitals_by_visits_per_station should raise TypeError for non-DataFrame input.""" + with pytest.raises(TypeError, match="df must be a pandas DataFrame"): + rank_hospitals_by_visits_per_station([1, 2, 3]) + + +def test_rank_hospitals_by_visits_per_station_invalid_agg(): + """rank_hospitals_by_visits_per_station should reject unsupported aggregation methods.""" + df = pd.DataFrame({ + "facility_name": ["A", "B"], + "visits_per_station": [10, 20], + }) + + with pytest.raises(ValueError, match="agg must be 'mean' or 'median'"): + rank_hospitals_by_visits_per_station(df, agg="sum") + + +def test_rank_hospitals_by_visits_per_station_negative_top_n(): + """rank_hospitals_by_visits_per_station should reject negative top_n values.""" + df = pd.DataFrame({ + "facility_name": ["A", "B"], + "visits_per_station": [10, 20], + }) + + with pytest.raises(ValueError, match="top_n must be nonnegative"): + rank_hospitals_by_visits_per_station(df, top_n=-1) + + +def test_rank_hospitals_by_visits_per_station_numeric_coercion(): + """String numeric values should be coerced before ranking.""" + df = pd.DataFrame({ + "facility_name": ["A", "B", "C"], + "visits_per_station": ["10", "30", "20"], + }) + + result = rank_hospitals_by_visits_per_station(df) + + assert list(result["facility_name"]) == ["B", "C", "A"] + assert pd.api.types.is_numeric_dtype(result["visits_per_station"]) + + +def test_rank_hospitals_by_visits_per_station_custom_columns(): + """Function should support custom facility and visits column names.""" + df = pd.DataFrame({ + "Hospital": ["A", "A", "B"], + "Burden": [10, 30, 50], + }) + + result = rank_hospitals_by_visits_per_station( + df, + facility_col="Hospital", + visits_col="Burden", + agg="mean", + ) + + assert list(result["Hospital"]) == ["B", "A"] + assert result.loc[0, "Burden"] == 50 + + +def test_rank_hospitals_by_visits_per_station_top_n_zero(): + """top_n=0 should return an empty DataFrame with the expected columns.""" + df = pd.DataFrame({ + "facility_name": ["A", "B"], + "visits_per_station": [10, 20], + }) + + result = rank_hospitals_by_visits_per_station(df, top_n=0) + + assert result.empty + assert list(result.columns) == ["facility_name", "visits_per_station"] \ No newline at end of file From 420dbd8edce0022b976f60159f996e64d6a966fa Mon Sep 17 00:00:00 2001 From: Sarah Kota Date: Tue, 28 Apr 2026 16:57:38 -0400 Subject: [PATCH 07/11] more pytests for stats visualization module --- tests/test_stats.py | 181 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 180 insertions(+), 1 deletion(-) diff --git a/tests/test_stats.py b/tests/test_stats.py index 9da6018..e34d602 100644 --- a/tests/test_stats.py +++ b/tests/test_stats.py @@ -1087,4 +1087,183 @@ def test_rank_hospitals_by_visits_per_station_top_n_zero(): result = rank_hospitals_by_visits_per_station(df, top_n=0) assert result.empty - assert list(result.columns) == ["facility_name", "visits_per_station"] \ No newline at end of file + assert list(result.columns) == ["facility_name", "visits_per_station"] + +from ertimes.stats_visualization import ( + plot_hospital_load_distribution, + year_range, + create_ed_map, + plot_category_visits_by_facility, +) + + +def test_plot_hospital_load_distribution_returns_figure(): + """plot_hospital_load_distribution should return a matplotlib Figure.""" + df = pd.DataFrame({ + "Tot_ED_NmbVsts": [100, 200, 300], + "EDStations": [10, 20, 30], + }) + + fig = plot_hospital_load_distribution(df) + + assert fig is not None + assert hasattr(fig, "savefig") + + +def test_plot_hospital_load_distribution_missing_columns(): + """plot_hospital_load_distribution should raise ValueError when required columns are missing.""" + df = pd.DataFrame({ + "Tot_ED_NmbVsts": [100, 200], + }) + + with pytest.raises(ValueError, match="Missing required columns"): + plot_hospital_load_distribution(df) + + +def test_plot_hospital_load_distribution_bad_input_type(): + """plot_hospital_load_distribution should raise TypeError for non-DataFrame input.""" + with pytest.raises(TypeError, match="df must be a pandas DataFrame"): + plot_hospital_load_distribution([1, 2, 3]) + + +def test_plot_hospital_load_distribution_save_path(tmp_path): + """plot_hospital_load_distribution should save a figure when save_path is provided.""" + df = pd.DataFrame({ + "Tot_ED_NmbVsts": [100, 200, 300], + "EDStations": [10, 20, 30], + }) + output_path = tmp_path / "load_distribution.png" + + fig = plot_hospital_load_distribution(df, save_path=str(output_path)) + + assert fig is not None + assert output_path.exists() + + +def test_year_range_basic(tmp_path): + """year_range should return the minimum and maximum valid year from a CSV.""" + csv_path = tmp_path / "years.csv" + pd.DataFrame({ + "year": [2020, 2021, 2023], + "value": [1, 2, 3], + }).to_csv(csv_path, index=False) + + assert year_range(str(csv_path)) == (2020, 2023) + + +def test_year_range_missing_year_column(tmp_path): + """year_range should raise ValueError when the CSV has no year column.""" + csv_path = tmp_path / "no_year.csv" + pd.DataFrame({ + "value": [1, 2, 3], + }).to_csv(csv_path, index=False) + + with pytest.raises(ValueError, match="year"): + year_range(str(csv_path)) + + +def test_year_range_no_valid_year_values(tmp_path): + """year_range should raise ValueError when year column has no valid numeric values.""" + csv_path = tmp_path / "bad_years.csv" + pd.DataFrame({ + "year": ["bad", None, "unknown"], + }).to_csv(csv_path, index=False) + + with pytest.raises(ValueError, match="valid year"): + year_range(str(csv_path)) + + +def test_plot_facility_trend_bad_input_type(): + """plot_facility_trend should raise TypeError for non-DataFrame input.""" + with pytest.raises(TypeError, match="df must be a pandas DataFrame"): + plot_facility_trend([1, 2, 3], "A") + + +def test_plot_urban_rural_map_missing_coordinate_rows(monkeypatch): + """plot_urban_rural_map should raise ValueError when no valid coordinates remain.""" + fake_df = pd.DataFrame({ + "LATITUDE": [None, None], + "LONGITUDE": [None, None], + "UrbanRuralDesi": ["Urban", "Rural"], + "FacilityName2": ["A", "B"], + }) + + def fake_download(state): + return fake_df + + monkeypatch.setattr("ertimes.stats_analysis.download_emergency_data", fake_download) + + with pytest.raises(ValueError, match="No valid latitude/longitude"): + plot_urban_rural_map("California") + + +def test_create_ed_map_filters_year(): + """create_ed_map should return a Plotly figure for the requested year.""" + df = pd.DataFrame({ + "year": [2020, 2021], + "latitude": [34.1, 35.2], + "longitude": [-118.2, -119.3], + "total_ed_visits": [100, 200], + "primary_care_shortage": ["Yes", "No"], + "mental_health_shortage": ["No", "Yes"], + "county": ["A", "B"], + "ed_name": ["Hospital A", "Hospital B"], + }) + + fig = create_ed_map(df, 2021) + + assert fig is not None + assert hasattr(fig, "to_dict") + + +def test_create_ed_map_missing_columns(): + """create_ed_map should raise ValueError when required columns are missing.""" + df = pd.DataFrame({ + "year": [2021], + "latitude": [34.1], + }) + + with pytest.raises(ValueError, match="Missing required columns"): + create_ed_map(df, 2021) + + +def test_create_ed_map_bad_input_type(): + """create_ed_map should raise TypeError for non-DataFrame input.""" + with pytest.raises(TypeError, match="df must be a pandas DataFrame"): + create_ed_map([1, 2, 3], 2021) + + +def test_plot_category_visits_by_facility_returns_figure(monkeypatch, capsys): + """plot_category_visits_by_facility should return a Figure and print the category summary.""" + monkeypatch.setattr(plt, "show", lambda: None) + + df = pd.DataFrame({ + "facility_name": ["A", "A", "B"], + "category": ["Stroke", "All ED Visits", "Stroke"], + "ed_burden": [20, 999, 40], + }) + + fig = plot_category_visits_by_facility(df, "A") + captured = capsys.readouterr() + + assert fig is not None + assert hasattr(fig, "savefig") + assert "Stroke" in captured.out + assert "All ED Visits" not in captured.out + + +def test_plot_category_visits_by_facility_missing_columns(): + """plot_category_visits_by_facility should raise ValueError if required columns are missing.""" + df = pd.DataFrame({ + "facility_name": ["A"], + "category": ["Stroke"], + }) + + with pytest.raises(ValueError, match="Missing required columns"): + plot_category_visits_by_facility(df, "A") + + +def test_plot_category_visits_bad_input_type(): + """plot_category_visits should raise TypeError for non-DataFrame input.""" + with pytest.raises(TypeError, match="df must be a pandas DataFrame"): + plot_category_visits([1, 2, 3]) \ No newline at end of file From 6307c7aa2acfa3398dc012600dc93ad201e1eb62 Mon Sep 17 00:00:00 2001 From: Sarah Kota Date: Tue, 28 Apr 2026 17:03:54 -0400 Subject: [PATCH 08/11] added a lot of demos and more functions to run_demo.py to output some of the work of our functions --- .../california_emergency_data_sample.csv | 101 + demo_outputs/category_visits_plot.png | Bin 0 -> 44768 bytes .../facility_category_visits_plot.png | Bin 0 -> 46449 bytes demo_outputs/facility_trend.png | Bin 0 -> 34424 bytes demo_outputs/hospital_load_distribution.png | Bin 0 -> 20170 bytes demo_outputs/urban_rural_map.html | 20545 ++++++++++++++++ run_demo.py | 509 +- 7 files changed, 21102 insertions(+), 53 deletions(-) create mode 100644 demo_outputs/california_emergency_data_sample.csv create mode 100644 demo_outputs/category_visits_plot.png create mode 100644 demo_outputs/facility_category_visits_plot.png create mode 100644 demo_outputs/facility_trend.png create mode 100644 demo_outputs/hospital_load_distribution.png create mode 100644 demo_outputs/urban_rural_map.html diff --git a/demo_outputs/california_emergency_data_sample.csv b/demo_outputs/california_emergency_data_sample.csv new file mode 100644 index 0000000..3b896c2 --- /dev/null +++ b/demo_outputs/california_emergency_data_sample.csv @@ -0,0 +1,101 @@ +facility_id,facility_name,county_name,hospital_system,year,licensed_bed_size,hospital_ownership,urban_rural_designation,teaching_designation,category,total_ed_visits,ed_stations,ed_burden,latitude,longitude,primary_care_shortage_area,mental_health_shortage_area,visits_per_station +106010735,Alameda Hospital,Alameda,Alameda Health System,2022,100-149,Government,Urban,Non-Teaching,Active COVID-19,13579,12.0,520,37.76266,-122.253991,No,No,43.3333333333333 +106010739,Alta Bates Summit Medical Center – Alta Bates Campus,Alameda,Sutter Health,2022,300-499,Nonprofit,Urban,Non-Teaching,Active COVID-19,29760,22.0,1177,37.85645,-122.25743,No,No,53.5 +106010776,UC San Francisco Benioff Children's Hospital Oakland,Alameda,,2022,150-199,Nonprofit,Urban,Teaching,Active COVID-19,35062,40.0,1822,37.83722,-122.26747,No,No,45.55 +106010846,Highland Hospital,Alameda,Alameda Health System,2022,200-299,Government,Urban,Non-Teaching,Active COVID-19,66095,53.0,2109,37.79925,-122.23138,No,No,39.7924528301887 +106010937,Alta Bates Summit Medical Center,Alameda,Sutter Health,2022,300-499,Nonprofit,Urban,Non-Teaching,Active COVID-19,29336,30.0,1325,37.82106,-122.26257,No,No,44.1666666666667 +106010987,Washington Hospital – Fremont,Alameda,,2022,300-499,Government,Urban,Non-Teaching,Active COVID-19,43964,39.0,3013,37.55847,-121.98006,No,No,77.2564102564103 +106014050,Stanford Health Care Tri-Valley,Alameda,,2022,150-199,Nonprofit,Urban,Non-Teaching,Active COVID-19,28620,17.0,1378,37.69206,-121.88095,No,No,81.0588235294118 +106014132,Kaiser Foundation Hospital – Fremont,Alameda,Kaiser Foundation Hospitals,2022,100-149,Nonprofit,Urban,Non-Teaching,Active COVID-19,38960,18.0,1487,37.55055,-121.97483,No,No,82.6111111111111 +106014233,Eden Medical Center,Alameda,Sutter Health,2022,100-149,Nonprofit,Urban,Non-Teaching,Active COVID-19,31062,22.0,1467,37.6983769,-122.0874055,No,No,66.6818181818182 +106014326,Kaiser Foundation Hospital – Oakland/Richmond,Alameda,Kaiser Foundation Hospitals,2022,300-499,Nonprofit,Urban,Non-Teaching,Active COVID-19,120088,80.0,4883,37.82402,-122.25791,No,No,61.0375 +106014337,Kaiser Foundation Hospital – San Leandro,Alameda,Kaiser Foundation Hospitals,2022,200-299,Nonprofit,Urban,Non-Teaching,Active COVID-19,69343,40.0,2893,37.70611,-122.16917,No,No,72.325 +106034002,Sutter Amador Hospital,Amador,Sutter Health,2022,50-99,Nonprofit,Rural,Non-Teaching,Active COVID-19,24996,14.0,1392,38.34743,-120.77272,Yes,No,99.4285714285714 +106040802,Orchard Hospital,Butte,,2022,100-149,Nonprofit,Rural,Non-Teaching,Active COVID-19,10325,5.0,366,39.36701,-121.68955,Yes,Yes,73.2 +106040937,Oroville Hospital,Butte,,2022,100-149,Nonprofit,Rural,Non-Teaching,Active COVID-19,9329,14.0,377,39.50485,-121.5428,Yes,Yes,26.9285714285714 +106040962,Enloe Medical Center– Esplanade,Butte,,2022,200-299,Nonprofit,Urban,Non-Teaching,Active COVID-19,56376,50.0,1902,39.74226,-121.84918,No,Yes,38.04 +106050932,Mark Twain Medical Center,Calaveras,Dignity Health,2022,1-49,Nonprofit,Rural,Non-Teaching,Active COVID-19,10190,8.0,497,38.19057,-120.67095,Yes,Yes,62.125 +106070934,Sutter Delta Medical Center,Contra Costa,Sutter Health,2022,100-149,Nonprofit,Urban,Non-Teaching,Active COVID-19,41182,30.0,2082,37.98222,-121.8054,No,No,69.4 +106070988,John Muir Medical Center – Walnut Creek Campus,Contra Costa,John Muir Health,2022,500+,Nonprofit,Urban,Non-Teaching,Active COVID-19,47848,44.0,2205,37.91304,-122.040781,No,No,50.1136363636364 +106070990,Kaiser Foundation Hospital – Walnut Creek,Contra Costa,Kaiser Foundation Hospitals,2022,200-299,Nonprofit,Urban,Non-Teaching,Active COVID-19,65573,52.0,3007,37.8923,-122.05828,No,No,57.8269230769231 +106071018,John Muir Medical Center – Concord Campus,Contra Costa,John Muir Health,2022,200-299,Nonprofit,Urban,Non-Teaching,Active COVID-19,52369,32.0,2404,37.98615,-122.03874,No,No,75.125 +106074017,San Ramon Regional Medical Center,Contra Costa,Tenet Healthcare Corporation,2022,100-149,Investor Owned,Urban,Non-Teaching,Active COVID-19,18054,12.0,1009,37.77549,-121.95884,No,No,84.0833333333333 +106074097,Kaiser Foundation Hospital – Antioch,Contra Costa,Kaiser Foundation Hospitals,2022,150-199,Nonprofit,Urban,Non-Teaching,Active COVID-19,66644,36.0,3385,37.951975,-121.776854,No,No,94.0277777777778 +106090793,Barton Memorial Hospital,El Dorado,,2022,100-149,Nonprofit,Rural,Non-Teaching,Active COVID-19,17483,12.0,596,38.91228,-119.99758,Yes,Yes,49.6666666666667 +106100005,Clovis Community Medical Center,Fresno,,2022,300-499,Nonprofit,Rural,Non-Teaching,Active COVID-19,56532,59.0,2051,36.83745,-119.66072,Yes,Yes,34.7627118644068 +106100697,Coalinga Regional Medical Center,Fresno,,2022,100-149,Investor Owned,Rural,Non-Teaching,Active COVID-19,8870,9.0,361,36.15152,-120.34035,Yes,Yes,40.1111111111111 +106100717,Community Regional Medical Center – Fresno,Fresno,,2022,500+,Nonprofit,Urban,Teaching,Active COVID-19,84815,73.0,2960,36.74252,-119.784071,Yes,No,40.5479452054795 +106100797,Adventist Health Reedley,Fresno,Adventist Health Systems,2022,1-49,Nonprofit,Rural,Non-Teaching,Active COVID-19,38319,10.0,2518,36.60789,-119.45145,Yes,Yes,251.8 +106100899,Saint Agnes Medical Center,Fresno,,2022,300-499,Nonprofit,Urban,Non-Teaching,Active COVID-19,58162,48.0,2182,36.8370782,-119.7649963,No,Yes,45.4583333333333 +106104062,Kaiser Foundation Hospital – Fresno,Fresno,Kaiser Foundation Hospitals,2022,150-199,Nonprofit,Urban,Non-Teaching,Active COVID-19,49785,21.0,2289,36.84246,-119.7832,No,Yes,109.0 +106110889,Glenn Medical Center,Glenn,,2022,1-49,Investor Owned,Frontier,Non-Teaching,Active COVID-19,6404,4.0,177,39.52055,-122.20791,Yes,Yes,44.25 +106121051,Providence Redwood Memorial Hospital,Humboldt,Providence St. Joseph Health,2022,1-49,Investor Owned,Rural,Non-Teaching,Active COVID-19,10531,8.0,353,40.58267,-124.13549,Yes,Yes,44.125 +106121080,Providence St. Joseph Hospital – Eureka,Humboldt,Providence St. Joseph Health,2022,100-149,Investor Owned,Rural,Non-Teaching,Active COVID-19,27953,20.0,882,40.7832,-124.14216,Yes,Yes,44.1 +106130760,Pioneers Memorial Healthcare District,Imperial,,2022,100-149,Government,Rural,Non-Teaching,Active COVID-19,42926,16.0,2435,32.96003,-115.55183,Yes,Yes,152.1875 +106141273,Northern Inyo Hospital,Inyo,,2022,1-49,Government,Rural,Non-Teaching,Active COVID-19,8301,8.0,368,37.36207,-118.40756,No,No,46.0 +106141338,Southern Inyo Hospital,Inyo,,2022,1-49,Government,Frontier,Non-Teaching,Active COVID-19,1668,2.0,63,36.6084,-118.05816,Yes,No,31.5 +106150706,Adventist Health Delano,Kern,,2022,150-199,Nonprofit,Urban,Non-Teaching,Active COVID-19,28475,10.0,945,35.76143,-119.23706,Yes,Yes,94.5 +106150737,Kern Valley Healthcare District,Kern,,2022,100-149,Government,Frontier,Non-Teaching,Active COVID-19,6607,8.0,280,35.63486,-118.40509,Yes,Yes,35.0 +106150761,Mercy Hospital – Bakersfield,Kern,Dignity Health,2022,100-149,Nonprofit,Urban,Non-Teaching,Active COVID-19,62403,45.0,2746,35.37323,-119.02715,No,Yes,61.0222222222222 +106150782,Ridgecrest Regional Hospital,Kern,,2022,50-99,Nonprofit,Rural,Non-Teaching,Active COVID-19,16279,12.0,738,35.6404,-117.66996,Yes,Yes,61.5 +106154168,Adventist Health Tehachapi Valley,Kern,Adventist Health Systems,2022,1-49,Nonprofit,Rural,Non-Teaching,Active COVID-19,21135,13.0,1130,35.14302,-118.44924,Yes,Yes,86.9230769230769 +106164029,Adventist Health Hanford,Kings,Adventist Health Systems,2022,150-199,Nonprofit,Urban,Non-Teaching,Active COVID-19,92128,44.0,4787,36.3256247,-119.6683912,Yes,Yes,108.795454545455 +106171049,Adventist Health Clearlake,Lake,Adventist Health Systems,2022,1-49,Nonprofit,Rural,Non-Teaching,Active COVID-19,19592,8.0,771,38.93619,-122.6202,Yes,Yes,96.375 +106171395,Sutter Lakeside Hospital,Lake,Sutter Health,2022,1-49,Nonprofit,Rural,Non-Teaching,Active COVID-19,19410,12.0,868,39.10232,-122.91003,Yes,Yes,72.3333333333333 +106184008,Banner Lassen Medical Center,Lassen,,2022,1-49,Nonprofit,Rural,Non-Teaching,Active COVID-19,10145,8.0,436,40.42306,-120.64609,Yes,Yes,54.5 +106190017,Alhambra Hospital Medical Center,Los Angeles,,2022,100-149,Investor Owned,Urban,Non-Teaching,Active COVID-19,16020,8.0,802,34.08988,-118.1449,No,No,100.25 +106190034,Antelope Valley Hospital,Los Angeles,,2022,300-499,Government,Urban,Non-Teaching,Active COVID-19,107707,45.0,4604,34.6878,-118.157981,No,Yes,102.311111111111 +106190053,St. Mary Medical Center – Long Beach,Los Angeles,Dignity Health,2022,300-499,Nonprofit,Urban,Non-Teaching,Active COVID-19,37582,26.0,1223,33.7802376,-118.1866412,No,No,47.0384615384615 +106190110,Southern California Hospital at Culver City,Los Angeles,Alta Hospitals System,2022,300-499,Investor Owned,Urban,Non-Teaching,Active COVID-19,12830,17.0,436,34.0231953,-118.3969429,No,No,25.6470588235294 +106190125,California Hospital Medical Center – Los Angeles,Los Angeles,Dignity Health,2022,300-499,Nonprofit,Urban,Non-Teaching,Active COVID-19,57917,35.0,1411,34.03721,-118.26551,No,No,40.3142857142857 +106190148,Centinela Hospital Medical Center,Los Angeles,Prime Healthcare Services,2022,300-499,Investor Owned,Urban,Non-Teaching,Active COVID-19,35849,50.0,712,33.94917,-118.34788,Yes,No,14.24 +106190170,Children's Hospital of Los Angeles,Los Angeles,,2022,300-499,Nonprofit,Urban,Teaching,Active COVID-19,68844,46.0,1716,34.0978692,-118.2909547,Yes,No,37.304347826087 +106190197,Community Hospital of Huntington Park,Los Angeles,Avanti Hospitals,2022,50-99,Investor Owned,Urban,Non-Teaching,Active COVID-19,31164,14.0,388,33.98929,-118.22466,No,Yes,27.7142857142857 +106190198,Los Angeles Community Hospital,Los Angeles,Alta Hospitals System,2022,100-149,Investor Owned,Urban,Non-Teaching,Active COVID-19,3857,4.0,71,34.01897,-118.1875,Yes,Yes,17.75 +106190200,San Gabriel Valley Medical Center,Los Angeles,"AHMC Healthcare, Inc.",2022,200-299,Investor Owned,Urban,Non-Teaching,Active COVID-19,21304,12.0,800,34.1024,-118.10503,No,No,66.6666666666667 +106190240,Lakewood Regional Medical Center,Los Angeles,Tenet Healthcare Corporation,2022,150-199,Investor Owned,Urban,Non-Teaching,Active COVID-19,34069,14.0,1077,33.859731,-118.1492012,No,No,76.9285714285714 +106190243,PIH Health Hospital – Downey,Los Angeles,,2022,150-199,Nonprofit,Urban,Non-Teaching,Active COVID-19,48690,26.0,1557,33.93515,-118.13196,No,No,59.8846153846154 +106190256,East Los Angeles Doctors Hospital,Los Angeles,Avanti Hospitals,2022,100-149,Investor Owned,Urban,Non-Teaching,Active COVID-19,10400,8.0,251,34.02383,-118.18377,Yes,Yes,31.375 +106190280,Encino Hospital Medical Center,Los Angeles,Prime Healthcare Services,2022,100-149,Investor Owned,Urban,Non-Teaching,Active COVID-19,6940,9.0,183,34.15686,-118.48662,No,No,20.3333333333333 +106190315,Garfield Medical Center,Los Angeles,"AHMC Healthcare, Inc.",2022,200-299,Investor Owned,Urban,Non-Teaching,Active COVID-19,15968,21.0,629,34.06826,-118.12302,No,No,29.952380952381 +106190323,Adventist Health Glendale,Los Angeles,Adventist Health Systems,2022,500+,Nonprofit,Urban,Non-Teaching,Active COVID-19,37767,39.0,2248,34.14951,-118.23109,No,No,57.6410256410256 +106190352,Greater El Monte Community Hospital,Los Angeles,"AHMC Healthcare, Inc.",2022,100-149,Investor Owned,Urban,Non-Teaching,Active COVID-19,20914,,635,34.04827,-118.04257,Yes,No, +106190385,Providence Holy Cross Medical Center,Los Angeles,Providence St. Joseph Health,2022,300-499,Nonprofit,Urban,Non-Teaching,Active COVID-19,82929,32.0,2956,34.2791,-118.45951,No,No,92.375 +106190422,Torrance Memorial Medical Center,Los Angeles,Cedars-Sinai Health System,2022,500+,Nonprofit,Urban,Non-Teaching,Active COVID-19,71601,29.0,3585,33.8119157,-118.3434945,Yes,No,123.620689655172 +106190429,Kaiser Foundation Hospital – Los Angeles,Los Angeles,Kaiser Foundation Hospitals,2022,300-499,Nonprofit,Urban,Teaching,Active COVID-19,55882,57.0,3477,34.09875,-118.295371,Yes,No,61.0 +106190431,Kaiser Foundation Hospital – South Bay,Los Angeles,Kaiser Foundation Hospitals,2022,200-299,Nonprofit,Urban,Non-Teaching,Active COVID-19,59992,52.0,3467,33.78926,-118.29373,Yes,No,66.6730769230769 +106190432,Kaiser Foundation Hospital – Panorama City,Los Angeles,Kaiser Foundation Hospitals,2022,200-299,Nonprofit,Urban,Non-Teaching,Active COVID-19,62888,41.0,4248,34.2198,-118.43103,No,No,103.609756097561 +106190434,Kaiser Foundation Hospital – West LA,Los Angeles,Kaiser Foundation Hospitals,2022,200-299,Nonprofit,Urban,Non-Teaching,Active COVID-19,80860,53.0,4385,34.03793,-118.37568,No,No,82.7358490566038 +106190470,Providence Little Company of Mary Medical Center – Torrance,Los Angeles,Providence St. Joseph Health,2022,300-499,Nonprofit,Urban,Non-Teaching,Active COVID-19,40497,29.0,2155,33.83891,-118.356771,No,No,74.3103448275862 +106190500,Cedars – Sinai Marina Del Rey Hospital,Los Angeles,Cedars-Sinai Health System,2022,100-149,Nonprofit,Urban,Non-Teaching,Active COVID-19,32685,18.0,1313,33.98125,-118.43971,No,No,72.9444444444444 +106190517,Providence Cedars – Sinai Tarzana Medical Center,Los Angeles,Providence St. Joseph Health,2022,200-299,Investor Owned,Urban,Non-Teaching,Active COVID-19,40962,15.0,2034,34.17067,-118.532001,No,No,135.6 +106190521,Memorial Hospital of Gardena,Los Angeles,Avanti Hospitals,2022,150-199,Investor Owned,Urban,Non-Teaching,Active COVID-19,29497,10.0,389,33.89246,-118.29493,Yes,No,38.9 +106190525,MemorialCare Long Beach Medical Center,Los Angeles,MemorialCare,2022,300-499,Nonprofit,Urban,Teaching,Active COVID-19,72326,64.0,4344,33.80801,-118.1852,No,No,67.875 +106190529,USC Arcadia Hospital,Los Angeles,,2022,300-499,Nonprofit,Urban,Non-Teaching,Active COVID-19,35962,26.0,1638,34.13603,-118.03879,No,No,63.0 +106190547,Monterey Park Hospital,Los Angeles,"AHMC Healthcare, Inc.",2022,100-149,Investor Owned,Urban,Non-Teaching,Active COVID-19,16386,6.0,471,34.05308,-118.13665,No,No,78.5 +106190555,Cedars – Sinai Medical Center,Los Angeles,Cedars-Sinai Health System,2022,500+,Nonprofit,Urban,Teaching,Active COVID-19,54587,60.0,2303,34.07681,-118.38061,No,No,38.3833333333333 +106190568,Northridge Hospital Medical Center,Los Angeles,Dignity Health,2022,300-499,Nonprofit,Urban,Non-Teaching,Active COVID-19,47234,37.0,2174,34.22075,-118.53186,No,No,58.7567567567568 +106190570,Norwalk Community Hospital,Los Angeles,Alta Hospitals System,2022,50-99,Investor Owned,Urban,Non-Teaching,Active COVID-19,5026,4.0,163,33.91108,-118.0644,No,No,40.75 +106190587,College Medical Center,Los Angeles,,2022,100-149,Investor Owned,Urban,Non-Teaching,Active COVID-19,6654,7.0,174,33.80759,-118.19355,No,No,24.8571428571429 +106190630,Pomona Valley Hospital Medical Center,Los Angeles,,2022,300-499,Nonprofit,Urban,Non-Teaching,Active COVID-19,78066,72.0,4775,34.07709,-117.750621,No,No,66.3194444444444 +106190631,PIH Health Hospital – Whittier,Los Angeles,,2022,500+,Nonprofit,Urban,Non-Teaching,Active COVID-19,58298,61.0,2422,33.9697943,-118.049255,No,No,39.7049180327869 +106190673,San Dimas Community Hospital,Los Angeles,Prime Healthcare Services,2022,100-149,Investor Owned,Urban,Non-Teaching,Active COVID-19,12256,8.0,417,34.099076,-117.834328,No,No,52.125 +106190680,Providence Little Company of Mary Medical Center – San Pedro,Los Angeles,Providence St. Joseph Health,2022,200-299,Nonprofit,Urban,Non-Teaching,Active COVID-19,33407,16.0,1674,33.737939,-118.303893,No,No,104.625 +106190687,Santa Monica – UCLA Medical Center and Orthopaedic Hospital,Los Angeles,University of California,2022,200-299,Government,Urban,Non-Teaching,Active COVID-19,33209,21.0,1381,34.027539,-118.486123,No,No,65.7619047619048 +106190696,Pacifica Hospital of the Valley,Los Angeles,,2022,200-299,Investor Owned,Urban,Non-Teaching,Active COVID-19,6908,7.0,186,34.24088,-118.39555,Yes,No,26.5714285714286 +106190708,Sherman Oaks Hospital,Los Angeles,Prime Healthcare Services,2022,150-199,Nonprofit,Urban,Non-Teaching,Active COVID-19,18208,12.0,423,34.15995,-118.4488,No,No,35.25 +106190754,St. Francis Medical Center,Los Angeles,Verity Health System,2022,300-499,Investor Owned,Urban,Non-Teaching,Active COVID-19,48363,42.0,1593,33.93085,-118.20415,Yes,Yes,37.9285714285714 +106190756,Providence Saint John's Health Center,Los Angeles,Providence St. Joseph Health,2022,200-299,Nonprofit,Urban,Non-Teaching,Active COVID-19,24761,27.0,1002,34.029804,-118.478668,No,No,37.1111111111111 +106190758,Providence Saint Joseph Medical Center,Los Angeles,Providence St. Joseph Health,2022,300-499,Nonprofit,Urban,Non-Teaching,Active COVID-19,50489,48.0,2375,34.15486,-118.32655,No,No,49.4791666666667 +106190766,Coast Plaza Hospital,Los Angeles,Avanti Hospitals,2022,100-149,Investor Owned,Urban,Non-Teaching,Active COVID-19,9366,8.0,138,33.91255,-118.09915,No,No,17.25 +106190812,Valley Presbyterian Hospital,Los Angeles,,2022,300-499,Nonprofit,Urban,Non-Teaching,Active COVID-19,44727,30.0,1491,34.19396,-118.4632,No,No,49.7 +106190818,USC Verdugo Hills Hospital,Los Angeles,University of Southern California,2022,150-199,Nonprofit,Urban,Non-Teaching,Active COVID-19,22041,13.0,1265,34.20557,-118.2152,No,No,97.3076923076923 +106190859,West Hills Hospital and Medical Center,Los Angeles,HCA Healthcare Corporation,2022,200-299,Investor Owned,Urban,Non-Teaching,Active COVID-19,46662,30.0,914,34.20337,-118.62939,No,No,30.4666666666667 +106190878,Adventist Health White Memorial,Los Angeles,Adventist Health Systems,2022,300-499,Nonprofit,Urban,Teaching,Active COVID-19,52148,28.0,1607,34.05085,-118.21691,No,No,57.3928571428571 +106190883,Whittier Hospital Medical Center,Los Angeles,"AHMC Healthcare, Inc.",2022,150-199,Investor Owned,Urban,Non-Teaching,Active COVID-19,22499,12.0,760,33.95379,-118.00303,No,No,63.3333333333333 +106190949,Henry Mayo Newhall Hospital,Los Angeles,,2022,300-499,Nonprofit,Urban,Non-Teaching,Active COVID-19,54067,30.0,2380,34.39545,-118.55476,No,No,79.3333333333333 +106191227,Los Angeles County/Harbor – UCLA Medical Center,Los Angeles,County of Los Angeles,2022,300-499,Government,Urban,Teaching,Active COVID-19,77616,73.0,2183,33.83155,-118.29353,Yes,No,29.9041095890411 +106191228,Los Angeles County+USC Medical Center,Los Angeles,County of Los Angeles,2022,500+,Government,Urban,Teaching,Active COVID-19,104935,106.0,1846,34.05982,-118.21031,No,No,17.4150943396226 +106191230,"Martin Luther King, Jr. Community Hospital",Los Angeles,,2022,100-149,Nonprofit,Urban,Teaching,Active COVID-19,99493,29.0,4238,33.92453,-118.2435,Yes,Yes,146.137931034483 +106191231,Los Angeles County Olive View – UCLA Medical Center,Los Angeles,County of Los Angeles,2022,300-499,Government,Urban,Teaching,Active COVID-19,47977,51.0,1112,34.32418,-118.45255,No,No,21.8039215686275 +106191450,Kaiser Foundation Hospital – Woodland Hills,Los Angeles,Kaiser Foundation Hospitals,2022,200-299,Nonprofit,Urban,Non-Teaching,Active COVID-19,40713,36.0,2674,34.17198,-118.58829,No,No,74.2777777777778 diff --git a/demo_outputs/category_visits_plot.png b/demo_outputs/category_visits_plot.png new file mode 100644 index 0000000000000000000000000000000000000000..dfb4e7574155ba7b69c2586d94429ea98770bd1b GIT binary patch literal 44768 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 literal 0 HcmV?d00001 diff --git a/demo_outputs/facility_category_visits_plot.png b/demo_outputs/facility_category_visits_plot.png new file mode 100644 index 0000000000000000000000000000000000000000..117187a078d61e01d7d1f2bdb37018f088ceb6e7 GIT binary patch literal 46449 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 CGur=kgVT6bLh$4 zQ=hZ@^53Kc9#_8m@p|QYxYDHjvzIHI#G%0$#b+?O(+H7e1^bZE&n>gF((KC#N zpgZ8?Fj!6Q4taa&@5l4W^w5V9x+CCT!H*~GfDG*ePhcQ3^dXSp|3Bpa1J6b9VNaHh z`>@}70&%@!sfmASd3kv=Rx!zYW2sq42ak34W$(X{p z_3u%Ch(72GNrzy8vtW@&Mq7A0Cc>sf<@Yuzyu@;Yb%w)-uV1`)yERt4E0B)97)i#V zs(K5pnrGLU*+u@mr#K8%^e2isk0_0&1?+DR$I7_dCCU-|r}<|rdUFh}ACYkAd-{T4 z6$QtHDQw;6_1_r1>_fFq^6Tx@A?Cq_`t8qJV)A%=W($h;1ceL=?fg3(*PAnS zl<=r7=!71nEn&4=OQRn)1inPnf1m6zoXckF+ktHJjVAehH}$v=m;aD^n6l% z@m!pWzw|0aQZbluGJQ@_M^iKWD4XC7jiP{k|7~$0JeD$HEiQQ&JvW%CxWA*tE#uby z=hvs6Y`uIre)_?>;@?59Uu*8dMxIUnW`-#wTmA}6qHcPbpy(8q_Vw!|cm~+qo(XY&y*vlJ zcigVDyR`&-xfKPVd}RUG2NS+ZJ$?uk2+9NL@F<^>$$$Yr<1MQ zx>qsY6wyV0LN57E5VMsm!He5rp!nC29OH=-rHZNLw=50k$A15IYZfTIdgDfmLgUYm zmo$8G2dnfD+rO?P6%(Ai=>~n5Th}J)GO

c`Ceq+9h^9nqO|enqBpwBzO$CkT&ZF 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 literal 0 HcmV?d00001 diff --git a/demo_outputs/hospital_load_distribution.png b/demo_outputs/hospital_load_distribution.png new file mode 100644 index 0000000000000000000000000000000000000000..9f02204d3b7f013186891996e8802298acf29171 GIT binary patch literal 20170 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 literal 0 HcmV?d00001 diff --git a/demo_outputs/urban_rural_map.html b/demo_outputs/urban_rural_map.html new file mode 100644 index 0000000..eb3b626 --- /dev/null +++ b/demo_outputs/urban_rural_map.html @@ -0,0 +1,20545 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + \ No newline at end of file diff --git a/run_demo.py b/run_demo.py index c5c3994..6b53d62 100644 --- a/run_demo.py +++ b/run_demo.py @@ -1,83 +1,486 @@ from pathlib import Path -from ertimes.stats_visualization import plot_category_visits, plot_hospital_load_distribution, plot_urban_rural_map -from ertimes.io import download_emergency_data, load_emergency_data -from ertimes.stats_analysis import find_capacity_volume_mismatch, county_capacity_summary, rank_counties_by_burden -from ertimes.stats_ranking import rank_hospitals_by_visits_per_station -from ertimes.stats_reports import summarize_by_ownership import pandas as pd +from ertimes.io import download_emergency_data, load_emergency_data + +from ertimes.stats_analysis import ( + county_capacity_summary, + find_capacity_volume_mismatch, + compute_capacity_pressure_score, + mental_health_shortage_analysis, + calculate_growth, + run_er_analysis, + county_facility_counts, + spike_frequency_pivot, + load_california_income_data, + get_income_by_zip, + get_income_by_county, +) + +from ertimes.stats_ranking import ( + rank_counties_by_burden, + rank_hospitals_by_visits_per_station, +) -df = download_emergency_data("california") +from ertimes.stats_reports import ( + generate_county_report, + summarize_by_ownership, + find_duplicates, + per_category_burden_report, +) -#raises error -result = find_capacity_volume_mismatch( - df, - high_visit_quantile=0.65, - low_capacity_quantile=0.35, +from ertimes.stats_visualization import ( + plot_hospital_load_distribution, + plot_facility_trend, + plot_category_visits, + plot_category_visits_by_facility, + plot_urban_rural_map, ) -print(result.head(10)) -print(f"Rows returned: {len(result)}") +from ertimes.demographics import ( + get_income_statistics, + filter_by_income_range, +) -print("Downloading data for test...") -df = download_emergency_data("california") +OUTPUT_DIR = Path("demo_outputs") +OUTPUT_DIR.mkdir(exist_ok=True) -print("Generating plot...") -plot_hospital_load_distribution(df, group_col='hospital_ownership', save=True) -print("Generating urban-rural map...") -plot_urban_rural_map("california", save=True) +def print_section(title: str) -> None: + """Print a clear section header for demo output.""" + print("\n" + "=" * 80) + print(title) + print("=" * 80) -print("Check your 'data/' folder for the new files!") -#test for health conditions bar plot -def demo_plot_category_visits_downloaded() -> None: - """Download emergency data for California and render the category visits plot.""" - print("Downloading emergency data for California...") +def demo_download_emergency_data() -> pd.DataFrame: + """Demo downloading and cleaning emergency department data.""" + print_section("1. Download Emergency Department Data") + + print("Downloading California emergency department data...") df = download_emergency_data("california") - print("Generating category visits plot from downloaded data...") - plot_category_visits(df, save=True) + print("Download complete.") + print(f"Shape: {df.shape}") + print("\nColumns:") + print(df.columns.tolist()) + + print("\nFirst 5 rows:") + print(df.head()) + + return df + + +def demo_load_emergency_data_from_saved_csv(df: pd.DataFrame) -> pd.DataFrame: + """Demo saving then loading emergency data locally.""" + print_section("2. Save and Reload Emergency Data Locally") + + csv_path = OUTPUT_DIR / "california_emergency_data_sample.csv" + df.head(100).to_csv(csv_path, index=False) + + print(f"Saved first 100 rows to: {csv_path}") + loaded_df = load_emergency_data(csv_path) + + print("Reloaded local CSV successfully.") + print(f"Reloaded shape: {loaded_df.shape}") + print(loaded_df.head()) + + return loaded_df + + +def demo_capacity_volume_mismatch(df: pd.DataFrame) -> pd.DataFrame: + """Demo identifying hospitals with high demand and low capacity.""" + print_section("3. Capacity-Volume Mismatch Analysis") + + result = find_capacity_volume_mismatch( + df, + high_visit_quantile=0.65, + low_capacity_quantile=0.35, + facility_col="facility_name", + county_col="county_name", + year_col="year", + visits_col="total_ed_visits", + stations_col="ed_stations", + bed_col="licensed_bed_size", + ) + + print("Hospitals with high visits per station and relatively low bed capacity:") + print(result.head(10)) + print(f"\nRows returned: {len(result)}") + + return result + + +def demo_county_capacity_summary() -> pd.DataFrame: + """Demo county-level capacity summary.""" + print_section("4. County Capacity Summary") + + summary = county_capacity_summary( + "california", + county_col="county_name", + visits_col="total_ed_visits", + stations_col="ed_stations", + bed_col="licensed_bed_size", + ) + + print("County-level capacity summary:") + print(summary.head(10)) + print(f"\nRows returned: {len(summary)}") -def demo_county_capacity_summary(): - """Demo county capacity summary.""" - print("Generating county capacity summary...") - summary = county_capacity_summary("california") - print(summary.head()) return summary -def demo_rank_counties(): - """Demo ranking counties by burden.""" - print("Ranking counties by burden...") - summary = demo_county_capacity_summary() - ranked = rank_counties_by_burden(summary) - print(ranked.head()) + +def demo_rank_counties(summary: pd.DataFrame) -> pd.DataFrame: + """Demo ranking counties by emergency department burden.""" + print_section("5. Rank Counties by Burden") + + ranked = rank_counties_by_burden( + summary, + visits_col="visits_per_station", + ) + + print("Top 10 counties by visits per station:") + print(ranked.head(10)) + return ranked -def demo_rank_hospitals(): + +def demo_generate_county_report(summary: pd.DataFrame) -> pd.DataFrame: + """Demo generating a single-county report.""" + print_section("6. Generate Single County Report") + + if summary.empty: + print("County summary is empty; skipping county report.") + return pd.DataFrame() + + county_name = summary.iloc[0]["county_name"] + + report = generate_county_report( + summary, + county_name=county_name, + county_col="county_name", + visits_col="tot_ed_visits", + stations_col="ed_stations", + beds_col="licensed_bed_size", + visits_per_station_col="visits_per_station", + ) + + print(f"Generated report for county: {county_name}") + print(report) + + return report + + +def demo_rank_hospitals(df: pd.DataFrame) -> pd.DataFrame: """Demo ranking hospitals by visits per station.""" - print("Ranking hospitals by visits per station...") - df = download_emergency_data("california") - ranked = rank_hospitals_by_visits_per_station(df, top_n=5) + print_section("7. Rank Hospitals by Visits per Station") + + ranked = rank_hospitals_by_visits_per_station( + df, + agg="median", + top_n=10, + facility_col="facility_name", + visits_col="visits_per_station", + ) + + print("Top 10 hospitals by median visits per station:") print(ranked) + return ranked -def demo_summarize_by_ownership(): - """Demo summarizing by ownership.""" - print("Summarizing by ownership...") - df = download_emergency_data("california") - summary = summarize_by_ownership(df) - print(summary) + +def demo_summarize_by_ownership(df: pd.DataFrame) -> pd.DataFrame: + """Demo summarizing emergency data by hospital ownership type.""" + print_section("8. Summarize by Hospital Ownership") + + summary = summarize_by_ownership( + df, + column_map={ + "hospital_ownership": "hospital_ownership", + "tot_ed_visits": "total_ed_visits", + "ed_stations": "ed_stations", + "visits_per_station": "visits_per_station", + }, + ) + + print("Ownership-level summary:") + print(summary.head(10)) + return summary -demo_plot_category_visits_downloaded() -# Run demos +def demo_find_duplicates(df: pd.DataFrame) -> pd.DataFrame: + """Demo duplicate detection.""" + print_section("9. Find Duplicate Rows") + + duplicate_rows = find_duplicates( + df, + subset=["facility_name", "county_name", "year", "category"], + ) + + print("Potential duplicate rows using facility, county, year, and category:") + print(duplicate_rows.head(10)) + print(f"\nDuplicate rows found: {len(duplicate_rows)}") + + return duplicate_rows + + +def demo_per_category_burden_report(df: pd.DataFrame) -> dict[str, list[str]]: + """Demo top burdened facilities by condition category.""" + print_section("10. Per-Category Burden Report") + + report = per_category_burden_report( + df, + top_n=3, + facility_col="facility_name", + category_col="category", + visits_col="visits_per_station", + ) + + print("Top 3 facilities by visits per station for each category:") + for category, facilities in list(report.items())[:10]: + print(f"{category}: {facilities}") + + return report + + +def demo_capacity_pressure_score(df: pd.DataFrame) -> pd.DataFrame: + """Demo composite capacity pressure score.""" + print_section("11. Capacity Pressure Score") + + scores = compute_capacity_pressure_score( + df, + facility_col="facility_name", + visits_col="visits_per_station", + bed_col="licensed_bed_size", + primary_shortage_col="primary_care_shortage_area", + mental_shortage_col="mental_health_shortage_area", + ) + + print("Top 10 facilities by capacity pressure score:") + print(scores.head(10)) + + return scores + + +def demo_mental_health_shortage_analysis(df: pd.DataFrame) -> pd.DataFrame: + """Demo high-burden facilities in mental health shortage areas.""" + print_section("12. Mental Health Shortage Analysis") + + result = mental_health_shortage_analysis( + df, + percentile_threshold=80, + visits_col="total_ed_visits", + stations_col="ed_stations", + shortage_col="mental_health_shortage_area", + year_col="year", + ) + + print("Facilities in mental health shortage areas with high ED burden:") + print(result.head(10)) + print(f"\nRows returned: {len(result)}") + + return result + + +def demo_growth_analysis(df: pd.DataFrame) -> pd.DataFrame: + """Demo year-over-year growth calculations.""" + print_section("13. Year-over-Year Growth Analysis") + + result = calculate_growth( + df, + value_col="total_ed_visits", + group_cols=["facility_name"], + time_col="year", + pct=True, + ) + + print("Growth analysis sample:") + print(result[["facility_name", "year", "total_ed_visits", "growth"]].head(15)) + + return result + + +def demo_run_er_analysis(df: pd.DataFrame) -> pd.DataFrame: + """Demo general ER analysis helper.""" + print_section("14. General ER Analysis") + + result = run_er_analysis( + df, + facility_col="facility_name", + year_col="year", + visits_col="total_ed_visits", + visits_per_station_col="visits_per_station", + ) + + print("ER analysis sample:") + print(result[["facility_name", "year", "YoY_Visits", "Utilization", "Mismatch"]].head(15)) + + print("\nMismatch counts:") + print(result["Mismatch"].value_counts(dropna=False)) + + return result + + +def demo_county_facility_counts(df: pd.DataFrame) -> pd.DataFrame: + """Demo counting unique facilities by county.""" + print_section("15. County Facility Counts") + + result = county_facility_counts( + df, + county_col="county_name", + facility_col="facility_name", + ) + + print("Top 10 counties by number of unique facilities:") + print(result.head(10)) + + return result + + +def demo_spike_frequency_pivot(df: pd.DataFrame) -> pd.DataFrame: + """Demo detecting year-over-year burden spikes by category.""" + print_section("16. Spike Frequency Pivot") + + result = spike_frequency_pivot( + df, + threshold_pct=20.0, + facility_col="facility_name", + category_col="category", + year_col="year", + visits_col="visits_per_station", + ) + + print("Categories with the most year-over-year spikes:") + print(result.head(10)) + + return result + + +def demo_income_data() -> pd.DataFrame: + """Demo California income data utilities.""" + print_section("17. California Income Data Utilities") + + income_path = Path("data/california_median_income_by_zipcode.csv") + + if income_path.exists(): + income_df = load_california_income_data(income_path) + print(f"Loaded income data from: {income_path}") + else: + income_df = load_california_income_data() + print("Income CSV not found. Loaded built-in sample income data.") + + print("\nIncome data sample:") + print(income_df.head()) + + print("\nIncome statistics:") + print(get_income_statistics(income_df)) + + print("\nIncome statistics by county:") + print(get_income_statistics(income_df, group_by="county")) + + zip_code = str(income_df.iloc[0]["zip_code"]) + print(f"\nLookup for ZIP code {zip_code}:") + print(get_income_by_zip(income_df, zip_code)) + + county = str(income_df.iloc[0]["county"]) + print(f"\nFirst 5 ZIP codes in county: {county}") + print(get_income_by_county(income_df, county).head()) + + print("\nZIP codes with median income between $70,000 and $120,000:") + print(filter_by_income_range(income_df, 70000, 120000).head(10)) + + return income_df + + +def demo_visualizations(df: pd.DataFrame) -> None: + """Demo visualization functions and save outputs.""" + print_section("18. Visualization Demos") + + load_plot_path = OUTPUT_DIR / "hospital_load_distribution.png" + category_plot_path = OUTPUT_DIR / "category_visits_plot.png" + facility_category_plot_path = OUTPUT_DIR / "facility_category_visits_plot.png" + trend_plot_path = OUTPUT_DIR / "facility_trend.png" + + print("Generating hospital load distribution plot...") + fig = plot_hospital_load_distribution( + df, + visits_col="total_ed_visits", + stations_col="ed_stations", + save_path=str(load_plot_path), + ) + print(f"Saved: {load_plot_path}") + + print("\nGenerating category visits plot...") + fig = plot_category_visits(df, save=False) + fig.savefig(category_plot_path) + print(f"Saved: {category_plot_path}") + + first_facility = df["facility_name"].dropna().iloc[0] + + print(f"\nGenerating facility trend plot for: {first_facility}") + fig = plot_facility_trend( + df, + first_facility, + facility_col="facility_name", + year_col="year", + visits_col="total_ed_visits", + ) + fig.savefig(trend_plot_path) + print(f"Saved: {trend_plot_path}") + + print(f"\nGenerating category visits plot for facility: {first_facility}") + fig = plot_category_visits_by_facility(df, first_facility, save=False) + fig.savefig(facility_category_plot_path) + print(f"Saved: {facility_category_plot_path}") + + print("\nGenerating urban-rural map...") + map_obj = plot_urban_rural_map( + "california", + save=False, + latitude_col="latitude", + longitude_col="longitude", + designation_col="urban_rural_designation", + facility_col="facility_name", + ) + map_path = OUTPUT_DIR / "urban_rural_map.html" + map_obj.save(map_path) + print(f"Saved: {map_path}") + + +def main() -> None: + """Run all demos.""" + print_section("ERTIMES PACKAGE DEMO") + + df = demo_download_emergency_data() + + demo_load_emergency_data_from_saved_csv(df) + + demo_capacity_volume_mismatch(df) + + county_summary = demo_county_capacity_summary() + demo_rank_counties(county_summary) + demo_generate_county_report(county_summary) + + demo_rank_hospitals(df) + demo_summarize_by_ownership(df) + demo_find_duplicates(df) + demo_per_category_burden_report(df) + demo_capacity_pressure_score(df) + demo_mental_health_shortage_analysis(df) + demo_growth_analysis(df) + demo_run_er_analysis(df) + demo_county_facility_counts(df) + demo_spike_frequency_pivot(df) + demo_income_data() + demo_visualizations(df) + + print_section("DEMO COMPLETE") + print(f"Check the '{OUTPUT_DIR}/' folder for saved CSVs, plots, and maps.") + + if __name__ == "__main__": - demo_county_capacity_summary() - demo_rank_counties() - demo_rank_hospitals() - demo_summarize_by_ownership() \ No newline at end of file + main() \ No newline at end of file From 95541af10728996462a7312d850aedd6caab2eba Mon Sep 17 00:00:00 2001 From: Sarah Kota Date: Tue, 28 Apr 2026 17:05:27 -0400 Subject: [PATCH 09/11] deleted/moved files to correct location --- data/urban_rural_map_California.html | 20560 ------------------------- data/urban_rural_map_california.html | 20560 ------------------------- demo_outputs/urban_rural_map.html | 8620 +++++------ 3 files changed, 4310 insertions(+), 45430 deletions(-) delete mode 100644 data/urban_rural_map_California.html delete mode 100644 data/urban_rural_map_california.html diff --git a/data/urban_rural_map_California.html b/data/urban_rural_map_California.html deleted file mode 100644 index cf10cc8..0000000 --- a/data/urban_rural_map_California.html +++ /dev/null @@ -1,20560 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - \ No newline at end of file diff --git a/data/urban_rural_map_california.html b/data/urban_rural_map_california.html deleted file mode 100644 index cf10cc8..0000000 --- a/data/urban_rural_map_california.html +++ /dev/null @@ -1,20560 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - \ No newline at end of file diff --git a/demo_outputs/urban_rural_map.html b/demo_outputs/urban_rural_map.html index eb3b626..8f534bc 100644 --- a/demo_outputs/urban_rural_map.html +++ b/demo_outputs/urban_rural_map.html @@ -17,7 +17,7 @@