```{r setup, include=FALSE} knitr::opts_chunk$set(include = FALSE) knitr::opts_knit$set(root.dir = "/work/CogSci_Methods01/Assign_03_data/") ``` ```{r install/load packages, include = FALSE} pacman::p_load(tidyverse, pastecs, WRS2, conflicted, stringi, stringr, gridExtra, Hmisc, broom, reticulate) ``` ```{r loading and anonymizing using the script from exercise 7, include = FALSE} # checks whether randomization has already been done: if not, run anonymization. if (is_empty(list.files(path = getwd(), pattern = "*logfile_snew*", full.names = T))){ files <- list.files(path = getwd(), pattern = "*logfile_*", full.names = T) data_out <- list() # determines number of files. num_files <- length(files) # randomly shuffles integers in range 1:num_files. rand_ids <- sample(seq(1,num_files,1)) # initializes file counter. cnt_f <- 0 # loops through files. for (f in files){ # updates counter. cnt_f <- cnt_f + 1 # reads current CSV file. data_out[[f]] <- read_csv(file = f, col_names = TRUE) # generates new random ID ("sXX", where XX is number from rand_ids) data_out[[f]]$ID <- paste(c("snew", rand_ids[cnt_f]), collapse = "") # removes column with timestamp (if there is one). data_out[[f]] <- subset(data_out[[f]], select = -c(TimeStamp)) # defines new output file name. out_name <- paste(c(getwd(), "/logfile_", unique(data_out[[f]]$ID[1]), ".csv"), collapse = "") # writes this CSV file. write_csv(data_out[[f]], out_name, na = "NA") # now delete original file. file.remove(f) } } ``` ```{r load data and braid files into one, using the script from exercise 7, include = FALSE} #The output of this script are the individual files, just anonymized. files <- list.files(path = getwd(), pattern = "*logfile_snew*", full.names = T) data <- map_dfr(files, read_csv) ?map_dfr # map_dfr() and map_dfc() return a data frame created by row-binding and column-binding respectively. They require dplyr to be installed. ``` ```{r prep_data_for_tests: making sure condition and ID are factors, message = FALSE} # Before running the analysis, we will make modifications to the data-frame: converting the data frame to tibble, renaming columns, and changing ID and Condition variables to factors. We also relevel the levels in the SoundCondition factor variable, setting the reference level to our baseline condition (silence in headphones). This will be important when doing a post-hoc linear model. # converting to tibble data <- as.tibble(data) # renaming columns data <- data %>% dplyr::rename(TrialNumber = "...1", WordCategory = "Word-Condition", SoundCondition = "Sound-Condition") # changing class of certain variables data$SoundCondition <- as.factor(data$SoundCondition) data$ID <- as.factor(data$ID) # releveling the levels in the data (setting baseline condition 'C' as the reference level) data <- data %>% dplyr::mutate(SoundConditionRelevel = relevel(SoundCondition, ref = 'C')) # checking levels levels(data$SoundConditionRelevel) # examining the data head(data) ``` ```{r} # renaming conditions within SoundCondition column data$SoundCondition <- stringr::str_replace_all(data$SoundCondition, "C", "No noise") data$SoundCondition <- stringr::str_replace_all(data$SoundCondition, "A", "High volume") data$SoundCondition <- stringr::str_replace_all(data$SoundCondition, "B", "Low volume") ``` ```{r Initial descriptive stats, message = FALSE} # Running initial descriptive statistics (visualizations and computations) to get an overview of the data. # aggregating data to one data point pr. participants aggregateddata <- aggregate(RT ~ SoundCondition + ID + Age + Gender, data = data, mean) # assessing the distribution of participants between the conditions table(aggregateddata$SoundCondition) # checking the mean RT for each condition group data %>% group_by(SoundCondition) %>% dplyr::summarize(M = mean(RT), SD = sd(RT)) # plotting the RT by condition group as box-plots (including a mean-point) data %>% ggplot(aes(x = SoundCondition, y = RT, fill = SoundCondition)) + geom_boxplot() + theme_minimal() + scale_fill_brewer(palette = 'PuOr') + stat_summary(fun = mean, geom = "point", shape = 23) # plotting the RT data as scatter plot ggplot(data, aes(ID, RT, color = SoundCondition)) + geom_point() + scale_color_brewer(palette = 'Accent')+ guides(x = guide_axis(angle = 90)) ``` ```{r ANOVA test 1, message = FALSE} # Running a one-way ANOVA test to examine if there is a difference between the means of the three experimental conditions. # making ANOVA model rt_condition.aov <- aov(RT ~ SoundConditionRelevel, data = data) # retriving results from the model summary(rt_condition.aov) ``` ```{r checking residuals for assumptions of normality and equal variance, message = FALSE} # We run visual diagnostics to assess normality and equal variance for the residuals of the predictor variable. Since our data was obtained by using a randomized design, it already meets the last assumption of independence. # creating plot matrix par(mfrow = c(1, 3)) # plot 1: histogram (assessing normality) hist(residuals(rt_condition.aov), col = 'orange') # plot 2: Q-Q plot (assessing normality) plot(rt_condition.aov, 2) #plot 3: residual plot (assessing equal variance) plot(rt_condition.aov, 1) # Bartlett.test bartlett.test(RT ~ SoundConditionRelevel, data=data) #Both the histogram and QQ-plot indicates a non-normal distribution of the residuals: the histogram is skewed, and the QQ-plot deviates from the normal-distribution line towards the extreme values. This is problematic, since the ANOVA assumes normal distribution of residuals for the predictor variable. # The evidence for equal variance is more ambiguous: The residual vs. fitted plot doesn't indicate a large variance in spread of residuals across categories (although the baseline category has a smaller variation, possibly due to the larger sample size). However, the data fails the Bartlett test of homogeneity of variances (p < 0.05). Ultimately, the plot doesn't indicate a huge violation of homoscedasticity, and we will continue with this assumption. # One thing to note is that the residual vs. fitted plot show some clear outliers in the form of individual data points — these are potentially driving up the variance unnecessarily, and could be filtered out. # To potentially tackle the problem of normality, we log-transform the Reaction Time data: ``` ```{r log-transforming RT and running new assumption tests, message = FALSE} # adding column with log-transformed RT to data frame: data <- data %>% dplyr::mutate(logRT = log(RT)) # making new ANOVA model to input in the residual plots logRT_condition.aov <- aov(logRT ~ SoundConditionRelevel, data = data) # creating plot matrix par(mfrow = c(1, 2)) # plot 1, histogram hist(residuals(logRT_condition.aov), col = 'forest green') # plot 2, Q-Q plot qqnorm(residuals(logRT_condition.aov)) qqline(residuals(logRT_condition.aov)) # While the histogram resembles a normal distribution more closely, the QQ-plot still shows an abnormal distribution. Thus we will not assume normality, and proceed with a non-parametric test (Kruskal-Wallis test) to check difference between the means of the condition-groups. ``` ```{r Kruskal-Wallis test, message = FALSE} kruskal.test(RT ~ SoundConditionRelevel, data = data) # The Kruskal test shows a significant difference between the means of the sound condition groups (chi-squared = 11.075, p = 0.003937). We run a post-hoc Bonferroni test to find out which means differ: ``` ```{r post-hoc Bonferroni test, message = FALSE} pairwise.t.test(data$RT, data$SoundConditionRelevel, p.adjust.method = "bonferroni") # The Bonferroni test does not output any significant differences (p > 0.05) between any of the means. However, the difference between the baseline condition (C) and the loudest condition (A) has the difference closest to significance (p = 0.30). # One reason for the discrepancy between the significant result of the Kruskal test and the insignificant post-hoc test result could be lack of statistical power due to the small sample size (n = 12). A larger sample could potentially boost statistical power. ``` ```{r fitting linear models to test difference between means, message = FALSE} # fitting model rt_cond_model <- lm(RT ~ SoundConditionRelevel, data = data) # retrieving results summary(rt_cond_model) # retrieving and rounding intercept intercept <- round(rt_cond_model$coefficients[1], digits = 3) intercept # retrieving and rounding slope 1 (C -> A) slope1 <- round(rt_cond_model$coefficients[2], digits = 3) slope1 # retrieving and rounding slope 2 (C -> B) slope2 <- round(rt_cond_model$coefficients[3], digits = 3) slope2 ``` ### 1. Introduction (Amalie) Do different volumes of white noise affect the human brain’s attention and performance? Former attention studies suggest that the noise is beneficial for cognitive performance (Dalton and Behm, 2007). This is suggested because it can block disturbing noise and the sound can be comforting. Particularly this approach is the motivation for this experiment. More precisely, the intention of this study is to inspect whether white noise stimuli has a significant effect on the participants' reaction time in a simple reading classification task. If there is a relationship between white noise and performance, we would expect reaction time to be affected by the level of white noise. ### 2. Methods #### 2.1 Participants (Christian) For the experiment, 12 participants are recruited (7 females). All participants are native Danish speakers, except for one. However, they are all considered fluent in English. All participants are university students and have attended the experiment on a weekday after a 2h university lecture. The age range is 19-24 years old (mean age of 21 years old). Group A had a standard deviation of 0.568, group B had a standard deviation 0.727 and group C had a standard deviation of 0.448. #### 2.2 Materials/stimuli (Laura) The only equipment required to run the experiment is a Python script (Python v. 2022.2.4 and R v.4.2.0 was used in the experiment) providing both sound stimuli and the word classification task. All trials ran on the same computer with the same pair of over-ear headphones (Marshall Wired Major III On-Ear) set to the same volume level, and participants wore headphones regardless of their assigned condition. The sound stimuli were generated in Audacity v3.2.0. Using the noise-generator, two white noise stimuli of 10 minutes length with a relative volume difference of 18 dB were generated. In a similar fashion, a silence stimuli of 10 minutes length was generated. Each stimuli would only play for the duration of the experiment. #### 2.3 Procedure (Lelia) The experiment is a between-subject design with three conditions, which were randomly assigned to the participants using the random.choice function in PsychoPy. Notice that this way of randomly assigning participants does not ensure a balanced experiment with an equal number of participants in each condition. We worked with the following conditions: Condition A: High volume white noise Condition B: Low volume white noise Condition C: No noise (silence in headphones) Participants were not informed about the three different sound conditions before the experiment. Participants chose an ID and specified their age and gender. Through an introduction screen, participants were instructed to press the left arrow key when seeing a word they would classify as an animal, and the right arrow key when seeing a word they would classify as a vegetable/fruit. The 19 words were presented randomly one at a time in white letters on a black screen. The participants' reaction times and accuracy scores were stored as a CSV file. ### 3. Analysis (Yosuf) We ran statistical tests to test for significant differences between the condition groups. Visual diagnostics assessing normality and equal variance for residuals were run to determine whether to use ANOVA or the Kruskal-Wallis test. After settling on the Kruskal-Wallis test, an additional post-hoc test with the Bonferroni correction and a paired sample Wilcoxon-tests were run to determine which groups, if any, were significantly different from each other. We used the packages tidyverse, pastecs, WRS2, conflicted, stringi, stringr, gridExtra, Hmisc, and broom. We’re running version 4.2.0 of R. ### 4. Results (Amalie) A Kruskal-Wallis test showed that sound level of white noise significantly affects reaction time, H(2) = 11.075, p = 0.004. Participants who were tested under condition B (moderate noise level) (Mdn = 0.728) performed better than participants tested under condition A (loud noise) (Mdn = 0.884) and condition C (silence) (Mdn = 0.8). Post-hoc tests using a Bonferroni-adjusted alpha level of 0.017 (0.05/3) were used to compare all pairs of groups. The tests revealed that reaction times of participants tested under condition B were not significantly different from reaction times of participants tested under condition A or C (all p > 0.017). An alternative post-hoc test (pairwise wilcox test) found a significant difference for the RT variable between group C and A (p = 0.031) and group B and A (p < 0.007), with a insignificant difference between group B and C (p = 0.069). ```{r Boxplot and scatterplot, include = TRUE, echo = FALSE} # plotting the RT by condition group as box-plots (including a mean-point) data %>% ggplot(aes(x = SoundCondition, y = RT, fill = SoundCondition)) + geom_boxplot() + theme_minimal() + labs(title = "Plot 1: Boxplot describing the data") + scale_fill_brewer(palette = 'PuOr') + stat_summary(fun = mean, geom = "point", shape = 23) # plotting the RT data as scatter plot ggplot(data, aes(ID, RT, color = SoundCondition)) + geom_point() + labs(title = "Plot 2: Scatterplot showing the results") + scale_x_discrete(labels=c("s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "s12")) + scale_color_brewer(palette = 'Accent')+ guides(x = guide_axis(angle = 90)) ``` ### 5. Discussion (Christian) Following the Kruskal-Wallis test-results, there is a significant omnibus difference between the mean RT for the condition groups. The Wilcox test found specific significant differences between baseline and high volume condition as well as low volume condition and no noise condition. The differences between the means are visualized using a means plot: ```{r visualizing difference in means, include = TRUE, echo = FALSE} pacman::p_load(ggpubr) ggline(data, x = "SoundCondition", y = "RT", add = c("mean_se"), order = c("No noise", "High volume", "Low volume"), ylab = "RT", xlab = "SoundCondition", title = "Plot 3: Plot showing the means") ``` #### 5.1 Methodological reflections and suggestions for future improvements (Laura, Lelia & Yosuf) We found a discrepancy between the significant result of the Kruskal test and the insignificant post-hoc test results. This makes the interpretation of the effect of the experimental conditions ambiguous; should we reject or accept the null-hypothesis? This discrepancy could be due to a lack of statistical power as a result of the small sample size. A larger sample could potentially boost statistical power. Another reason for the discrepancy between the Kruskall test and the post-hoc test could be that the Bonferroni correction is very conservative. The more conservative the correction, the more likely it is that significant differences are rejected. An improvement that could be considered is the method for classifying stimulus using arrow keys. We had one participant accidentally mix between the arrow keys which gave them an inaccurate measure. If we were to conduct another experiment, a more supportive stimulus that indicates what key does what. Example of an improved stimulus: Looking at other similar studies it is common to not achieve significant results when testing whether noise affects attention and performance. A study by Dalton & Behm (2007) investigated the effects of noise and music on human performance. The study found that music might be beneficial for certain tasks, if it’s the right volume and tempo. The study concludes that the effect of music and noise is a very subjective debate that varies from person to person. This leads to the discussion whether it could have been interesting to include more personal information if the study was to be redone. It could be questions about the participants’ music preferences, how much they listen to music and on what volume. This could give the experiment another dimension, that also considered subjective variance. By blocking other sounds, white noise seems to be beneficial for one's concentration abilities. Former research has suggested that white noise releases tention and stress, if it's on the preferred volume (Othman et al., 2019). ### Litterature Dalton & Behm (2007): “Effects of noise and music on human and task performance: A systematic review”: https://content.iospress.com/download/occupational-ergonomics/oer00144?id=occupational-ergonomics%2Foer00144 Huang & Shih (2011): “Effects of noise and music on human and task performance: A systematic review”: https://content.iospress.com/download/work/wor01141?id=work%2Fwor01141 Othman et al. (2019): https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6819787/