This weeks data dive requires forming pairs of numeric data and doing some analysis with those pairs. The goal is to eventually run some confidence interval (CI) analysis on the pairs.
So, as always, we can begin by loading libraries and identifying the data set.
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.3.2
## Warning: package 'ggplot2' was built under R version 4.3.2
## Warning: package 'tidyr' was built under R version 4.3.2
## Warning: package 'readr' was built under R version 4.3.2
## Warning: package 'purrr' was built under R version 4.3.2
## Warning: package 'dplyr' was built under R version 4.3.2
## Warning: package 'stringr' was built under R version 4.3.2
## Warning: package 'forcats' was built under R version 4.3.2
## Warning: package 'lubridate' was built under R version 4.3.2
## ── 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.4.4 ✔ 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(purrr)
library(plotrix)
## Warning: package 'plotrix' was built under R version 4.3.2
library(readxl)
data0 <- read_excel("~/IUPUI/Research/Computational_Data/Updated_F23/F18-F23_Survey_Data2_Clean.xlsx")
view(data0)
With the data set defined, we are ready to move on to the first requirement.
The prompt for this data dive asks to create two pairs of numeric variables, with at least one column being created based on the others. It is important to keep in mind as well, that one variable needs to be explanatory and one needs to be responsive (i.e., independent and dependenyt variables, respectively).
Creating the new columns is fairly straightforward for this data as we are interested in the growth of certain skills. In the survey from which the data is gathered, undergraduate students are asked to provide a skill rating (1-10) for a variety of computational skills necessary in physics. So, in order to measure growth, a fairly obvious solution is to create new columns that measure growth for each skill and defined simply as the difference between the present and initial skill ratings.
Because there are 11 total skills measured, I will just create two new columns in the interest of time. Going a bit further, the first four skills measured are specific to programming languages, so I will just make growth columns for the fifth and sixth sills measured (“working with dimensionless quantities/rescaling a problem to eliminate units” and “testing cose to determine its overall correctness”, respectively).
Creating two columns to measure growth in skills 5 and 6 can be done by the following:
growth_data <-
data0 |>
mutate(data0, growth5 = Present5 - Initial5) |>
mutate(data0, growth6 = Present6 - Initial6)
view(growth_data)
The dataset “growth_data” now contains all of the information originally in the original dataset, but now includes two new columns that measure the growth in skills 5 and 6.
In order to build a relationship between variables, however, we cannot simply use the growth_data set because there are multiple surveys taken in the same overall_level, semester, and course. So instead, it would be better to simply average the growth data so that for each level and each semester, there is only one entry which allows us to actually build a independent/dependent variable pair.
So, let’s take our original data set and build a new one that will contain only the information we need (i.e., the average growth per level and the standard error in that growth):
avg_growth <-
growth_data |>
group_by(Overall_Level) |>
summarise(avg_growth5 = mean(growth5, na.rm=TRUE),
se_growth5 = std.error(growth5, na.rm=TRUE),
avg_growth6 = mean(growth6, na.rm=TRUE),
se_growth6 = std.error(growth6, na.rm=TRUE))
view(avg_growth)
Admittedly, this shrinks our dataset down to just four entries, but for the purpose of this data dive, it is the best way to build a relationship that fits the requirements while representing meaningful data.
The relationships are set for the independent (explanatory) variable to be the overall level and the dependent (response) variable to be the average growth in survey items 5 and 6. First, we can simply build a bar chart to show the growth per level and we can use the standard error as our error bars. The instructions for the data dive require an individual visualization for both, though it’s worth noting that both pairs could be shown on the same stacked bar plot.
First, let’s see the growth in skill 5:
plot5 <-
ggplot(avg_growth)+
geom_col(mapping = aes(x = as.character(Overall_Level), y = avg_growth5))+
geom_errorbar(mapping = aes(x=as.character(Overall_Level), ymin = (avg_growth5 - se_growth5), ymax = (avg_growth5 + se_growth5)))
plot5+
labs(title = "Growth: Dimensionless/Unitless Quantities")+
theme(plot.title = element_text(hjust = 0.5))
It is abundantly clear that as the level increases, the growth in this skill increases as well. While expected, it is worth noting that the growth between he 100 and 200 levels is essentially identical within overlapping error. This could be something to keep an eye on moving forward.
To find the growth in skill 6, we can use the same independent variable and make a similar plot to the one above:
plot6 <-
ggplot(avg_growth)+
geom_col(mapping = aes(x = as.character(Overall_Level), y = avg_growth6))+
geom_errorbar(mapping = aes(x=as.character(Overall_Level), ymin = (avg_growth6 - se_growth6), ymax = (avg_growth6 + se_growth6)))
plot6+
labs(title = "Growth: Testing Code")+
theme(plot.title = element_text(hjust = 0.5))
Again, we see the same general trend with some overlap in the errors again for the 100 and 200 level. This seems to suggest that while the overall level has an affect on the growth, the growth is more significant between the 300 and 200 levels as opposed to the 100 and 200 levels. While interesting, we would need to run an ANOVA test to see if the comparison between each level is statistically significant (but let’s save that for later).
The correlation coefficient can be calculated for each set of variables using Spearman’s Rho coefficient (based on given feedback). Instead of writing the code separately for each, lets just put it all together:
coeff_5 <- cor(avg_growth$Overall_Level, y = avg_growth$avg_growth5, method = "spearman")
coeff_6 <- cor(avg_growth$Overall_Level, y = avg_growth$avg_growth6, method = "spearman")
coeff_5
## [1] 1
coeff_6
## [1] 1
Both coefficients using Spearman’s Rho give values of 1, which is somewhat strange, but indicate very strong correlation between the two variables. It is very clear from the visualizations above that these coefficients would be relatively strong, although again, a value of 1 for each does give me some amount of pause.
While there are a few different methods to finding a confidence interval, based on prior feedback, it is best to simply use the mean growth and standard error, and using a z-score of 1.96. Beginning with the confidence intervals for the average growth in skill 5, the confidence intervals can be found by:
z <- 1.96
ci5_lower <- avg_growth$avg_growth5 - z*avg_growth$se_growth5
ci5_upper <- avg_growth$avg_growth5 + z*avg_growth$se_growth5
ci5_upper
## [1] 1.310443 1.487704 3.898904 5.765893
ci5_lower
## [1] 0.7935568 0.9823424 2.3233178 3.6254111
This gives the upper and lower bounds for the 95% confidence interval for the growth in skill 5 by overall level. It is worth noting that as the level increases, the confidence interval size increases as well (for example, the difference in the CI for the 100 level is ~0.5 while the CI difference for the 400 level is ~2). This makes sense as there are fewer responses for the 400 level, so the standard error is significantly larger, so based on these confidence intervals, it is clear that the “true” mean is better represented by the mean for the 100 level students than the 400 level students.
Repeating this process for the growth in skill 6 results in:
ci6_lower <- avg_growth$avg_growth6 - z*avg_growth$se_growth6
ci6_upper <- avg_growth$avg_growth6 + z*avg_growth$se_growth6
ci6_upper
## [1] 1.993875 2.403002 4.886896 6.080628
ci6_lower
## [1] 1.366125 1.698381 2.946438 3.571545
The confidence intervals for skill 6 show a similar trend to that seen in skill 5. The difference for the 100 and 200 level students is significantly smaller than the difference seen for the 300 and 400 level students, again serving to highlight the difference in amount of data available for each level of student.