Update app.py
Browse files
app.py
CHANGED
|
@@ -41,13 +41,10 @@ def generate_custom_model_points(
|
|
| 41 |
sum_assured_col = np.round((sa_max_val - sa_min_val) * rng.random(size=mp_count_val) + sa_min_val, -3)
|
| 42 |
|
| 43 |
max_duration_val = policy_term_col * 12 - 1
|
| 44 |
-
max_duration_val = np.maximum(1, max_duration_val)
|
| 45 |
-
# Adjust random generation to ensure it's within [0, max_duration_val-1] then add 1
|
| 46 |
-
# If max_duration_val is 1, rng.random * 1 is [0,1), int is 0. So duration is 1.
|
| 47 |
-
# If max_duration_val is > 1, rng.random * (max_duration_val) is [0, max_duration_val), int is [0, max_duration_val-1]. Add 1 for [1, max_duration_val]
|
| 48 |
duration_mth_col = (rng.random(size=mp_count_val) * max_duration_val).astype(int) + 1
|
| 49 |
-
duration_mth_col = np.minimum(duration_mth_col, max_duration_val)
|
| 50 |
-
duration_mth_col = np.maximum(1, duration_mth_col)
|
| 51 |
|
| 52 |
|
| 53 |
if policy_count_fixed_val:
|
|
@@ -64,7 +61,7 @@ def generate_custom_model_points(
|
|
| 64 |
return model_point_df
|
| 65 |
|
| 66 |
# 2. Gradio App Definition
|
| 67 |
-
with gr.Blocks(theme=gr.themes.Soft()
|
| 68 |
gr.Markdown("# Actuarial Model Points Generator")
|
| 69 |
gr.Markdown(
|
| 70 |
"Configure the parameters below to generate a custom set of seriatim model points. "
|
|
@@ -77,7 +74,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 77 |
with gr.Row():
|
| 78 |
with gr.Column(scale=1):
|
| 79 |
gr.Markdown("### Generation Parameters")
|
| 80 |
-
mp_count_input = gr.Slider(minimum=100, maximum=50000, value=1000, step=100, label="Number of Model Points")
|
| 81 |
seed_input = gr.Number(value=12345, precision=0, label="Random Seed")
|
| 82 |
gr.Markdown("#### Age Parameters")
|
| 83 |
age_min_input = gr.Slider(minimum=18, maximum=40, value=20, step=1, label="Minimum Age at Entry")
|
|
@@ -101,7 +98,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 101 |
summary_stats_display = gr.Markdown(value="*No data generated yet or summary failed.*")
|
| 102 |
with gr.TabItem("Distribution Plot"):
|
| 103 |
gr.Markdown("Distribution of **Sum Assured**. Data is generated uniformly; a normal curve is fitted for illustration.")
|
| 104 |
-
distribution_plot_display = gr.Plot()
|
| 105 |
with gr.TabItem("Categorical Summary"):
|
| 106 |
categorical_summary_display = gr.Markdown(value="*No data generated yet or summary failed.*")
|
| 107 |
|
|
@@ -109,18 +106,16 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 109 |
def handle_generate_button_click(
|
| 110 |
mp_c, s, age_m, age_mx, sa_m, sa_mx, p_terms, incl_sex, pc_fixed
|
| 111 |
):
|
| 112 |
-
# Initialize outputs for potential error returns
|
| 113 |
error_desc_md = "Error during generation. Check parameters."
|
| 114 |
error_cat_md = "Error during generation. Check parameters."
|
| 115 |
current_df = df_state.value if df_state.value is not None else pd.DataFrame()
|
| 116 |
|
| 117 |
-
|
| 118 |
if int(age_m) >= int(age_mx):
|
| 119 |
gr.Warning("Minimum Age must be less than Maximum Age.")
|
| 120 |
-
return current_df, df_state.value, "Error: Minimum Age
|
| 121 |
if float(sa_m) >= float(sa_mx):
|
| 122 |
gr.Warning("Minimum Sum Assured must be less than Maximum Sum Assured.")
|
| 123 |
-
return current_df, df_state.value, "Error:
|
| 124 |
|
| 125 |
gr.Info("Generating model points... Please wait.")
|
| 126 |
try:
|
|
@@ -141,9 +136,9 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 141 |
else:
|
| 142 |
desc_stats_md = "No numerical data to describe or DataFrame is empty."
|
| 143 |
|
| 144 |
-
fig = None
|
| 145 |
if 'sum_assured' in df.columns and not df['sum_assured'].empty:
|
| 146 |
-
fig, ax = plt.subplots(figsize=(8, 5))
|
| 147 |
ax.hist(df['sum_assured'], bins=50, density=True, alpha=0.7, color='skyblue', edgecolor='black', label='Actual Distribution')
|
| 148 |
mu, std = stats.norm.fit(df['sum_assured'])
|
| 149 |
xmin_hist, xmax_hist = ax.get_xlim()
|
|
@@ -156,8 +151,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 156 |
ax.legend()
|
| 157 |
ax.grid(axis='y', linestyle='--', alpha=0.7)
|
| 158 |
plt.tight_layout()
|
| 159 |
-
|
| 160 |
-
plot_object = fig # This will be None if sum_assured data was missing
|
| 161 |
|
| 162 |
cat_summary_md = "### Categorical Data Frequencies\n\n"
|
| 163 |
if not df.empty:
|
|
@@ -171,7 +165,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 171 |
term_counts.columns = ['Policy Term (Years)', 'Count']
|
| 172 |
term_counts['Percentage'] = (term_counts['Count'] / term_counts['Count'].sum() * 100).round(2).astype(str) + '%'
|
| 173 |
cat_summary_md += "#### Policy Term Distribution\n" + term_counts.to_markdown(index=False)
|
| 174 |
-
if cat_summary_md == "### Categorical Data Frequencies\n\n":
|
| 175 |
cat_summary_md += "*No categorical columns ('sex', 'policy_term') found or data is empty.*"
|
| 176 |
else:
|
| 177 |
cat_summary_md = "*DataFrame is empty, no categorical data to summarize.*"
|
|
@@ -180,7 +174,6 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 180 |
|
| 181 |
except Exception as e:
|
| 182 |
gr.Error(f"An error occurred during generation: {str(e)}")
|
| 183 |
-
# Return current state or empty placeholders for all outputs
|
| 184 |
return current_df, df_state.value, f"Error: {str(e)}", None, f"Error: {str(e)}"
|
| 185 |
|
| 186 |
|
|
|
|
| 41 |
sum_assured_col = np.round((sa_max_val - sa_min_val) * rng.random(size=mp_count_val) + sa_min_val, -3)
|
| 42 |
|
| 43 |
max_duration_val = policy_term_col * 12 - 1
|
| 44 |
+
max_duration_val = np.maximum(1, max_duration_val)
|
|
|
|
|
|
|
|
|
|
| 45 |
duration_mth_col = (rng.random(size=mp_count_val) * max_duration_val).astype(int) + 1
|
| 46 |
+
duration_mth_col = np.minimum(duration_mth_col, max_duration_val)
|
| 47 |
+
duration_mth_col = np.maximum(1, duration_mth_col)
|
| 48 |
|
| 49 |
|
| 50 |
if policy_count_fixed_val:
|
|
|
|
| 61 |
return model_point_df
|
| 62 |
|
| 63 |
# 2. Gradio App Definition
|
| 64 |
+
with gr.Blocks() as demo: # Removed theme=gr.themes.Soft() to use Gradio default
|
| 65 |
gr.Markdown("# Actuarial Model Points Generator")
|
| 66 |
gr.Markdown(
|
| 67 |
"Configure the parameters below to generate a custom set of seriatim model points. "
|
|
|
|
| 74 |
with gr.Row():
|
| 75 |
with gr.Column(scale=1):
|
| 76 |
gr.Markdown("### Generation Parameters")
|
| 77 |
+
mp_count_input = gr.Slider(minimum=100, maximum=50000, value=1000, step=100, label="Number of Model Points")
|
| 78 |
seed_input = gr.Number(value=12345, precision=0, label="Random Seed")
|
| 79 |
gr.Markdown("#### Age Parameters")
|
| 80 |
age_min_input = gr.Slider(minimum=18, maximum=40, value=20, step=1, label="Minimum Age at Entry")
|
|
|
|
| 98 |
summary_stats_display = gr.Markdown(value="*No data generated yet or summary failed.*")
|
| 99 |
with gr.TabItem("Distribution Plot"):
|
| 100 |
gr.Markdown("Distribution of **Sum Assured**. Data is generated uniformly; a normal curve is fitted for illustration.")
|
| 101 |
+
distribution_plot_display = gr.Plot()
|
| 102 |
with gr.TabItem("Categorical Summary"):
|
| 103 |
categorical_summary_display = gr.Markdown(value="*No data generated yet or summary failed.*")
|
| 104 |
|
|
|
|
| 106 |
def handle_generate_button_click(
|
| 107 |
mp_c, s, age_m, age_mx, sa_m, sa_mx, p_terms, incl_sex, pc_fixed
|
| 108 |
):
|
|
|
|
| 109 |
error_desc_md = "Error during generation. Check parameters."
|
| 110 |
error_cat_md = "Error during generation. Check parameters."
|
| 111 |
current_df = df_state.value if df_state.value is not None else pd.DataFrame()
|
| 112 |
|
|
|
|
| 113 |
if int(age_m) >= int(age_mx):
|
| 114 |
gr.Warning("Minimum Age must be less than Maximum Age.")
|
| 115 |
+
return current_df, df_state.value, "Error: Minimum Age must be less than Maximum Age.", None, "Error: Minimum Age must be less than Maximum Age."
|
| 116 |
if float(sa_m) >= float(sa_mx):
|
| 117 |
gr.Warning("Minimum Sum Assured must be less than Maximum Sum Assured.")
|
| 118 |
+
return current_df, df_state.value, "Error: Minimum Sum Assured must be less than Maximum Sum Assured.", None, "Error: Minimum Sum Assured must be less than Maximum Sum Assured."
|
| 119 |
|
| 120 |
gr.Info("Generating model points... Please wait.")
|
| 121 |
try:
|
|
|
|
| 136 |
else:
|
| 137 |
desc_stats_md = "No numerical data to describe or DataFrame is empty."
|
| 138 |
|
| 139 |
+
fig = None
|
| 140 |
if 'sum_assured' in df.columns and not df['sum_assured'].empty:
|
| 141 |
+
fig, ax = plt.subplots(figsize=(8, 5))
|
| 142 |
ax.hist(df['sum_assured'], bins=50, density=True, alpha=0.7, color='skyblue', edgecolor='black', label='Actual Distribution')
|
| 143 |
mu, std = stats.norm.fit(df['sum_assured'])
|
| 144 |
xmin_hist, xmax_hist = ax.get_xlim()
|
|
|
|
| 151 |
ax.legend()
|
| 152 |
ax.grid(axis='y', linestyle='--', alpha=0.7)
|
| 153 |
plt.tight_layout()
|
| 154 |
+
plot_object = fig
|
|
|
|
| 155 |
|
| 156 |
cat_summary_md = "### Categorical Data Frequencies\n\n"
|
| 157 |
if not df.empty:
|
|
|
|
| 165 |
term_counts.columns = ['Policy Term (Years)', 'Count']
|
| 166 |
term_counts['Percentage'] = (term_counts['Count'] / term_counts['Count'].sum() * 100).round(2).astype(str) + '%'
|
| 167 |
cat_summary_md += "#### Policy Term Distribution\n" + term_counts.to_markdown(index=False)
|
| 168 |
+
if cat_summary_md == "### Categorical Data Frequencies\n\n":
|
| 169 |
cat_summary_md += "*No categorical columns ('sex', 'policy_term') found or data is empty.*"
|
| 170 |
else:
|
| 171 |
cat_summary_md = "*DataFrame is empty, no categorical data to summarize.*"
|
|
|
|
| 174 |
|
| 175 |
except Exception as e:
|
| 176 |
gr.Error(f"An error occurred during generation: {str(e)}")
|
|
|
|
| 177 |
return current_df, df_state.value, f"Error: {str(e)}", None, f"Error: {str(e)}"
|
| 178 |
|
| 179 |
|