Connect with me on Open Science Framework | Contact me via LinkedIn
Depending on your machine it might be necessary to use right-click -> open in new browser window.
R analysis script presenting the solutions for the exercise in Sensory Marketing regarding Girard et al. (2019). In one of the questions students are asked: How many respondents should one at minimum calculate for a replication of study 1’s results regarding perceived service value? Assumptions: equal split to scent vs. no scent conditions, \(\alpha\)=5%, \(\beta\)=5%, between-subjects ANOVA).
If this exercise grabs your attention, please check-out our study programs at the Chemnitz University of Technology by clicking on the logo (Germany):
Beware: R is a context-sensitive language. Thus, ‘data’ will be interpreted not in the same way as ‘Data’ will.
In R most functionality is provided by additional packages.
Most of the packages are well-documented, See: https://cran.r-project.org/
The code chunk below first evaluates if the package pacman is already installed to your machine. If yes, the corresponding package will be loaded. If not, R will install the package.
Alternatively, you can do this manually first by executing install.packages(“pacman”) and then library(pacman).
The second line then loads the package pacman
The third line uses the function p_load() from the pacman package to install (if necessary) and load all packages that we provide as arguments (e.g., pwr, which provides functions for power analysis).
if(!"pacman" %in% rownames(installed.packages())) install.packages("pacman")
library(pacman)
pacman::p_load(tidyverse, dplyr, pwr, tidyselect, compute.es, WebPower)
Here is the R session info which gives you information on my machine, all loaded packages and their version:
sessionInfo()
## R version 4.1.1 (2021-08-10)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 10 x64 (build 19043)
##
## Matrix products: default
##
## locale:
## [1] LC_COLLATE=German_Germany.1252 LC_CTYPE=German_Germany.1252
## [3] LC_MONETARY=German_Germany.1252 LC_NUMERIC=C
## [5] LC_TIME=German_Germany.1252
##
## attached base packages:
## [1] parallel stats graphics grDevices utils datasets methods
## [8] base
##
## other attached packages:
## [1] WebPower_0.6 PearsonDS_1.2 lavaan_0.6-9 lme4_1.1-27.1
## [5] Matrix_1.3-4 MASS_7.3-54 compute.es_0.2-5 tidyselect_1.1.1
## [9] pwr_1.3-0 forcats_0.5.1 stringr_1.4.0 dplyr_1.0.7
## [13] purrr_0.3.4 readr_2.0.1 tidyr_1.1.3 tibble_3.1.3
## [17] ggplot2_3.3.5 tidyverse_1.3.1 pacman_0.5.1
##
## loaded via a namespace (and not attached):
## [1] httr_1.4.2 sass_0.4.0 jsonlite_1.7.2 splines_4.1.1
## [5] tmvnsim_1.0-2 modelr_0.1.8 bslib_0.2.5.1 assertthat_0.2.1
## [9] stats4_4.1.1 cellranger_1.1.0 yaml_2.2.1 pbivnorm_0.6.0
## [13] pillar_1.6.2 backports_1.2.1 lattice_0.20-44 glue_1.4.2
## [17] digest_0.6.27 rvest_1.0.1 minqa_1.2.4 colorspace_2.0-2
## [21] htmltools_0.5.1.1 pkgconfig_2.0.3 broom_0.7.9 haven_2.4.3
## [25] scales_1.1.1 tzdb_0.1.2 generics_0.1.0 ellipsis_0.3.2
## [29] withr_2.4.2 cli_3.0.1 mnormt_2.0.2 magrittr_2.0.1
## [33] crayon_1.4.1 readxl_1.3.1 evaluate_0.14 fs_1.5.0
## [37] fansi_0.5.0 nlme_3.1-152 xml2_1.3.2 tools_4.1.1
## [41] hms_1.1.0 lifecycle_1.0.0 munsell_0.5.0 reprex_2.0.1
## [45] compiler_4.1.1 jquerylib_0.1.4 rlang_0.4.11 grid_4.1.1
## [49] nloptr_1.2.2.2 rstudioapi_0.13 rmarkdown_2.10 boot_1.3-28
## [53] codetools_0.2-18 gtable_0.3.0 DBI_1.1.1 R6_2.5.1
## [57] lubridate_1.7.10 knitr_1.33 utf8_1.2.2 stringi_1.6.2
## [61] Rcpp_1.0.7 vctrs_0.3.8 dbplyr_2.1.1 xfun_0.25
How many respondents should one at minimum calculate for a replication of study 1’s results regarding perceived service value? Assumptions: equal split to scent vs. no scent conditions, \(\alpha\)=5%, \(\beta\)=5%, between-subjects ANOVA)
We use an ANOVA here.
We have seen from our exercise that the program G*Power requires the effect size measure Cohen’s f (Cohen, 1988). The same hold for the pwr package, which we will, again, use to conduct power analysis in R. Therefore, we first need to convert information provided by the JSR article into a sample estimate of f.
Information the article provides:
“[…] and service value, Mscented = 3.69, SD = 1.37 versus Munscented = 3.05, SD = 1.38, F(1, 195) = 14.521, p < .001, \(\eta^{2}_{p}\) = .069, than those in the unscented condition, […]”
From this we are able to extract:
This is all that we need to first calculate the observed effect size Cohen’s f (Cohen, 1988). According the Cohen (1988, p. 281) \(\eta^{2}_{p}\) can easily be converted to f by a simple formula: f= \(\sqrt{\frac{\eta^{2}}{1-\eta^{2}}}\) Therefore, we need to solve \(\sqrt{\frac{0.069}{1-0.069}}\)
We achieve this by using the next code chunk. Within this code chunk we use the sqrt() function (place the cursor in the function and press ‘F1’ to see help), which calculates the square root of a number. We feed this function with the value of \(\eta^{2}_{p}\)=0.069. We assign the results to an object that we call ‘Cohen_f.’
In the next line we call the object and simultaneously round the results to 4 digits. This is obtained by using the round() function.
Cohen_f <- sqrt(0.069 / (1 - 0.069))
round(Cohen_f, digits = 4)
## [1] 0.2722
We can see that the calculated effect size 0.2722 perfectly mirrors the one we have seen in the exercise slides using G*Power. A common classification for Cohen’s f is: [0.1 | 0.25[ - small effect, [0.25 | 0.4[ - medium effect, and [0.4 | 1] - large effect.
In the question we are asked for \(\beta\)=5%, which corresponds to a statistical power of 95%.
To estimate a minimum sample size n for the replication we apply the pwr.anova.test() function from the pwr package. This function needs us to provide 5 arguments to fill its parameters. These are (see help by pressing ‘F1’):
The function, furthermore, assumes us to set one of these arguments to NULL. By doing so, we tell the function to use the remaining 4 parameters to search for the value of the fifth. In our case, we are searching for ‘n,’ therefore, we set ‘n=NULL.’
We assign the results of our power analysis to a new object named ‘results.’ Then we call for its content.
results <- pwr.anova.test(k = 2, n = NULL, f = Cohen_f, sig.level = 0.05, power = 0.95)
results
Balanced one-way analysis of variance power calculation
k = 2
n = 88.63934
f = 0.2722386
sig.level = 0.05
power = 0.95
NOTE: n is number in each group
We can see that the calculated sample size per group 88.6393365 only closely mirrors the one we have seen in G*Power 3 (Faul et al., 2007) at n=89. We have to round upwards to end up with 89. For the total sample size, we just multiply by 2, which gives 178.
In a last step we can visualize the relationship between the expected statistical power and different sample sizes.
For this purpose we apply the plot() function with the ‘results’ object and a catchy label for the x-axes as arguments.
plot(results, xlab = "sample size")
From this plot we can alternatively extract the same information for sample size planning.