Skip to content

Instantly share code, notes, and snippets.

@QuentinAndre
Last active September 9, 2020 15:20
Show Gist options
  • Save QuentinAndre/0227651e062bf10eca897ef73185f51d to your computer and use it in GitHub Desktop.
Save QuentinAndre/0227651e062bf10eca897ef73185f51d to your computer and use it in GitHub Desktop.
Code to reproduce the simulation of André and de Langhe's response to Walasek, Mullett and Stewart.
condition bet_number loss gain
0.0 0.0 6.0 6.0
0.0 1.0 6.0 8.0
0.0 2.0 6.0 10.0
0.0 3.0 6.0 12.0
0.0 4.0 6.0 14.0
0.0 5.0 6.0 16.0
0.0 6.0 6.0 18.0
0.0 7.0 6.0 20.0
0.0 8.0 8.0 6.0
0.0 9.0 8.0 8.0
0.0 10.0 8.0 10.0
0.0 11.0 8.0 12.0
0.0 12.0 8.0 14.0
0.0 13.0 8.0 16.0
0.0 14.0 8.0 18.0
0.0 15.0 8.0 20.0
0.0 16.0 10.0 6.0
0.0 17.0 10.0 8.0
0.0 18.0 10.0 10.0
0.0 19.0 10.0 12.0
0.0 20.0 10.0 14.0
0.0 21.0 10.0 16.0
0.0 22.0 10.0 18.0
0.0 23.0 10.0 20.0
0.0 24.0 12.0 6.0
0.0 25.0 12.0 8.0
0.0 26.0 12.0 10.0
0.0 27.0 12.0 12.0
0.0 28.0 12.0 14.0
0.0 29.0 12.0 16.0
0.0 30.0 12.0 18.0
0.0 31.0 12.0 20.0
0.0 32.0 14.0 6.0
0.0 33.0 14.0 8.0
0.0 34.0 14.0 10.0
0.0 35.0 14.0 12.0
0.0 36.0 14.0 14.0
0.0 37.0 14.0 16.0
0.0 38.0 14.0 18.0
0.0 39.0 14.0 20.0
0.0 40.0 16.0 6.0
0.0 41.0 16.0 8.0
0.0 42.0 16.0 10.0
0.0 43.0 16.0 12.0
0.0 44.0 16.0 14.0
0.0 45.0 16.0 16.0
0.0 46.0 16.0 18.0
0.0 47.0 16.0 20.0
0.0 48.0 18.0 6.0
0.0 49.0 18.0 8.0
0.0 50.0 18.0 10.0
0.0 51.0 18.0 12.0
0.0 52.0 18.0 14.0
0.0 53.0 18.0 16.0
0.0 54.0 18.0 18.0
0.0 55.0 18.0 20.0
0.0 56.0 20.0 6.0
0.0 57.0 20.0 8.0
0.0 58.0 20.0 10.0
0.0 59.0 20.0 12.0
0.0 60.0 20.0 14.0
0.0 61.0 20.0 16.0
0.0 62.0 20.0 18.0
0.0 63.0 20.0 20.0
1.0 0.0 12.0 6.0
1.0 1.0 12.0 8.0
1.0 2.0 12.0 10.0
1.0 3.0 12.0 12.0
1.0 4.0 12.0 14.0
1.0 5.0 12.0 16.0
1.0 6.0 12.0 18.0
1.0 7.0 12.0 20.0
1.0 8.0 16.0 6.0
1.0 9.0 16.0 8.0
1.0 10.0 16.0 10.0
1.0 11.0 16.0 12.0
1.0 12.0 16.0 14.0
1.0 13.0 16.0 16.0
1.0 14.0 16.0 18.0
1.0 15.0 16.0 20.0
1.0 16.0 20.0 6.0
1.0 17.0 20.0 8.0
1.0 18.0 20.0 10.0
1.0 19.0 20.0 12.0
1.0 20.0 20.0 14.0
1.0 21.0 20.0 16.0
1.0 22.0 20.0 18.0
1.0 23.0 20.0 20.0
1.0 24.0 24.0 6.0
1.0 25.0 24.0 8.0
1.0 26.0 24.0 10.0
1.0 27.0 24.0 12.0
1.0 28.0 24.0 14.0
1.0 29.0 24.0 16.0
1.0 30.0 24.0 18.0
1.0 31.0 24.0 20.0
1.0 32.0 28.0 6.0
1.0 33.0 28.0 8.0
1.0 34.0 28.0 10.0
1.0 35.0 28.0 12.0
1.0 36.0 28.0 14.0
1.0 37.0 28.0 16.0
1.0 38.0 28.0 18.0
1.0 39.0 28.0 20.0
1.0 40.0 32.0 6.0
1.0 41.0 32.0 8.0
1.0 42.0 32.0 10.0
1.0 43.0 32.0 12.0
1.0 44.0 32.0 14.0
1.0 45.0 32.0 16.0
1.0 46.0 32.0 18.0
1.0 47.0 32.0 20.0
1.0 48.0 36.0 6.0
1.0 49.0 36.0 8.0
1.0 50.0 36.0 10.0
1.0 51.0 36.0 12.0
1.0 52.0 36.0 14.0
1.0 53.0 36.0 16.0
1.0 54.0 36.0 18.0
1.0 55.0 36.0 20.0
1.0 56.0 40.0 6.0
1.0 57.0 40.0 8.0
1.0 58.0 40.0 10.0
1.0 59.0 40.0 12.0
1.0 60.0 40.0 14.0
1.0 61.0 40.0 16.0
1.0 62.0 40.0 18.0
1.0 63.0 40.0 20.0
2.0 0.0 6.0 12.0
2.0 1.0 6.0 16.0
2.0 2.0 6.0 20.0
2.0 3.0 6.0 24.0
2.0 4.0 6.0 28.0
2.0 5.0 6.0 32.0
2.0 6.0 6.0 36.0
2.0 7.0 6.0 40.0
2.0 8.0 8.0 12.0
2.0 9.0 8.0 16.0
2.0 10.0 8.0 20.0
2.0 11.0 8.0 24.0
2.0 12.0 8.0 28.0
2.0 13.0 8.0 32.0
2.0 14.0 8.0 36.0
2.0 15.0 8.0 40.0
2.0 16.0 10.0 12.0
2.0 17.0 10.0 16.0
2.0 18.0 10.0 20.0
2.0 19.0 10.0 24.0
2.0 20.0 10.0 28.0
2.0 21.0 10.0 32.0
2.0 22.0 10.0 36.0
2.0 23.0 10.0 40.0
2.0 24.0 12.0 12.0
2.0 25.0 12.0 16.0
2.0 26.0 12.0 20.0
2.0 27.0 12.0 24.0
2.0 28.0 12.0 28.0
2.0 29.0 12.0 32.0
2.0 30.0 12.0 36.0
2.0 31.0 12.0 40.0
2.0 32.0 14.0 12.0
2.0 33.0 14.0 16.0
2.0 34.0 14.0 20.0
2.0 35.0 14.0 24.0
2.0 36.0 14.0 28.0
2.0 37.0 14.0 32.0
2.0 38.0 14.0 36.0
2.0 39.0 14.0 40.0
2.0 40.0 16.0 12.0
2.0 41.0 16.0 16.0
2.0 42.0 16.0 20.0
2.0 43.0 16.0 24.0
2.0 44.0 16.0 28.0
2.0 45.0 16.0 32.0
2.0 46.0 16.0 36.0
2.0 47.0 16.0 40.0
2.0 48.0 18.0 12.0
2.0 49.0 18.0 16.0
2.0 50.0 18.0 20.0
2.0 51.0 18.0 24.0
2.0 52.0 18.0 28.0
2.0 53.0 18.0 32.0
2.0 54.0 18.0 36.0
2.0 55.0 18.0 40.0
2.0 56.0 20.0 12.0
2.0 57.0 20.0 16.0
2.0 58.0 20.0 20.0
2.0 59.0 20.0 24.0
2.0 60.0 20.0 28.0
2.0 61.0 20.0 32.0
2.0 62.0 20.0 36.0
2.0 63.0 20.0 40.0
3.0 0.0 12.0 12.0
3.0 1.0 12.0 16.0
3.0 2.0 12.0 20.0
3.0 3.0 12.0 24.0
3.0 4.0 12.0 28.0
3.0 5.0 12.0 32.0
3.0 6.0 12.0 36.0
3.0 7.0 12.0 40.0
3.0 8.0 16.0 12.0
3.0 9.0 16.0 16.0
3.0 10.0 16.0 20.0
3.0 11.0 16.0 24.0
3.0 12.0 16.0 28.0
3.0 13.0 16.0 32.0
3.0 14.0 16.0 36.0
3.0 15.0 16.0 40.0
3.0 16.0 20.0 12.0
3.0 17.0 20.0 16.0
3.0 18.0 20.0 20.0
3.0 19.0 20.0 24.0
3.0 20.0 20.0 28.0
3.0 21.0 20.0 32.0
3.0 22.0 20.0 36.0
3.0 23.0 20.0 40.0
3.0 24.0 24.0 12.0
3.0 25.0 24.0 16.0
3.0 26.0 24.0 20.0
3.0 27.0 24.0 24.0
3.0 28.0 24.0 28.0
3.0 29.0 24.0 32.0
3.0 30.0 24.0 36.0
3.0 31.0 24.0 40.0
3.0 32.0 28.0 12.0
3.0 33.0 28.0 16.0
3.0 34.0 28.0 20.0
3.0 35.0 28.0 24.0
3.0 36.0 28.0 28.0
3.0 37.0 28.0 32.0
3.0 38.0 28.0 36.0
3.0 39.0 28.0 40.0
3.0 40.0 32.0 12.0
3.0 41.0 32.0 16.0
3.0 42.0 32.0 20.0
3.0 43.0 32.0 24.0
3.0 44.0 32.0 28.0
3.0 45.0 32.0 32.0
3.0 46.0 32.0 36.0
3.0 47.0 32.0 40.0
3.0 48.0 36.0 12.0
3.0 49.0 36.0 16.0
3.0 50.0 36.0 20.0
3.0 51.0 36.0 24.0
3.0 52.0 36.0 28.0
3.0 53.0 36.0 32.0
3.0 54.0 36.0 36.0
3.0 55.0 36.0 40.0
3.0 56.0 40.0 12.0
3.0 57.0 40.0 16.0
3.0 58.0 40.0 20.0
3.0 59.0 40.0 24.0
3.0 60.0 40.0 28.0
3.0 61.0 40.0 32.0
3.0 62.0 40.0 36.0
3.0 63.0 40.0 40.0
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
# Reading the bets from S1 of W&S: 64 bets for each condition
bets_s1 = pd.read_csv("Bets_S1.csv")
# Unique ID for each bet
bets_s1["bet"] = bets_s1[["gain", "loss"]].apply(
lambda x: f"{x.gain:.0f}-{x.loss:.0f}", axis=1
)
# Computing the expected value of each bet
bets_s1["EV"] = bets_s1["gain"] - bets_s1["loss"]
def simulate_choices(df, N=1000):
"""
Simulate the choices for N participants: They see all 64 bets in a random order,
and accept 50% of the bets, favoring those with the highest expected value.
"""
all_participants = []
for pid in range(N): # Simulate one participant
participant = df[["bet", "gain", "loss", "EV"]].sample(
n=64, replace=False
) # We sample all the gambles, without replacement, in a random order
choices = []
for i in range(64): # For each of the gamble
prev_evs = participant.iloc[0:i][
"EV"
] # Expected value of all the previously encountered gambles
current_ev = participant.iloc[i]["EV"] # Expected value of the focal gamble
ap = (
current_ev > prev_evs
).mean() # Acceptance probability: Proportion of previously encountered gambles that have a smaller EV than the focal gamble
ap = (
1 if np.isnan(ap) else ap
) # If it is the first gamble, it is accepted with probability 1.
rp = 1 - ap # Rejection probability
choices.append(
np.random.choice([0, 1], p=[rp, ap])
) # The choice is recorded
participant["choices"] = choices
participant["pid"] = pid
all_participants.append(participant)
return pd.concat(all_participants) # Return the choices of all participants
np.random.seed(189123789) # Seed for reproducibility
# Simulate 1000 choices in each condition
t0 = simulate_choices(bets_s1[bets_s1.condition == 0], 1000)
t0["condition"] = 0
t1 = simulate_choices(bets_s1[bets_s1.condition == 1], 1000)
t1["condition"] = 1
t2 = simulate_choices(bets_s1[bets_s1.condition == 2], 1000)
t2["condition"] = 2
t3 = simulate_choices(bets_s1[bets_s1.condition == 3], 1000)
t3["condition"] = 3
# All choices
choices = pd.concat([t0, t1, t2, t3]).reset_index(drop=True)
# Choices for all common gambles
choices_common = choices[
choices.gain.apply(lambda x: x in [12, 16, 20])
& choices.loss.apply(lambda x: x in [12, 16, 20])
]
# Plotting the choices
sns.set_context("paper")
g = sns.FacetGrid(
col="condition", col_wrap=2, data=t, height=6.38 / 2, sharex=True, sharey=True
)
axes = g.axes.flatten()
for i, ax in enumerate(axes):
# Summary of acceptance probabilities for all gain/loss pairs
data = (
choices_common[choices_common.condition == i]
.groupby(["gain", "loss"])
.mean()
.reset_index()
.pivot("gain", "loss", "choices")
)
# Heatmap of acceptance probabilities
sns.heatmap(
data, ax=ax, cbar=False, vmin=0, vmax=1, cmap="RdBu", annot=True, fmt=".0%"
)
ax.invert_yaxis()
ax.set_xticklabels([12, 16, 20])
ax.set_yticklabels([12, 16, 20])
ax.tick_params(axis="both", which="both", length=0)
# Ticks and labels
axes[0].set_xlabel("")
axes[0].set_ylabel("Prospective Gain")
axes[0].set_title("G20-L20")
axes[1].set_xlabel("")
axes[1].set_ylabel("")
axes[1].set_title("G20-L40")
axes[2].set_ylabel("Prospective Gain")
axes[2].set_xlabel("Prospective Loss")
axes[2].set_title("G40-L20")
axes[3].set_ylabel("")
axes[3].set_xlabel("Prospective Loss")
axes[3].set_title("G40-L40")
plt.tight_layout()
plt.savefig("SimulatedAcceptanceRate.png", dpi=100)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment