Skip to content

Commit 0d0dbe3

Browse files
Matías Castillo AguilarMatías Castillo Aguilar
authored andcommitted
v0.1.1 release!
1 parent 2238783 commit 0d0dbe3

File tree

8 files changed

+1817
-10
lines changed

8 files changed

+1817
-10
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: writR
22
Title: Inferential statistics and reporting in APA style
3-
Version: 0.0.1
3+
Version: 0.1.1
44
Date: 2021-03-05
55
Authors@R:
66
person(given = "Matías",

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# Generated by roxygen2: do not edit by hand
22

3+
export(aov_r)
34
export(report)

R/aov.R

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#' ANOVA for factorial designs
2+
#'
3+
#' This is function let you perform automated inferential testing based on certain assumptions, some of which are tested automatically, then the propper test is perform, giving you an APA formated output with your statistical results.
4+
#'
5+
#' @param data Your dataset in long format, can have some missing values.
6+
#' @param response Response variable, numeric.
7+
#' @param between Quoted or unquoted variable indicating the between-subject(s) factor(s)/column(s) in data. Default is NULL indicating no between-subjects factors. Must be character vector if more than one between-subject(s) factor(s)/column(s) is specified.
8+
#' @param within Quoted or unquoted variable indicating the within-subject(s) factor(s)/column(s) in data. Default is NULL indicating no between-subjects factors. Must be character vector if more than one within-subject(s) factor(s)/column(s) is specified.
9+
#' @param id Quoted or unquoted variable (of length 1) indicating the subject identifier column in data.
10+
#' @param type The type of sums of squares for the ANOVA. Possible values are "II", "III", 2, or 3 (default).
11+
#' @param es The effect size used to estimate the effects of the factors on the response variable. Possible values are 'omega' or 'eta' (default).
12+
#' @param sphericity If `"none"`, then sphericity assumption is assumed to be met for within-subject(s) factor(s). "GG": applies Greenhouse-Geisser correction. "HF": applies Hyunh-Feldt correction. 'auto' (Default) choose the appropiate correction based on Mauchly test of sphericity (p-value > 0.05)
13+
#' @param markdown Whether you want the output formated for inline R Markdown or as plain text.
14+
#' @keywords aov_r
15+
#' @return A list with full statistical results, estimates and simple stats in APA style for each factor and interaction term(s).
16+
#' @export
17+
18+
aov_r <- function(data
19+
, response
20+
, between = NULL
21+
, within = NULL
22+
, id
23+
, type = 3
24+
, es = 'eta' # 'omega' (default) or 'eta'
25+
, sphericity = 'auto' # 'auto' (default), 'GG', 'HF' or 'none'
26+
, markdown = TRUE # FALSE for plain text
27+
) {
28+
29+
result <- list()
30+
response <- rlang::ensym(response)
31+
between <- if(grepl(',', deparse(substitute(between)))) between else rlang::ensym(between)
32+
within <- if(grepl(',', deparse(substitute(within)))) within else rlang::ensym(within)
33+
id <- rlang::ensym(id)
34+
35+
suppressMessages(
36+
suppressWarnings(model <- afex::aov_ez(id = as.character(id)
37+
, dv = as.character(response)
38+
, data = data
39+
, between = as.character(between)
40+
, within = as.character(within)
41+
, type = type) ) )
42+
43+
spher.test <- suppressWarnings(expr = { afex::test_sphericity(model) })
44+
sphericity <- if(sphericity == 'auto') {
45+
# Comprobación de esfericidad ----
46+
if( purrr::is_empty(spher.test) || all(spher.test[,2] > 0.05) ) {
47+
'none' } else { ges <- any(model$anova_table$ges <= 0.75)
48+
if(ges) { 'GG' } else { 'HF' } }
49+
} else if(purrr::is_empty(spher.test)) { 'none' } else { sphericity }
50+
51+
efs <- if(es == 'eta') { effectsize::eta_squared(model, ci = 0.95)
52+
} else if(es == 'omega') { effectsize::omega_squared(model, ci = 0.95)
53+
} else stop('You have to choose between "eta" or "omega"')
54+
55+
model <- anova(object = model, correction = sphericity)
56+
at <- attributes(model)
57+
class(model) <- 'data.frame'
58+
model <- within(model, {
59+
`num Df` <- round(`num Df`, digits = 2)
60+
`den Df` <- round(`den Df`, digits = 2)
61+
MSE <- round(MSE, digits = 2)
62+
F <- round(F, digits = 2)
63+
`Pr(>F)` <- ifelse(`Pr(>F)` < 0.001, '< 0.001', paste('=', round(`Pr(>F)`, 3) ) )
64+
})
65+
66+
efs[,-1] <- round(efs[,-1],2)
67+
at$correction <- if(at$correction == 'none') 'Fisher'
68+
et <- if(markdown) paste0('$\\',es,'$^2^ = ') else paste0(es,'^2 = ')
69+
70+
if(markdown) {
71+
# Formato en Markdown para R Markdown ----
72+
for(i in row.names(model)) {
73+
rt <- model[i,]
74+
j <- if (grepl(pattern = ':', i)) gsub(':', '_', i) else i
75+
result[['full']][[j]] <- paste0(
76+
stats <- paste0("*F* ~", at$correction
77+
, "~ (", rt$`num Df`
78+
,", ",rt$`den Df`
79+
,') = ',rt$F
80+
,', *p* ',rt$`Pr(>F)`), ', ',
81+
es <- paste0(et, efs[efs$Parameter == i, 2]
82+
,', CI~95%~[', efs[efs$Parameter == i,"CI_low"]
83+
,', ',efs[efs$Parameter == i, "CI_high"], ']') )
84+
result[['stats']][[j]] <- stats
85+
result[['es']][[j]] <- es
86+
}
87+
} else {
88+
# Formato en texto plano ----
89+
for(i in row.names(model)) {
90+
rt <- model[i,]
91+
j <- if (grepl(pattern = ':', i)) gsub(':', '_', i) else i
92+
result[['full']][[j]] <- paste0(
93+
stats <- paste0("F(", rt$`num Df`
94+
,", ",rt$`den Df`
95+
,') = ',rt$F
96+
,', p ',rt$`Pr(>F)`), ', ',
97+
es <- paste0(et, efs[efs$Parameter == i, 2]
98+
,', CI95% [', efs[efs$Parameter == i,"CI_low"]
99+
,', ',efs[efs$Parameter == i, "CI_high"], ']') )
100+
result[['stats']][[j]] <- stats
101+
result[['es']][[j]] <- es
102+
}
103+
}
104+
return(result)
105+
}

R/multpair.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ multpair <- function(data
113113

114114
if(markdown) {
115115
result[['full']] <- paste0(
116-
stats <- paste0('*F* ~Greenhouse-Geisser~ (', round(output[["num Df"]],1)
116+
stats <- paste0('*F* ~GG~ (', round(output[["num Df"]],1)
117117
, ', ', round(output[["den Df"]],1)
118118
, ') = ', round(output[["F"]],2)
119119
, ', *p* ',ifelse(output[["Pr(>F)"]] < 0.001, '< 0.001', paste(
@@ -147,7 +147,7 @@ multpair <- function(data
147147

148148
if(markdown) {
149149
result[['full']] <- paste0(
150-
stats <- paste0('*F* ~Huynh-Feldt~ (', round(output[["num Df"]],1)
150+
stats <- paste0('*F* ~HF~ (', round(output[["num Df"]],1)
151151
, ', ', round(output[["den Df"]],1)
152152
, ') = ', round(output[["F"]],2)
153153
, ', *p* ',ifelse(output[["Pr(>F)"]] < 0.001, '< 0.001', paste(

README.Rmd

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,62 @@ result
9494

9595
The core function: `report` by default return a list of length two in Markdown format (as seen before) for inline results. An example using same data as before:
9696

97-
The analysis of the effects of the treatment shows an statistically significant difference between the groups, `result$full`, evaluated through `result$method`.
97+
> The analysis of the effects of the treatment shows an statistically significant difference between the groups, `result$full`, evaluated through `result$method`.
9898
9999
translates into this:
100100

101-
The analysis of the effects of the treatment shows an statistically significant difference between the groups, *t* <sub>Student</sub> (98) = 2.509, *p* = 0.014, *d* <sub>Cohen's</sub> = 0.51, IC<sub>95%</sub> [0.1, 0.91], evaluated through Student's t-test for independent samples.
101+
> The analysis of the effects of the treatment shows an statistically significant difference between the groups, *t* <sub>Student</sub> (98) = 2.509, *p* = 0.014, *d* <sub>Cohen's</sub> = 0.51, CI<sub>95%</sub>[0.1, 0.91], evaluated through Student's t-test for independent samples.
102+
103+
## Mixed effects ANOVA
104+
105+
By using `aov_r` function is possible to get the statistical report of between/within-subject(s) factor(s) for factorial designs using `afex` package under the hood for statistical reporting. Let's see an example
106+
107+
```{r message=FALSE, warning=FALSE, paged.print=FALSE}
108+
# set parameters to simulate data with a between and within subject factor
109+
within <- 3
110+
between <- 2
111+
n <- 400
112+
113+
set.seed(123)
114+
Stroop <- data.frame(
115+
Subject = rep(1:n, within),
116+
Gender = gl(between, n/between, length = n*within, labels = c('Male','Female')),
117+
Time = gl(within, n, length = n*within),
118+
Score = rnorm(n*within, mean = 150, sd = 30))
119+
120+
# Manipulate data to generate interaction between Gender and Time
121+
Stroop <- within(Stroop, {
122+
Score[Gender == 'Male' & Time == 1] <- Score[Gender == 'Male' & Time == 1]*1
123+
Score[Gender == 'Male' & Time == 2] <- Score[Gender == 'Male' & Time == 2]*1.15
124+
Score[Gender == 'Male' & Time == 3] <- Score[Gender == 'Male' & Time == 3]*1.3
125+
Score[Gender == 'Female' & Time == 1] <- Score[Gender == 'Female' & Time == 1]*1
126+
Score[Gender == 'Female' & Time == 2] <- Score[Gender == 'Female' & Time == 2]*0.85
127+
Score[Gender == 'Female' & Time == 3] <- Score[Gender == 'Female' & Time == 3]*0.7
128+
})
129+
130+
131+
r <- aov_r(
132+
data = Stroop
133+
, response = Score
134+
, between = Gender
135+
, within = Time
136+
, id = Subject
137+
, es = 'omega' # omega squared as our measure of effect size
138+
, sphericity = 'auto' # check if sphericity is not being violated
139+
)
140+
141+
r
142+
```
143+
144+
For inline results with previous data we would do something like this:
145+
146+
> In order to analyze the effect of gender on subjects' scores in each of the evaluation periods, we performed an analysis of variance (ANOVA) with between- and within-subjects factors. From the analyses, we find that gender has a large effect ( `r$es$Gender` ) on scores when adjusting for each of the time periods, `r$stats$Gender`. In a similar way we find a significant interaction between evaluative time and gender ( `r$stats$Gender_Time` ), indicating unequal responses between males and females over time, `r$es$Gender_Time`, however, time alone is not able to explain statistically significantly the variance in scores, `r$full$Time`.
147+
148+
Which will translate into this after evaluation in R Markdown:
149+
150+
> In order to analyze the effect of gender on subjects' scores in each of the evaluation periods, we performed an analysis of variance (ANOVA) with between- and within-subjects factors. From the analyses, we find that gender has a large effect ( 𝜔<sup>2</sup> = 0.63, CI<sub>95%</sub>[0.58, 0.67] ) on scores when adjusting for each of the time periods, *F* <sub>Fisher</sub> (1, 398) = 682.91, *p* < 0.001. In a similar way we find a significant interaction between evaluative time and gender ( *F* <sub>Fisher</sub> (2, 796) = 223.68, *p* < 0.001 ), indicating unequal responses between males and females over time, 𝜔<sup>2</sup> = 0.27, CI<sub>95%</sub>[0.22, 0.32], however, time alone is not able to explain statistically significantly the variance in scores, *F* <sub>Fisher</sub> (2, 796) = 0.11, *p* = 0.894, 𝜔<sup>2</sup> = 0, CI<sub>95%</sub>[0, 0].
151+
152+
When you have more than 1 factor (between or within subjects) you have to specify them a character vector: `between = c('factor1', 'factor2' ...)`, and the same for `within = c('factor1', 'factor2' ...)`.
102153

103154
## Paired samples design
104155

README.md

Lines changed: 92 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
# writR: Inferential statistics and reporting in APA style
23

34
For automated and basic inferential testing.
@@ -25,7 +26,7 @@ citation('writR')
2526
## To cite package 'writR' in publications use:
2627
##
2728
## Matías Castillo Aguilar (2021). writR: Inferential statistics and
28-
## reporting in APA style. R package version 0.0.1.
29+
## reporting in APA style. R package version 0.1.1.
2930
## https://github.com/matcasti/writR
3031
##
3132
## A BibTeX entry for LaTeX users is
@@ -34,7 +35,7 @@ citation('writR')
3435
## title = {writR: Inferential statistics and reporting in APA style},
3536
## author = {Matías {Castillo Aguilar}},
3637
## year = {2021},
37-
## note = {R package version 0.0.1},
38+
## note = {R package version 0.1.1},
3839
## url = {https://github.com/matcasti/writR},
3940
## }
4041
```
@@ -122,11 +123,97 @@ result
122123

123124
The core function: `report` by default return a list of length two in Markdown format (as seen before) for inline results. An example using same data as before:
124125

125-
The analysis of the effects of the treatment shows an statistically significant difference between the groups, `result$full`, evaluated through `result$method`.
126+
> The analysis of the effects of the treatment shows an statistically significant difference between the groups, `result$full`, evaluated through `result$method`.
126127
127128
translates into this:
128129

129-
The analysis of the effects of the treatment shows an statistically significant difference between the groups, *t* <sub>Student</sub> (98) = 2.509, *p* = 0.014, *d* <sub>Cohen's</sub> = 0.51, IC<sub>95%</sub> [0.1, 0.91], evaluated through Student's t-test for independent samples.
130+
> The analysis of the effects of the treatment shows an statistically significant difference between the groups, *t* <sub>Student</sub> (98) = 2.509, *p* = 0.014, *d* <sub>Cohen's</sub> = 0.51, CI<sub>95%</sub>[0.1, 0.91], evaluated through Student's t-test for independent samples.
131+
132+
## Mixed effects ANOVA
133+
134+
By using `aov_r` function is possible to get the statistical report of between/within-subject(s) factor(s) for factorial designs using `afex` package under the hood for statistical reporting. Let's see an example
135+
136+
137+
```r
138+
# set parameters to simulate data with a between and within subject factor
139+
within <- 3
140+
between <- 2
141+
n <- 400
142+
143+
set.seed(123)
144+
Stroop <- data.frame(
145+
Subject = rep(1:n, within),
146+
Gender = gl(between, n/between, length = n*within, labels = c('Male','Female')),
147+
Time = gl(within, n, length = n*within),
148+
Score = rnorm(n*within, mean = 150, sd = 30))
149+
150+
# Manipulate data to generate interaction between Gender and Time
151+
Stroop <- within(Stroop, {
152+
Score[Gender == 'Male' & Time == 1] <- Score[Gender == 'Male' & Time == 1]*1
153+
Score[Gender == 'Male' & Time == 2] <- Score[Gender == 'Male' & Time == 2]*1.15
154+
Score[Gender == 'Male' & Time == 3] <- Score[Gender == 'Male' & Time == 3]*1.3
155+
Score[Gender == 'Female' & Time == 1] <- Score[Gender == 'Female' & Time == 1]*1
156+
Score[Gender == 'Female' & Time == 2] <- Score[Gender == 'Female' & Time == 2]*0.85
157+
Score[Gender == 'Female' & Time == 3] <- Score[Gender == 'Female' & Time == 3]*0.7
158+
})
159+
160+
161+
r <- aov_r(
162+
data = Stroop
163+
, response = Score
164+
, between = Gender
165+
, within = Time
166+
, id = Subject
167+
, es = 'omega' # omega squared as our measure of effect size
168+
, sphericity = 'auto' # check if sphericity is not being violated
169+
)
170+
171+
r
172+
```
173+
174+
```
175+
## $full
176+
## $full$Gender
177+
## [1] "*F* ~Fisher~ (1, 398) = 682.91, *p* < 0.001, $\\omega$^2^ = 0.63, CI~95%~[0.58, 0.67]"
178+
##
179+
## $full$Time
180+
## [1] "*F* ~Fisher~ (2, 796) = 0.11, *p* = 0.894, $\\omega$^2^ = 0, CI~95%~[0, 0]"
181+
##
182+
## $full$Gender_Time
183+
## [1] "*F* ~Fisher~ (2, 796) = 223.68, *p* < 0.001, $\\omega$^2^ = 0.27, CI~95%~[0.22, 0.32]"
184+
##
185+
##
186+
## $stats
187+
## $stats$Gender
188+
## [1] "*F* ~Fisher~ (1, 398) = 682.91, *p* < 0.001"
189+
##
190+
## $stats$Time
191+
## [1] "*F* ~Fisher~ (2, 796) = 0.11, *p* = 0.894"
192+
##
193+
## $stats$Gender_Time
194+
## [1] "*F* ~Fisher~ (2, 796) = 223.68, *p* < 0.001"
195+
##
196+
##
197+
## $es
198+
## $es$Gender
199+
## [1] "$\\omega$^2^ = 0.63, CI~95%~[0.58, 0.67]"
200+
##
201+
## $es$Time
202+
## [1] "$\\omega$^2^ = 0, CI~95%~[0, 0]"
203+
##
204+
## $es$Gender_Time
205+
## [1] "$\\omega$^2^ = 0.27, CI~95%~[0.22, 0.32]"
206+
```
207+
208+
For inline results with previous data we would do something like this:
209+
210+
> In order to analyze the effect of gender on subjects' scores in each of the evaluation periods, we performed an analysis of variance (ANOVA) with between- and within-subjects factors. From the analyses, we find that gender has a large effect ( `r$es$Gender` ) on scores when adjusting for each of the time periods, `r$stats$Gender`. In a similar way we find a significant interaction between evaluative time and gender ( `r$stats$Gender_Time` ), indicating unequal responses between males and females over time, `r$es$Gender_Time`, however, time alone is not able to explain statistically significantly the variance in scores, `r$full$Time`.
211+
212+
Which will translate into this after evaluation in R Markdown:
213+
214+
> In order to analyze the effect of gender on subjects' scores in each of the evaluation periods, we performed an analysis of variance (ANOVA) with between- and within-subjects factors. From the analyses, we find that gender has a large effect ( 𝜔<sup>2</sup> = 0.63, CI<sub>95%</sub>[0.58, 0.67] ) on scores when adjusting for each of the time periods, *F* <sub>Fisher</sub> (1, 398) = 682.91, *p* < 0.001. In a similar way we find a significant interaction between evaluative time and gender ( *F* <sub>Fisher</sub> (2, 796) = 223.68, *p* < 0.001 ), indicating unequal responses between males and females over time, 𝜔<sup>2</sup> = 0.27, CI<sub>95%</sub>[0.22, 0.32], however, time alone is not able to explain statistically significantly the variance in scores, *F* <sub>Fisher</sub> (2, 796) = 0.11, *p* = 0.894, 𝜔<sup>2</sup> = 0, CI<sub>95%</sub>[0, 0].
215+
216+
When you have more than 1 factor (between or within subjects) you have to specify them a character vector: `between = c('factor1', 'factor2' ...)`, and the same for `within = c('factor1', 'factor2' ...)`.
130217

131218
## Paired samples design
132219

@@ -358,7 +445,7 @@ library(deepdep)
358445
plot_dependencies('writR', local = TRUE, depth = 3)
359446
```
360447

361-
![](README_files/figure-html/unnamed-chunk-7-1.svg)<!-- -->
448+
![](README_files/figure-html/unnamed-chunk-8-1.svg)<!-- -->
362449

363450
## Acknowledgments
364451

0 commit comments

Comments
 (0)