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 not statistically significant. We fail to reject the null hypothesis. There is insufficient evidence to conclude that resting blood pressure is higher among individuals 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_train)
summary(fit)
##
## Call:
## lm(formula = trestbps ~ ., data = heart_train)
##
## Residuals:
## Min 1Q Median 3Q Max
## -34.531 -11.214 -2.583 10.220 52.703
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 82.27851 14.69977 5.597 6.66e-08 ***
## age 0.48965 0.14343 3.414 0.000767 ***
## sex -2.98269 2.68222 -1.112 0.267383
## cp 3.09584 1.26592 2.446 0.015276 *
## chol 0.03750 0.02420 1.549 0.122797
## fbs 5.31727 3.01292 1.765 0.079026 .
## restecg -1.60514 2.22819 -0.720 0.472082
## thalach 0.10656 0.05999 1.776 0.077120 .
## exang 0.18955 2.73809 0.069 0.944875
## oldpeak 1.06635 1.28801 0.828 0.408649
## slope -1.47851 2.34178 -0.631 0.528479
## ca 0.57162 1.22524 0.467 0.641308
## thal 0.57033 1.91458 0.298 0.766080
## target -6.66474 3.16091 -2.108 0.036158 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 16.26 on 213 degrees of freedom
## Multiple R-squared: 0.1971, Adjusted R-squared: 0.1481
## F-statistic: 4.023 on 13 and 213 DF, p-value: 6.688e-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.8157895
#81.57895% of the time this model is accurate