Inference for numerical data

Author

Megan Vollbrecht

library(tidyverse)
Warning: package 'ggplot2' was built under R version 4.3.3
Warning: package 'tidyr' was built under R version 4.3.3
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.0     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ 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
library(openintro)
Loading required package: airports
Loading required package: cherryblossom
Loading required package: usdata
library(infer)
Warning: package 'infer' was built under R version 4.3.3
library(skimr)
Warning: package 'skimr' was built under R version 4.3.3
set.seed(61656)
data(yrbss)
glimpse(yrbss)
Rows: 13,583
Columns: 13
$ age                      <int> 14, 14, 15, 15, 15, 15, 15, 14, 15, 15, 15, 1…
$ gender                   <chr> "female", "female", "female", "female", "fema…
$ grade                    <chr> "9", "9", "9", "9", "9", "9", "9", "9", "9", …
$ hispanic                 <chr> "not", "not", "hispanic", "not", "not", "not"…
$ race                     <chr> "Black or African American", "Black or Africa…
$ height                   <dbl> NA, NA, 1.73, 1.60, 1.50, 1.57, 1.65, 1.88, 1…
$ weight                   <dbl> NA, NA, 84.37, 55.79, 46.72, 67.13, 131.54, 7…
$ helmet_12m               <chr> "never", "never", "never", "never", "did not …
$ text_while_driving_30d   <chr> "0", NA, "30", "0", "did not drive", "did not…
$ physically_active_7d     <int> 4, 2, 7, 0, 2, 1, 4, 4, 5, 0, 0, 0, 4, 7, 7, …
$ hours_tv_per_school_day  <chr> "5+", "5+", "5+", "2", "3", "5+", "5+", "5+",…
$ strength_training_7d     <int> 0, 0, 0, 0, 1, 0, 2, 0, 3, 0, 3, 0, 0, 7, 7, …
$ school_night_hours_sleep <chr> "8", "6", "<5", "6", "9", "8", "9", "6", "<5"…

#Exercise 1: What are the cases in this data set? How many cases are there in our sample?

The cases in this data set are highschoolers. There are 13,583 cases in our sample.

yrbss %>% 
  skim()
Data summary
Name Piped data
Number of rows 13583
Number of columns 13
_______________________
Column type frequency:
character 8
numeric 5
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
gender 12 1.00 4 6 0 2 0
grade 79 0.99 1 5 0 5 0
hispanic 231 0.98 3 8 0 2 0
race 2805 0.79 5 41 0 5 0
helmet_12m 311 0.98 5 12 0 6 0
text_while_driving_30d 918 0.93 1 13 0 8 0
hours_tv_per_school_day 338 0.98 1 12 0 7 0
school_night_hours_sleep 1248 0.91 1 3 0 7 0

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
age 77 0.99 16.16 1.26 12.00 15.00 16.00 17.00 18.00 ▁▂▅▅▇
height 1004 0.93 1.69 0.10 1.27 1.60 1.68 1.78 2.11 ▁▅▇▃▁
weight 1004 0.93 67.91 16.90 29.94 56.25 64.41 76.20 180.99 ▆▇▂▁▁
physically_active_7d 273 0.98 3.90 2.56 0.00 2.00 4.00 7.00 7.00 ▆▂▅▃▇
strength_training_7d 1176 0.91 2.95 2.58 0.00 0.00 3.00 5.00 7.00 ▇▂▅▂▅

##Exercise 2: How many observations are we missing weights from?

We are missing weights from 1004 observations.

yrbss1 <- yrbss %>% 
  mutate(physical_3plus = if_else(physically_active_7d > 2, "yes", "no"))
head(yrbss1)
# A tibble: 6 × 14
    age gender grade hispanic race                      height weight helmet_12m
  <int> <chr>  <chr> <chr>    <chr>                      <dbl>  <dbl> <chr>     
1    14 female 9     not      Black or African American  NA      NA   never     
2    14 female 9     not      Black or African American  NA      NA   never     
3    15 female 9     hispanic Native Hawaiian or Other…   1.73   84.4 never     
4    15 female 9     not      Black or African American   1.6    55.8 never     
5    15 female 9     not      Black or African American   1.5    46.7 did not r…
6    15 female 9     not      Black or African American   1.57   67.1 did not r…
# ℹ 6 more variables: text_while_driving_30d <chr>, physically_active_7d <int>,
#   hours_tv_per_school_day <chr>, strength_training_7d <int>,
#   school_night_hours_sleep <chr>, physical_3plus <chr>

##Exercise 3: Make a side-by-side violin plots of physical_3plus and weight. Is there a relationship between these two variables? What did you expect and why?

ggplot(data = yrbss1, aes(x = physical_3plus, y = weight)) + geom_violin()
Warning: Removed 1004 rows containing non-finite outside the scale range
(`stat_ydensity()`).

