2025-10-19

MONTE CARLO METHODS

What are Monte Carlo methods?

Monte Carlo methods are computational algorithms that rely on repeated random sampling to solve problems that might be deterministic.

They usually follow a particular pattern:

  1. Define a domain of possible inputs.
  2. Generate inputs randomly from a probability distribution over the domain.
  3. Perform a deterministic computation of the outputs.
  4. Aggregate the results.

An Example

We know that the probability of getting an even number on a die is:

\[P(Even) = \frac{Number\ of\ even\ outcomes}{Total\ number\ of\ outcomes} = \frac{3}{6} = 0.5\]

Monte Carlo Approach:

  1. Simulate dice rolls N times.
  2. Count the number of even rolls X.
  3. Estimate probability: \[ \hat{P} = \frac{X}{N} \]

We can do this using the following R program:

sim = 10000
even = 0

for(i in 1:sim){
  roll = sample(1:6, 1)
  
  if(roll %% 2 == 0){
    even = even + 1
  }
}

probEven = even/sim
probEven
## [1] 0.4927

As we can see on the left, we simulated rolling a die and our probability for getting an even number was approximately 0.5, which is what we found using the formula on the previous side.

So, we observed that: Each die roll is an independent random experiment, and as N→∞, the Monte Carlo estimate P(Even) = 0.5 according to the Law of Large Numbers.

Our Experiment: Heart Health

For our experiment, we will simulate a random person’s characteristics like age, sex, resting blood pressure, cholesterol level, etc. and determine how likely it is for them to have heart disease. We will he using the “heart_cleveland_upload.csv” database.

First, we will fit a logistic regression model using our dataset to see how each variable actually relates to heart disease.

model = glm(condition ~ age + sex + cp + trestbps + chol + fbs +
               restecg + thalach + exang + oldpeak + slope + ca + thal,
             data = heart, family = binomial)

Regression Coefficients:

(Intercept) = -5.118
age = -0.014
sex = 1.32
cp = 0.579
trestbps = 0.024
chol = 0.005
fbs = -0.992
restecg = 0.246
thalach = -0.021
exang = 0.916
oldpeak = 0.25
slope = 0.583
ca = 1.267
thal = 0.714

The equation we will use to calculate the probability of Heart Disease is: \[P = \frac{1}{1 + e^{-(\beta_0 + \beta_1 x_1 + \beta_2 x_2 + \dots + \beta_n x_n)}}\]

where each \(\beta\) is the coefficient and each \(x\) is the variable (like age, chol, etc.)

Plotting the coefficients

We will use the following R code to generate a plot for the coefficients we got. Longer bars to the right increase the likelihood of heart disease, while longer bares to the left decrease it.

coefs <- data.frame(variable = names(coef(model)), estimate = coef(model))

ggplot(coefs, aes(x = variable, y = estimate)) + geom_col() + 
  coord_flip() + labs(x = "Variable", y = "Coefficient Estimate")

Monte Carlo Simulation

Now we will use the following code to generate a simulation for the probability of 20,000 people having heart disease using the Monte Carlo Method.

sim = 20000
diseased = 0

for(i in 1:sim){
  randAge = sample(heart$age, 1, replace = TRUE)
  randSex = sample(heart$sex, 1, replace = TRUE)
  randCp = sample(heart$cp, 1, replace = TRUE)
  randTrest = sample(heart$trestbps, 1, replace = TRUE)
  randChol = sample(heart$chol, 1, replace = TRUE)
  randFbs = sample(heart$fbs, 1, replace = TRUE)
  randEcg = sample(heart$restecg, 1, replace = TRUE)
  randThalach = sample(heart$thalach, 1, replace = TRUE)
  randEx = sample(heart$exang, 1, replace = TRUE)
  randOld = sample(heart$oldpeak, 1, replace = TRUE)
  randSlope = sample(heart$slope, 1, replace = TRUE)
  randCa = sample(heart$ca, 1, replace = TRUE)
  randThal = sample(heart$thal, 1, replace = TRUE)
  
  stats = coefs$estimate[1] + coefs$estimate[2] * randAge + 
          coefs$estimate[3] * randSex + coefs$estimate[4] * randCp +
          coefs$estimate[5] * randTrest + coefs$estimate[6] * randChol +
          coefs$estimate[7] * randFbs + coefs$estimate[8] * randEcg +
          coefs$estimate[9] * randThalach + coefs$estimate[10] * randEx +
          coefs$estimate[11] * randOld + coefs$estimate[12] * randSlope +
          coefs$estimate[13] * randCa + coefs$estimate[14] * randThal
  
  prob = 1 / (1 + exp(-stats))
  
  if(prob > 0.5){
    diseased = diseased + 1
  }
}
probHeart = diseased/sim
print(probHeart)
## [1] 0.462
flush.console()

Evaluation using the formula

Now we will use the formula \[ P = \frac{Number\ of\ people\ with\ heart\ conditions}{Total\ number\ of\ people}\] to find out the actual probability that someone has heart disease.

## [1] 0.4612795

As we can see, this value 0.46128 is quite close to the one we obtained by running a Monte Carlo Simulation.

Results

We have demonstrated that Monte Carlo methods can accurately estimate real-world probabilities. Our simulation of 20,000 random patients yielded a heart disease probability of approximately 0.46, which closely matches the actual rate of 0.46128 in our dataset. This validates both our Monte Carlo approach and the Law of Large Numbers.

Some more interesting plots

Here are some more interesting plots related to our data. On the left, it shows how age differs between people with and without heart disease. On the right, we can see how the 3 key variables – Age, Cholesterol, and Blood Pressure – relate to heart disease: