Let’s suppose that we have a two-way experiment (i.e. with two factors) that requires us to do different Tukey’s tests for different levels of a factor.
The following dataset represents the result of a series of experiments for measuring the battery discharge time at different temperatures and for different dielectric material used in the batteries:
knitr::opts_chunk$set(fig.align ="center",# This for default deviceout.width ="12cm",# This two for high quality charts:fig.asp =9/16)df <-read.table("https://paolobosetti.quarto.pub/data/battery.dat",comment ="#",header =TRUE) %>%mutate(Temperature =factor(Temperature),Material =factor(LETTERS[Material])) %>%select(!(RunOrder:StandardOrder))df %>%pivot_wider(names_from = Temperature, values_from = Response) %>%rename_with( ~paste0(., "°C"), `15`:`125`) %>% knitr::kable()
Material
Repeat
15°C
70°C
125°C
A
1
130
34
20
B
1
150
136
25
C
1
138
174
96
A
2
155
40
70
B
2
188
122
70
C
2
110
120
104
A
3
74
80
82
B
3
159
106
58
C
3
168
150
82
A
4
180
75
58
B
4
126
115
45
C
4
160
139
60
Let’s plot the data, with bars ranging from minimum to maximum values:
Now res is a list with three elements: res[["15"]], res[["70"]] e res[["125"]]. Each element in turn has one element, which holds a matrix with the data we need to make the plot. For example:
but repeated for the other two levels of Temperature.
I can do this using the purrr::reduce() function, which is similar to map(), but accumulates the elements of the list it operates on into a container specified by the .init parameter, which we set initially to an empty tibble:
names(res) %>%reduce( # needs two-args function.init =tibble(), # initial accumulatorfunction(tbl, key) { # key is the Temp levelbind_rows( tbl, # tbl is the accumulator res[[key]][[1]] %>%# extract the matrixfortify() %>%# convert to tibblerownames_to_column("pair") %>%add_column(T = key, .before ="pair") # add the T column ) }) %>%mutate(Significant =`p adj`< alpha) %>% knitr::kable()
T
pair
diff
lwr
upr
p adj
Significant
15
B-A
21.00
-70.203952
112.20395
0.6633090
FALSE
15
C-A
9.25
-81.953952
100.45395
0.9205830
FALSE
15
C-B
-11.75
-102.953952
79.45395
0.8756855
FALSE
70
B-A
62.50
7.647739
117.35226
0.0045670
TRUE
70
C-A
88.50
33.647739
143.35226
0.0004209
TRUE
70
C-B
26.00
-28.852261
80.85226
0.2177840
FALSE
125
B-A
-8.00
-67.947867
51.94787
0.8673817
FALSE
125
C-A
28.00
-31.947867
87.94787
0.2261123
FALSE
125
C-B
36.00
-23.947867
95.94787
0.1062483
FALSE
Now I can plot the data. This time I am using the purrr shortcut for the inline function, replacing the function(tbl, key) {...} with ~ {...}:
The plot shows that the only two cases where the dielectric material actually makes a significant difference in the battery discharge time are the B-A and C-A differences at 70°C.