There doesn’t appear to be much of a difference between each of these plots. I would have expected those who were not physically active to weigh more than those who are.

yrbss2 <- yrbss1 |>
  filter(physical_3plus %in% c("no", "yes")) 
  
yrbss2 %>%
  group_by(physical_3plus) %>%
  summarise(mean_weight = mean(weight, na.rm = TRUE))
# A tibble: 2 × 2
  physical_3plus mean_weight
  <chr>                <dbl>
1 no                    66.7
2 yes                   68.4

##Exercise 4: Are all conditions necessary for inference satisfied? Comment on each. You can compute the group sizes with the summarize command above by defining a new variable with the definition n().

The conditions necessary for inference: 1. the distribution of the statistic is reasonably symmetric and bell-shaped 2. the sample size is reasonably large 3. the sample was representative of the population These conditions are met.

Excercise 5: Write the hypotheses for testing if the average weights are different for those who exercise at least times a week and those who don’t.

Ho = There is no difference in the average weights of those who exercise at least 3 times a week and those who do not.

Ha = There is a difference in the average weights of those who exercise at least 3 times a week and those who do not.

obs_diff <- yrbss2 %>%
  specify(weight ~ physical_3plus) %>%
  calculate(stat = "diff in means", order = c("yes", "no"))
Warning: Removed 946 rows containing missing values.
obs_diff
Response: weight (numeric)
Explanatory: physical_3plus (factor)
# A tibble: 1 × 1
   stat
  <dbl>
1  1.77
null_dist <- yrbss2 %>%
  specify(weight ~ physical_3plus) %>%
  hypothesize(null = "independence") %>%
  generate(reps = 1000, type = "permute") %>%
  calculate(stat = "diff in means", order = c("yes", "no"))
Warning: Removed 946 rows containing missing values.
null_dist
Response: weight (numeric)
Explanatory: physical_3plus (factor)
Null Hypothesis: independence
# A tibble: 1,000 × 2
   replicate       stat
       <int>      <dbl>
 1         1 -0.393    
 2         2 -0.379    
 3         3 -0.167    
 4         4  0.263    
 5         5  0.0000642
 6         6  0.00375  
 7         7  0.141    
 8         8 -0.732    
 9         9 -0.242    
10        10  0.270    
# ℹ 990 more rows
ggplot(data = null_dist, aes(x = stat)) +
  geom_vline(xintercept = c(-1.774584   , 1.774584), color = "blue", linetype = "dotted", linewidth=1) +
  geom_histogram()
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

##Exercise 6: Add a vertical red line to the plot above, demonstrating where the observed difference in means (obs_diff) falls on the distribution.

##Exercise 7: How many of these null_dist permutations have a difference at least as large (or larger) as obs_diff?

None of these seem to have a difference of this size.

null_dist %>%
  get_p_value(obs_stat = obs_diff, direction = "two_sided")
Warning: Please be cautious in reporting a p-value of 0. This result is an approximation
based on the number of `reps` chosen in the `generate()` step.
ℹ See `get_p_value()` (`?infer::get_p_value()`) for more information.
# A tibble: 1 × 1
  p_value
    <dbl>
1       0

##Exercise 8: What warning message do you get? Why do you think you get this warning message?

The warning I got was “Please be cautious in reporting a p-value of 0. This result is an approximation based on the number of reps chosen in the generate() step.” I think that I got this warning because there is never truly a 0% chance that the Ha is true, and it seems like a very unlikely p value to R.

##Exercise 9: Construct and record a confidence interval for the difference between the weights of those who exercise at least three times a week and those who don’t, and interpret this interval in context of the data.

percentile_ci <- null_dist %>% 
  get_confidence_interval(level = 0.95)
percentile_ci
# A tibble: 1 × 2
  lower_ci upper_ci
     <dbl>    <dbl>
1   -0.607    0.601

We are 95% confident that the true population difference in means for those who exercise 3 or more days a week and those who do not is between -.618 and 0.660.

##Excercise 10: Calculate a 95% confidence interval for the average height in meters (height) and interpret it in context.

l.model <- lm(height ~ 1, yrbss)
confint(l.model, level=0.95)
               2.5 %   97.5 %
(Intercept) 1.689411 1.693071

We are 95% confident that the true population mean height is between 1.689 and 1.693.

##Exercise 11: Calculate a new confidence interval for the same parameter at the 90% confidence level. Comment on the width of this interval versus the one obtained in the previous exercise.

confint(l.model, level=0.90)
                 5 %     95 %
(Intercept) 1.689705 1.692777

The width of this confidence interval is smaller than the previous example, as it leaves out more possibilities so we are less confident that the true population mean is contained within it.

##Exercise 12: Conduct a hypothesis test evaluating whether the average height is different for those who exercise at least three times a week and those who don’t.

