analysis of initial risk attitude distributions & population outcomes¶
Analyzing data generated from a batch run with 1000 iterations each per risk distribution
- maximum run length of 3000 steps
- convergence threshold at <=7% agents changing for two adjustment rounds in a row
In [13]:
import polars as pl
df = pl.read_csv("../../data/hawkdovemulti/dist_c7_3k_2024-02-27T162947_580557_model.csv")
In [14]:
total_runs = len(df)
print(f"Analyzing {total_runs} runs")
Analyzing 5000 runs
what % converged?¶
In [15]:
converged_df = df.filter(df["status"] == "converged")
len(converged_df)
Out[15]:
4594
almost all of them!
how long does it take to converge?¶
In [16]:
converged_df["Step"].describe()
Out[16]:
shape: (9, 2)
statistic | value |
---|---|
str | f64 |
"count" | 4594.0 |
"null_count" | 0.0 |
"mean" | 147.572921 |
"std" | 135.641494 |
"min" | 50.0 |
"25%" | 70.0 |
"50%" | 110.0 |
"75%" | 170.0 |
"max" | 2410.0 |
In [17]:
converged_df["Step"].plot.hist()
Out[17]:
compare different initial distributions¶
In [18]:
df["risk_distribution"].unique()
Out[18]:
shape: (5,)
risk_distribution |
---|
str |
"skewed right" |
"uniform" |
"bimodal" |
"skewed left" |
"normal" |
How many converged runs in each subset?
In [19]:
converged_df.group_by("risk_distribution").count()
/var/folders/mb/6qm4h4yx3yqdy2bv2sjyp4z00000gp/T/ipykernel_43782/1942186623.py:1: DeprecationWarning: `GroupBy.count` was renamed; use `GroupBy.len` instead converged_df.group_by("risk_distribution").count()
Out[19]:
shape: (5, 2)
risk_distribution | count |
---|---|
str | u32 |
"uniform" | 938 |
"skewed right" | 987 |
"bimodal" | 710 |
"normal" | 996 |
"skewed left" | 963 |
In [20]:
# filter converged run data into subsets by risk distribution
subset = {}
for distribution in converged_df["risk_distribution"].unique():
subset[distribution] = converged_df.filter(pl.col("risk_distribution") == distribution)
How does initial distribution affect convergence?¶
In [21]:
status_by_dist = df.group_by("risk_distribution", "status").count()
status_by_dist
/var/folders/mb/6qm4h4yx3yqdy2bv2sjyp4z00000gp/T/ipykernel_43782/3878793973.py:1: DeprecationWarning: `GroupBy.count` was renamed; use `GroupBy.len` instead status_by_dist = df.group_by("risk_distribution", "status").count()
Out[21]:
shape: (10, 3)
risk_distribution | status | count |
---|---|---|
str | str | u32 |
"skewed left" | "running" | 37 |
"skewed right" | "converged" | 987 |
"bimodal" | "converged" | 710 |
"uniform" | "running" | 62 |
"skewed left" | "converged" | 963 |
"bimodal" | "running" | 290 |
"uniform" | "converged" | 938 |
"skewed right" | "running" | 13 |
"normal" | "running" | 4 |
"normal" | "converged" | 996 |
In [22]:
import altair as alt
alt.Chart(status_by_dist).mark_bar().encode(
x='risk_distribution:N',
y='count',
color='status:N'
).properties(title="Simulation status (converged/running) by risk distribution", width=250, height=400)
Out[22]:
In [23]:
alt.Chart(converged_df).mark_boxplot(size=20).encode(
x='risk_distribution:N',
y='Step',
).properties(
title=alt.TitleParams(
"Simulation run length by risk distribution",
subtitle="(converged runs only)"),
width=350, height=450)
Out[23]:
population categories by risk distribution¶
In [24]:
import altair as alt
from simulatingrisk.hawkdovemulti import analysis_utils
uniform_chart = analysis_utils.graph_population_risk_category(
analysis_utils.groupby_population_risk_category(subset["uniform"])
).properties(title="risk distribution: uniform/random")
normal_chart = analysis_utils.graph_population_risk_category(
analysis_utils.groupby_population_risk_category(subset["normal"])
).properties(title="risk distribution: normal")
bimodal_chart = analysis_utils.graph_population_risk_category(
analysis_utils.groupby_population_risk_category(subset["bimodal"])
).properties(title="risk distribution: bimodal")
skewedleft_chart = analysis_utils.graph_population_risk_category(
analysis_utils.groupby_population_risk_category(subset["skewed left"])
).properties(title="risk distribution: skewed left")
skewedright_chart = analysis_utils.graph_population_risk_category(
analysis_utils.groupby_population_risk_category(subset["skewed right"])
).properties(title="risk distribution: skewed right")
(uniform_chart | normal_chart | bimodal_chart | skewedleft_chart | skewedright_chart) \
.properties(title=alt.TitleParams("Population category by run over initial risk distributions", anchor="middle")).resolve_scale(y='shared')
/Users/rkoeser/workarea/env/simrisk/lib/python3.12/site-packages/simulatingrisk/hawkdovemulti/analysis_utils.py:28: MapWithoutReturnDtypeWarning: Calling `map_elements` without specifying `return_dtype` can lead to unpredictable results. Specify `return_dtype` to silence this warning. values=poprisk_grouped["risk_category"].map_elements(RiskState.category),
Out[24]: