Run the three code blocks below to get the heart data set.
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.4
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.4.4 ✔ tibble 3.2.1
## ✔ lubridate 1.9.3 ✔ tidyr 1.3.0
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
heart <- read_csv('heart.csv')
## Rows: 303 Columns: 14
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## dbl (14): age, sex, cp, trestbps, chol, fbs, restecg, thalach, exang, oldpea...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(heart)
## # A tibble: 6 × 14
## age sex cp trestbps chol fbs restecg thalach exang oldpeak slope
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 63 1 3 145 233 1 0 150 0 2.3 0
## 2 37 1 2 130 250 0 1 187 0 3.5 0
## 3 41 0 1 130 204 0 0 172 0 1.4 2
## 4 56 1 1 120 236 0 1 178 0 0.8 2
## 5 57 0 0 120 354 0 1 163 1 0.6 2
## 6 57 1 0 140 192 0 1 148 0 0.4 1
## # ℹ 3 more variables: ca <dbl>, thal <dbl>, target <dbl>
Input code for and answer all prompts below.
heart %>%
ggplot(aes(x = chol)) +
geom_histogram()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#The distribution’s shape is right skewed
cor <- cor(heart[,1],heart[,8],use='complete',method='pearson')
cor
## thalach
## age -0.3985219
heart %>%
ggplot(aes(x=age,y=thalach)) +
geom_point()
#This correlation makes sense. Because as age increases, human’s physical functions and health reduce, therefore have lower heart rates.
t.test(chol ~ sex, data = heart)
##
## Welch Two Sample t-test
##
## data: chol by sex
## t = 3.0244, df = 134.39, p-value = 0.002985
## alternative hypothesis: true difference in means between group 0 and group 1 is not equal to 0
## 95 percent confidence interval:
## 7.617474 36.406982
## sample estimates:
## mean in group 0 mean in group 1
## 261.3021 239.2899
heart %>%
group_by(sex) %>%
summarise(mean_cholesterol = mean(chol))
## # A tibble: 2 × 2
## sex mean_cholesterol
## <dbl> <dbl>
## 1 0 261.
## 2 1 239.
#Because the p-value = 0.002985 < significance threshold 0.05, the results are statistically significant.
t.test(trestbps ~ target, data = heart, alternative = 'less')
##
## Welch Two Sample t-test
##
## data: trestbps by target
## t = 2.5083, df = 272.56, p-value = 0.9936
## alternative hypothesis: true difference in means between group 0 and group 1 is less than 0
## 95 percent confidence interval:
## -Inf 8.448315
## sample estimates:
## mean in group 0 mean in group 1
## 134.3986 129.3030
#The results are statistically significant,
#Because the p-value = 0.9936 > significance threshold 0.05, we can not reject the null hypothesis(H0).
#Because the null hypothesis(H0) is that true difference in means between group 0 and group 1 is equal or more than 0, and the alternative hypothesis(H1) is that true difference in means between group 0 and group 1 is less than 0, we reach the conclusion that true difference in means between group 0 and group 1 is equal or more than 0 (H0). Blood pressure is higher among those with heart disease.
sample_indexes <- sample(1:nrow(heart), size = nrow(heart) * 3/4)
heart_train <- heart[sample_indexes, ]
heart_test <- heart[-sample_indexes, ]
fit <- lm(trestbps ~ ., data = heart)
summary(fit)
##
## Call:
## lm(formula = trestbps ~ ., data = heart)
##
## Residuals:
## Min 1Q Median 3Q Max
## -35.522 -10.750 -1.928 10.413 56.525
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 86.92336 12.85367 6.763 7.51e-11 ***
## age 0.47413 0.12248 3.871 0.000134 ***
## sex -2.98074 2.25394 -1.322 0.187060
## cp 1.73933 1.08254 1.607 0.109210
## chol 0.01111 0.01966 0.565 0.572325
## fbs 6.68874 2.75185 2.431 0.015681 *
## restecg -1.92400 1.86127 -1.034 0.302140
## thalach 0.10257 0.05296 1.937 0.053752 .
## exang 1.55689 2.42349 0.642 0.521114
## oldpeak 2.16359 1.07255 2.017 0.044594 *
## slope 0.08129 1.98643 0.041 0.967384
## ca -0.37861 1.05455 -0.359 0.719836
## thal 0.42037 1.69244 0.248 0.804018
## target -4.32024 2.72833 -1.583 0.114407
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 16.5 on 289 degrees of freedom
## Multiple R-squared: 0.1531, Adjusted R-squared: 0.115
## F-statistic: 4.018 on 13 and 289 DF, p-value: 4.573e-06
#1. Statistically significant variables: age (because p_value 0.000134 < 0.05) fbs (because p_value 0.015681 < 0.05) oldpeak (because p_value 0.044594 < 0.05)
#2. Multiple R-squared: 0.1531 R^2=1-SSE/SST (SSE:error sum of squares, SST:total sum of squares)
#It refers to the goodness of fit, which is how well the regression line fits the observations. Its value is between 0 and 1, the closer to 1, the better the regression fitting effect. Because Multiple R-squared is 0.1531, the regression fits not well and is not a good prediction model.
fit_class <- glm(target ~ ., data = heart_train, family = binomial(link = 'logit'))
prediction_class <- ifelse(predict(fit_class, newdata = heart_test, type = 'response') < 0.5, 0, 1)
sum(heart_test$target == prediction_class)/length(prediction_class)
## [1] 0.8552632
#80.26316% of the time this model is accurate