null_dist1 <- yrbss2 %>%
  specify(height ~ physical_3plus) %>%
  hypothesize(null = "independence") %>%
  generate(reps = 1000, type = "permute") %>%
  calculate(stat = "diff in means", order = c("yes", "no"))
Warning: Removed 946 rows containing missing values.
null_dist1
Response: height (numeric)
Explanatory: physical_3plus (factor)
Null Hypothesis: independence
# A tibble: 1,000 × 2
   replicate       stat
       <int>      <dbl>
 1         1 -0.000625 
 2         2  0.00197  
 3         3 -0.000482 
 4         4 -0.0000872
 5         5 -0.000334 
 6         6  0.000981 
 7         7 -0.00371  
 8         8  0.000123 
 9         9  0.00191  
10        10 -0.000644 
# ℹ 990 more rows
obs_diff1 <- yrbss2 %>%
  specify(height ~ physical_3plus) %>%
  calculate(stat = "diff in means", order = c("yes", "no"))
Warning: Removed 946 rows containing missing values.
obs_diff1
Response: height (numeric)
Explanatory: physical_3plus (factor)
# A tibble: 1 × 1
    stat
   <dbl>
1 0.0376
ggplot(data = null_dist1, aes(x = stat)) +
  geom_vline(xintercept = c(-0.03762589 ,0.03762589), color = "blue", linetype = "dotted", linewidth=1) +
  geom_histogram()
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

From the histogram, it looks like the results are not independent as there are barely any here the difference is as large as the one observed. We reject the null hypothesis that there is no mean height difference between those who do exercise 3 or more times a week and those who do not.

##Exercise 13: Now, a non-inference task: Determine the number of different options there are in the dataset for the hours_tv_per_school_day there are.

possible <- unique(yrbss$hours_tv_per_school_day)
possible
[1] "5+"           "2"            "3"            "do not watch" "<1"          
[6] "4"            "1"            NA            

There are 8 options. Which are do not watch, <1 ,1,2,3,4,5+, and NA.

##Exercise 14: Come up with a research question evaluating the relationship between height or weight and sleep. Formulate the question in a way that it can be answered using a hypothesis test and/or a confidence interval. Report the statistical results, and also provide an explanation in plain language. Be sure to check all assumptions, state your αlevel, and conclude in context

Do high schoolers who sleep less than 6 hours a night weigh more?

yrbss3 <- yrbss %>% 
  mutate(sleep6plus = if_else(school_night_hours_sleep > 6, "yes", "no"))
yrbss4 <- yrbss3 |>
  filter(sleep6plus %in% c("no", "yes")) 
  
yrbss4 %>%
  group_by(sleep6plus) %>%
  summarise(mean_weight = mean(weight, na.rm = TRUE))
# A tibble: 2 × 2
  sleep6plus mean_weight
  <chr>            <dbl>
1 no                68.7
2 yes               67.2
obs_diff2 <- yrbss4 %>%
  specify(weight ~ sleep6plus) %>%
  calculate(stat = "diff in means", order = c("yes", "no"))
Warning: Removed 854 rows containing missing values.
obs_diff2
Response: weight (numeric)
Explanatory: sleep6plus (factor)
# A tibble: 1 × 1
   stat
  <dbl>
1 -1.50
null_dist2 <- yrbss4 %>%
  specify(weight ~ sleep6plus) %>%
  hypothesize(null = "independence") %>%
  generate(reps = 1000, type = "permute") %>%
  calculate(stat = "diff in means", order = c("yes", "no"))
Warning: Removed 854 rows containing missing values.
null_dist2
Response: weight (numeric)
Explanatory: sleep6plus (factor)
Null Hypothesis: independence
# A tibble: 1,000 × 2
   replicate    stat
       <int>   <dbl>
 1         1  1.00  
 2         2 -0.0678
 3         3 -0.106 
 4         4 -0.280 
 5         5 -0.380 
 6         6 -0.736 
 7         7  0.0691
 8         8 -0.198 
 9         9  0.606 
10        10 -0.122 
# ℹ 990 more rows
ggplot(data = null_dist2, aes(x = stat)) +
  geom_vline(xintercept = c(-1.50412    , 1.50412), color = "blue", linetype = "dotted", linewidth=1) +
  geom_histogram()
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

null_dist2 %>%
  get_p_value(obs_stat = obs_diff, direction = "two_sided")
Warning: Please be cautious in reporting a p-value of 0. This result is an approximation
based on the number of `reps` chosen in the `generate()` step.
ℹ See `get_p_value()` (`?infer::get_p_value()`) for more information.
# A tibble: 1 × 1
  p_value
    <dbl>
1       0

Because the p value is so low, we can reject the null hypothesis that there is not a difference in the average weight of those students who do get less than 6 hours of sleep on a school night and those who do not.