I want the re order my tukeyHSD results comparison table, so that rcompanion::cldList() [@SalMangiafico] assigns letters in a specific order.
I am Looking at spicule (Sponge skeleton) variation between a heavily nested model. I have produced a plot for this model :
I am wanting CldList to assign letters in the following order to match my plot and have first bar staring with a :
desired_order <- c(
"Summer:Beggers:Mid", "Summer:Beggers:Low",
"Winter:Beggers:Mid", "Winter:Beggers:Low",
"Summer:Looe:Mid", "Summer:Looe:Low",
"Winter:Looe:Mid", "Winter:Looe:Low",
"Summer:Noss:Mid", "Summer:Noss:Low",
"Winter:Noss:Mid", "Winter:Noss:Low"
)"
Here is my TukeyHSD results in a comparison and p-value table ready for cldlist() which in my code is referred to as length_df:
edit : Had to remove some stuff to fit character limit: TukeyHSD output is given below as 'length_tukey2'
I've tried many different methods, and none worked.
# Define the desired order of comparisons
desired_order <- c(
"Summer:Beggers:Mid", "Summer:Beggers:Low",
"Winter:Beggers:Mid", "Winter:Beggers:Low",
"Summer:Looe:Mid", "Summer:Looe:Low",
"Winter:Looe:Mid", "Winter:Looe:Low",
"Summer:Noss:Mid", "Summer:Noss:Low",
"Winter:Noss:Mid", "Winter:Noss:Low"
)
# Create the data frame with the 'Comparison' column ordered according to the desired order
length_df <- data.frame(
Comparison = names(length_tukey_results[, "p adj"]),
P.adj = as.vector(length_tukey_results[, "p adj"])
)
# Reorder the data frame based on the desired order
length_df$Comparison <- factor(length_df$Comparison, levels = desired_order)
length_df <- length_df[order(length_df$Comparison), ]
length_df$Comparison
# Define the exact desired order of comparisons
desired_order <- c(
"Summer.Beggers.Mid-Summer.Beggers.Low",
"Summer.Beggers.Mid-Winter.Beggers.Low",
"Summer.Beggers.Mid-Summer.Looe.Mid",
"Summer.Beggers.Mid-Winter.Looe.Mid",
"Summer.Beggers.Mid-Summer.Noss.Mid",
"Summer.Beggers.Mid-Winter.Noss.Mid",
"Summer.Beggers.Mid-Summer.Looe.Low",
"Summer.Beggers.Mid-Winter.Looe.Low",
"Summer.Beggers.Mid-Summer.Noss.Low",
"Summer.Beggers.Mid-Winter.Noss.Low",
"Summer.Beggers.Low-Summer.Beggers.Mid",
"Summer.Beggers.Low-Winter.Beggers.Mid",
"Summer.Beggers.Low-Summer.Looe.Mid",
"Summer.Beggers.Low-Winter.Looe.Mid",
"Summer.Beggers.Low-Summer.Noss.Mid",
"Summer.Beggers.Low-Winter.Noss.Mid",
"Summer.Beggers.Low-Summer.Looe.Low",
"Summer.Beggers.Low-Winter.Looe.Low",
"Summer.Beggers.Low-Summer.Noss.Low",
"Summer.Beggers.Low-Winter.Noss.Low",
"Winter.Beggers.Mid-Summer.Beggers.Mid",
"Winter.Beggers.Mid-Summer.Looe.Mid",
"Winter.Beggers.Mid-Winter.Looe.Mid",
"Winter.Beggers.Mid-Summer.Noss.Mid",
"Winter.Beggers.Mid-Winter.Noss.Mid",
"Winter.Beggers.Mid-Summer.Looe.Low",
"Winter.Beggers.Mid-Winter.Looe.Low",
"Winter.Beggers.Mid-Summer.Noss.Low",
"Winter.Beggers.Mid-Winter.Noss.Low",
"Winter.Beggers.Low-Summer.Beggers.Mid",
"Winter.Beggers.Low-Winter.Beggers.Mid",
"Winter.Beggers.Low-Summer.Looe.Mid",
"Winter.Beggers.Low-Winter.Looe.Mid",
"Winter.Beggers.Low-Summer.Noss.Mid",
"Winter.Beggers.Low-Winter.Noss.Mid",
"Winter.Beggers.Low-Summer.Beggers.Low",
"Summer.Looe.Mid-Summer.Beggers.Mid",
"Summer.Looe.Mid-Winter.Beggers.Mid",
"Summer.Looe.Mid-Summer.Looe.Mid",
"Summer.Looe.Mid-Winter.Looe.Mid",
"Summer.Looe.Mid-Summer.Noss.Mid",
"Summer.Looe.Mid-Winter.Noss.Mid",
"Summer.Looe.Mid-Summer.Looe.Low",
"Summer.Looe.Mid-Winter.Looe.Low",
"Summer.Looe.Mid-Summer.Noss.Low",
"Summer.Looe.Mid-Winter.Noss.Low",
"Summer.Looe.Low-Summer.Beggers.Mid",
"Summer.Looe.Low-Winter.Beggers.Mid",
"Summer.Looe.Low-Summer.Looe.Mid",
"Summer.Looe.Low-Winter.Looe.Mid",
"Summer.Looe.Low-Summer.Noss.Mid",
"Summer.Looe.Low-Winter.Noss.Mid",
"Summer.Looe.Low-Summer.Looe.Low",
"Summer.Looe.Low-Winter.Looe.Low",
"Summer.Looe.Low-Summer.Noss.Low",
"Summer.Looe.Low-Winter.Noss.Low",
"Summer.Looe.Low-Summer.Beggers.Low",
"Summer.Looe.Low-Winter.Beggers.Low",
"Winter.Looe.Mid-Summer.Beggers.Mid",
"Winter.Looe.Mid-Summer.Looe.Mid",
"Winter.Looe.Mid-Winter.Looe.Mid",
"Winter.Looe.Mid-Summer.Noss.Mid",
"Winter.Looe.Mid-Winter.Noss.Mid",
"Winter.Looe.Mid-Summer.Looe.Low",
"Winter.Looe.Mid-Winter.Looe.Low",
"Winter.Looe.Mid-Summer.Noss.Low",
"Winter.Looe.Mid-Winter.Noss.Low",
"Winter.Looe.Mid-Winter.Beggers.Mid",
"Winter.Looe.Low-Summer.Beggers.Mid",
"Winter.Looe.Low-Summer.Looe.Mid",
"Winter.Looe.Low-Winter.Looe.Mid",
"Winter.Looe.Low-Summer.Noss.Mid",
"Winter.Looe.Low-Winter.Noss.Mid",
"Winter.Looe.Low-Summer.Looe.Low",
"Winter.Looe.Low-Winter.Looe.Low",
"Winter.Looe.Low-Summer.Noss.Low",
"Winter.Looe.Low-Winter.Noss.Low",
"Winter.Looe.Low-Summer.Beggers.Low",
"Winter.Looe.Low-Winter.Beggers.Mid",
"Winter.Looe.Low-Winter.Beggers.Low",
"Summer.Noss.Mid-Summer.Beggers.Mid",
"Summer.Noss.Mid-Winter.Beggers.Mid",
"Summer.Noss.Mid-Summer.Looe.Mid",
"Summer.Noss.Mid-Winter.Looe.Mid",
"Summer.Noss.Mid-Summer.Noss.Mid",
"Summer.Noss.Mid-Winter.Noss.Mid",
"Summer.Noss.Mid-Summer.Looe.Low",
"Summer.Noss.Mid-Winter.Looe.Low",
"Summer.Noss.Mid-Summer.Noss.Low",
"Summer.Noss.Mid-Winter.Noss.Low",
"Summer.Noss.Low-Summer.Beggers.Mid",
"Summer.Noss.Low-Winter.Beggers.Mid",
"Summer.Noss.Low-Summer.Looe.Mid",
"Summer.Noss.Low-Winter.Looe.Mid",
"Summer.Noss.Low-Summer.Noss.Mid",
"Summer.Noss.Low-Winter.Noss.Mid",
"Summer.Noss.Low-Summer.Looe.Low",
"Summer.Noss.Low-Winter.Looe.Low",
"Summer.Noss.Low-Summer.Noss.Low",
"Summer.Noss.Low-Winter.Noss.Low",
"Summer.Noss.Low-Summer.Beggers.Low",
"Summer.Noss.Low-Winter.Beggers.Low",
"Winter.Noss.Mid-Summer.Beggers.Mid",
"Winter.Noss.Mid-Summer.Looe.Mid",
"Winter.Noss.Mid-Winter.Looe.Mid",
"Winter.Noss.Mid-Summer.Noss.Mid",
"Winter.Noss.Mid-Winter.Noss.Mid",
"Winter.Noss.Mid-Summer.Looe.Low",
"Winter.Noss.Mid-Winter.Looe.Low",
"Winter.Noss.Mid-Summer.Noss.Low",
"Winter.Noss.Mid-Winter.Noss.Low",
"Winter.Noss.Mid-Winter.Beggers.Mid",
"Winter.Noss.Low-Summer.Beggers.Mid",
"Winter.Noss.Low-Summer.Looe.Mid",
"Winter.Noss.Low-Winter.Looe.Mid",
"Winter.Noss.Low-Summer.Noss.Mid",
"Winter.Noss.Low-Winter.Noss.Mid",
"Winter.Noss.Low-Summer.Looe.Low",
"Winter.Noss.Low-Winter.Looe.Low",
"Winter.Noss.Low-Summer.Noss.Low",
"Winter.Noss.Low-Winter.Noss.Low",
"Winter.Noss.Low-Winter.Beggers.Mid",
"Winter.Noss.Low-Summer.Beggers.Low",
"Winter.Noss.Low-Winter.Beggers.Low"
)
length_df$Comparison[!length_df$Comparison %in% desired_order]
# character(0)
desired_order
# Reorder the rows of 'length_df' based on the 'desired_order'
length_df$Comparison <- factor(length_df$Comparison, levels = desired_order)
length_df <- length_df[order(length_df$Comparison),]
# View the result
print(length_df)
length_df <- read.table(text = "'Row' 'Comparison' 'P.adj'
1 'Summer.Beggers.Low-Summer.Beggers.Mid' 5.807083e-04
2 'Summer.Beggers.Low-Winter.Beggers.Mid' 1.724772e-06
3 'Summer.Beggers.Low-Summer.Looe.Mid' 4.744247e-09
4 'Summer.Beggers.Low-Winter.Looe.Mid' 4.744245e-09
5 'Summer.Beggers.Low-Summer.Noss.Mid' 4.744612e-09
6 'Summer.Beggers.Low-Winter.Noss.Mid' 4.444223e-06
7 'Winter.Beggers.Mid-Summer.Beggers.Mid' 4.744253e-09
8 'Winter.Beggers.Low-Summer.Beggers.Mid' 4.744306e-09
9 'Winter.Beggers.Low-Winter.Beggers.Mid' 7.580746e-01
10 'Summer.Looe.Mid-Summer.Beggers.Mid' 1.138199e-07
11 'Summer.Looe.Mid-Winter.Beggers.Mid' 4.744133e-09
12 'Summer.Looe.Low-Summer.Beggers.Mid' 4.811983e-09
13 'Summer.Looe.Low-Winter.Beggers.Mid' 4.744133e-09
14 'Summer.Looe.Low-Summer.Looe.Mid' 9.916068e-01
15 'Summer.Looe.Low-Winter.Looe.Mid' 7.486876e-01
16 'Summer.Looe.Low-Summer.Noss.Mid' 2.461065e-03
17 'Summer.Looe.Low-Winter.Noss.Mid' 7.037123e-09
18 'Summer.Looe.Low-Summer.Beggers.Low' 4.744133e-09
19 'Winter.Looe.Mid-Summer.Beggers.Mid' 1.808862e-06
20 'Winter.Looe.Mid-Summer.Looe.Mid' 9.999087e-01
21 'Winter.Looe.Mid-Winter.Beggers.Mid' 4.744133e-09
22 'Winter.Looe.Low-Summer.Beggers.Mid' 1.576504e-02
23 'Winter.Looe.Low-Summer.Looe.Mid' 1.664206e-01
24 'Winter.Looe.Low-Winter.Looe.Mid' 5.513244e-01
25 'Winter.Looe.Low-Summer.Noss.Mid' 1.000000e+00
26 'Winter.Looe.Low-Winter.Noss.Mid' 1.311895e-01
27 'Winter.Looe.Low-Summer.Looe.Low' 3.044077e-03
28 'Winter.Looe.Low-Summer.Beggers.Low' 4.744259e-09
29 'Winter.Looe.Low-Winter.Beggers.Mid' 4.744133e-09
30 'Winter.Looe.Low-Winter.Beggers.Low' 4.744133e-09
31 'Summer.Noss.Mid-Summer.Beggers.Mid' 5.481544e-02
32 'Summer.Noss.Mid-Winter.Beggers.Mid' 4.744133e-09
33 'Summer.Noss.Mid-Summer.Looe.Mid' 1.275696e-01
34 'Summer.Noss.Mid-Winter.Looe.Mid' 4.524766e-01
35 'Summer.Noss.Low-Summer.Beggers.Mid' 9.104882e-04
36 'Summer.Noss.Low-Winter.Beggers.Mid' 4.744133e-09
37 'Summer.Noss.Low-Summer.Looe.Mid' 7.513767e-01
38 'Summer.Noss.Low-Winter.Looe.Mid' 9.841118e-01
39 'Summer.Noss.Low-Summer.Noss.Mid' 9.952838e-01
40 'Summer.Noss.Low-Winter.Noss.Mid' 1.206607e-02
41 'Summer.Noss.Low-Summer.Looe.Low' 8.300121e-02
42 'Summer.Noss.Low-Winter.Looe.Low' 9.992360e-01
43 'Summer.Noss.Low-Summer.Beggers.Low' 4.744227e-09
44 'Summer.Noss.Low-Winter.Beggers.Low' 4.744133e-09
45 'Winter.Noss.Mid-Summer.Beggers.Mid' 9.997435e-01
46 'Winter.Noss.Mid-Summer.Looe.Mid' 2.844608e-06
47 'Winter.Noss.Mid-Winter.Looe.Mid' 4.297392e-05
48 'Winter.Noss.Mid-Summer.Noss.Mid' 3.046563e-01
49 'Winter.Noss.Mid-Winter.Beggers.Mid' 4.744143e-09
50 'Winter.Noss.Low-Summer.Beggers.Mid' 1.602939e-01
51 'Winter.Noss.Low-Summer.Looe.Mid' 4.744255e-09
52 'Winter.Noss.Low-Winter.Looe.Mid' 4.744219e-09
53 'Winter.Noss.Low-Summer.Noss.Mid' 1.551057e-08
54 'Winter.Noss.Low-Winter.Noss.Mid' 7.554644e-03
55 'Winter.Noss.Low-Summer.Looe.Low' 4.744247e-09
56 'Winter.Noss.Low-Winter.Looe.Low' 4.974489e-09
57 'Winter.Noss.Low-Summer.Noss.Low' 4.746061e-09
58 'Winter.Noss.Low-Winter.Beggers.Mid' 4.744843e-09
59 'Winter.Noss.Low-Summer.Beggers.Low' 8.016093e-01
60 'Winter.Noss.Low-Winter.Beggers.Low' 7.351187e-07", header = TRUE, sep = " ")
After each of these data frame mutations, I use the following code to run CldList. For attempt 2, it follows the order, but does not start with Summer.Beggers.Mid as it is always the second component in any comparison.
# Use cldList to get compact letter display
length_cld <- cldList(
p.value = length_df$P.adj,
comparison = length_df$Comparison,
threshold = 0.05
)
# View results
print(length_cld)
# Attempt 2
> print(length_cld)
# Group Letter MonoLetter
#1 Summer.Beggers.Low a a
#2 Winter.Beggers.Mid b b
#3 Winter.Beggers.Low b b
#4 Summer.Looe.Mid cd cd
#5 Summer.Looe.Low c c
#6 Winter.Looe.Mid cd cd
#7 Winter.Looe.Low de de
#8 Summer.Noss.Mid def def
#9 Summer.Noss.Low cd cd
#10 Winter.Noss.Mid ef ef
#11 Winter.Noss.Low ag a g
#12 Summer.Beggers.Mid fg fg
So overall:
CldList works normally without setting a desired order.
I want it in a specific order to match the figure order attached, so that the first columns / bar starts with a, and not EG (After edit, figure does not match new CLDlist, now is fg). It is starting with Summer.Beggers.Low as this is the first component in most comparisons with it.
Is this then to do with the way TukeyHSD formats its results? If so, is there a way to alter the TukeyHSD code to have Summer.Beggers.Mid as a first component in pair-wise comparisons?
Attempt 3 : I went though my length_df and manually flipped all comparisons with Summer.Beggers.Mid to have it as the first component in the comparison. But it completely changes the compact letter display: Interestingly, Winter.Beggers.Low is now assigned 'cefgh', when previously it was a single letter (b) different from all other comparisons except Winter.beggers.Mid
I am unsure why as the p-values should be the exact same even if the comparisons are flipped? There must be something I have written wrong or the output of TukeyHSD is this way for a reason? But all the same comparions are present in length_df and my new length_df_ordered2 with Summer.Beggers.Mid as the first component in its comparisons.
length_df_ordered2 <- read.table(text = "
Row Comparison P.adj
1 'Summer.Beggers.Mid-Summer.Beggers.Low' 5.807083e-04
8 'Summer.Beggers.Mid-Winter.Beggers.Low' 4.744306e-09
10 'Summer.Beggers.Mid-Summer.Looe.Mid' 1.138199e-07
19 'Summer.Beggers.Mid-Winter.Looe.Mid' 1.808862e-06
31 'Summer.Beggers.Mid-Summer.Noss.Mid' 5.481544e-02
45 'Summer.Beggers.Mid-Winter.Noss.Mid' 9.997435e-01
12 'Summer.Beggers.Mid-Summer.Looe.Low' 4.811983e-09
22 'Summer.Beggers.Mid-Winter.Looe.Low' 1.576504e-02
35 'Summer.Beggers.Mid-Summer.Noss.Low' 9.104882e-04
50 'Summer.Beggers.Mid-Winter.Noss.Low' 1.602939e-01
2 'Summer.Beggers.Low-Winter.Beggers.Mid' 1.724772e-06
3 'Summer.Beggers.Low-Summer.Looe.Mid' 4.744247e-09
4 'Summer.Beggers.Low-Winter.Looe.Mid' 4.744245e-09
5 'Summer.Beggers.Low-Summer.Noss.Mid' 4.744612e-09
6 'Summer.Beggers.Low-Winter.Noss.Mid' 4.444223e-06
7 'Winter.Beggers.Mid-Summer.Beggers.Mid' 4.744253e-09
9 'Winter.Beggers.Low-Winter.Beggers.Mid' 7.580746e-01
11 'Summer.Looe.Mid-Winter.Beggers.Mid' 4.744133e-09
13 'Summer.Looe.Low-Winter.Beggers.Mid' 4.744133e-09
14 'Summer.Looe.Low-Summer.Looe.Mid' 9.916068e-01
15 'Summer.Looe.Low-Winter.Looe.Mid' 7.486876e-01
16 'Summer.Looe.Low-Summer.Noss.Mid' 2.461065e-03
17 'Summer.Looe.Low-Winter.Noss.Mid' 7.037123e-09
18 'Summer.Looe.Low-Summer.Beggers.Low' 4.744133e-09
20 'Winter.Looe.Mid-Summer.Looe.Mid' 9.999087e-01
21 'Winter.Looe.Mid-Winter.Beggers.Mid' 4.744133e-09
23 'Winter.Looe.Low-Summer.Looe.Mid' 1.664206e-01
24 'Winter.Looe.Low-Winter.Looe.Mid' 5.513244e-01
25 'Winter.Looe.Low-Summer.Noss.Mid' 1.000000e+00
26 'Winter.Looe.Low-Winter.Noss.Mid' 1.311895e-01
27 'Winter.Looe.Low-Summer.Looe.Low' 3.044077e-03
28 'Winter.Looe.Low-Summer.Beggers.Low' 4.744259e-09
29 'Winter.Looe.Low-Winter.Beggers.Mid' 4.744133e-09
30 'Winter.Looe.Low-Winter.Beggers.Low' 4.744133e-09
32 'Summer.Noss.Mid-Winter.Beggers.Mid' 4.744133e-09
33 'Summer.Noss.Mid-Summer.Looe.Mid' 1.275696e-01
34 'Summer.Noss.Mid-Winter.Looe.Mid' 4.524766e-01
36 'Summer.Noss.Low-Winter.Beggers.Mid' 4.744133e-09
37 'Summer.Noss.Low-Summer.Looe.Mid' 7.513767e-01
38 'Summer.Noss.Low-Winter.Looe.Mid' 9.841118e-01
39 'Summer.Noss.Low-Summer.Noss.Mid' 9.952838e-01
40 'Summer.Noss.Low-Winter.Noss.Mid' 1.206607e-02
41 'Summer.Noss.Low-Summer.Looe.Low' 8.300121e-02
42 'Summer.Noss.Low-Winter.Looe.Low' 9.992360e-01
43 'Summer.Noss.Low-Summer.Beggers.Low' 4.744227e-09
44 'Summer.Noss.Low-Winter.Beggers.Low' 4.744133e-09
46 'Winter.Noss.Mid-Summer.Looe.Mid' 2.844608e-06
47 'Winter.Noss.Mid-Winter.Looe.Mid' 4.297392e-05
48 'Winter.Noss.Mid-Summer.Noss.Mid' 3.046563e-01
49 'Winter.Noss.Mid-Winter.Beggers.Mid' 4.744143e-09
51 'Winter.Noss.Low-Summer.Looe.Mid' 4.744255e-09
52 'Winter.Noss.Low-Winter.Looe.Mid' 4.744219e-09
53 'Winter.Noss.Low-Summer.Noss.Mid' 1.551057e-08
54 'Winter.Noss.Low-Winter.Noss.Mid' 7.554644e-03
55 'Winter.Noss.Low-Summer.Looe.Low' 4.744247e-09
56 'Winter.Noss.Low-Winter.Looe.Low' 4.974489e-09
57 'Winter.Noss.Low-Summer.Noss.Low' 4.746061e-09
58 'Winter.Noss.Low-Winter.Beggers.Mid' 4.744843e-09
59 'Winter.Noss.Low-Summer.Beggers.Low' 8.016093e-01
60 'Winter.Noss.Low-Winter.Beggers.Low' 7.351187e-07
", header = TRUE)
# Check for missing comaprions #
length_df_ordered2$Comparison[!length_df_ordered2$Comparison %in% length_df]
# character(0)
# Use cldList to get compact letter display
length_cld_ordered2 <- cldList(
p.value = length_df_ordered2$P.adj,
comparison = length_df_ordered2$Comparison,
threshold = 0.05
)
# View results
print(length_cld_ordered2)
# Group Letter MonoLetter
#1 Summer.Beggers.Mid ab ab
#2 Summer.Beggers.Low cd cd
#3 Winter.Beggers.Mid e e
#4 Winter.Beggers.Low cefgh c efgh
#5 Summer.Looe.Mid fgij fg ij
#6 Summer.Looe.Low fi f i
#7 Winter.Looe.Mid fgij fg ij
#8 Winter.Looe.Low jk jk
#9 Summer.Noss.Mid aghjk a gh jk
#10 Summer.Noss.Low ij ij
#11 Winter.Noss.Mid ahk a h k
#12 Winter.Noss.Low bd b d
Hopefully this can be worked around to make plot more aesthetic and easier to follow.
If in need of more info / context / data just comment :)
Many thanks for all responses.
CONTEXT FOR CORRECT ANSWER : Edit : Below table has a 'Comparison' column added, and 'p adj' replaced with p_adj, as my previous syntax was incorrect.
length_Tukey <- TukeyHSD(length.mod.max)
length_Tukey
length_tukey2 <- read.table(text = "
Comparion diff lwr upr p_adj
'Winter:Beggers:Mid-Summer:Beggers:Mid' 29.4223913 19.8928280 38.95195464 0.0000000
'Summer:Looe:Mid-Summer:Beggers:Mid' -17.0816085 -26.3374620 -7.82575506 0.0000001
'Winter:Looe:Mid-Summer:Beggers:Mid' -15.2041608 -24.1435742 -6.26474731 0.0000018
'Summer:Noss:Mid-Summer:Beggers:Mid' -9.1104143 -18.3054013 0.08457279 0.0548154
'Winter:Noss:Mid-Summer:Beggers:Mid' -2.2282797 -11.4180417 6.96148231 0.9997435
'Summer:Beggers:Low-Summer:Beggers:Mid' 13.0708662 3.4300630 22.71166931 0.0005807
'Winter:Beggers:Low-Summer:Beggers:Mid' 23.8704968 14.2899835 33.45101004 0.0000000
'Summer:Looe:Low-Summer:Beggers:Mid' -20.2690529 -29.5565237 -10.98158210 0.0000000
'Winter:Looe:Low-Summer:Beggers:Mid' -9.7459188 -18.5546802 -0.93715738 0.0157650
'Summer:Noss:Low-Summer:Beggers:Mid' -11.9838481 -21.0283902 -2.93930611 0.0009105
'Winter:Noss:Low-Summer:Beggers:Mid' 7.9324954 -1.1718230 17.03681388 0.1602939
'Summer:Looe:Mid-Winter:Beggers:Mid' -46.5039998 -55.7168884 -37.29111130 0.0000000
'Winter:Looe:Mid-Winter:Beggers:Mid' -44.6265521 -53.5214723 -35.73163191 0.0000000
'Summer:Noss:Mid-Winter:Beggers:Mid' -38.5328056 -47.6845420 -29.38106919 0.0000000
'Winter:Noss:Mid-Winter:Beggers:Mid' -31.6506710 -40.7971576 -22.50418438 0.0000000
'Summer:Beggers:Low-Winter:Beggers:Mid' -16.3515252 -25.9510865 -6.75196384 0.0000017
'Winter:Beggers:Low-Winter:Beggers:Mid' -5.5518946 -15.0909053 3.98711623 0.7580746
'Summer:Looe:Low-Winter:Beggers:Mid' -49.6914442 -58.9360971 -40.44679139 0.0000000
'Winter:Looe:Low-Winter:Beggers:Mid' -39.1683101 -47.9319149 -30.40470528 0.0000000
'Summer:Noss:Low-Winter:Beggers:Mid' -41.4062395 -50.4068079 -32.40567100 0.0000000
'Winter:Noss:Low-Winter:Beggers:Mid' -21.4898959 -30.5505309 -12.42926090 0.0000000
'Winter:Looe:Mid-Summer:Looe:Mid' 1.8774477 -6.7235900 10.47848551 0.9999087
'Summer:Noss:Mid-Summer:Looe:Mid' 7.9711942 -0.8951762 16.83756468 0.1275696
'Winter:Noss:Mid-Summer:Looe:Mid' 14.8533288 5.9923772 23.71428043 0.0000028
'Summer:Beggers:Low-Summer:Looe:Mid' 30.1524747 20.8245691 39.48038029 0.0000000
'Winter:Beggers:Low-Summer:Looe:Mid' 40.9521053 31.6865253 50.21768526 0.0000000
'Summer:Looe:Low-Summer:Looe:Mid' -3.1874444 -12.1496903 5.77480151 0.9916068
'Winter:Looe:Low-Summer:Looe:Mid' 7.3356897 -1.1294751 15.80085454 0.1664206
'Summer:Noss:Low-Summer:Looe:Mid' 5.0977604 -3.6124910 13.80801170 0.7513767
'Winter:Noss:Low-Summer:Looe:Mid' 25.0141039 16.2417979 33.78640992 0.0000000
'Summer:Noss:Mid-Winter:Looe:Mid' 6.0937465 -2.4417567 14.62924969 0.4524766
'Winter:Noss:Mid-Winter:Looe:Mid' 12.9758811 4.4460069 21.50575525 0.0000430
'Summer:Beggers:Low-Winter:Looe:Mid' 28.2750269 19.2610315 37.28902233 0.0000000
'Winter:Beggers:Low-Winter:Looe:Mid' 39.0746575 30.1251736 48.02414145 0.0000000
'Summer:Looe:Low-Winter:Looe:Mid' -5.0648921 -13.6999452 3.57016094 0.7486876
'Winter:Looe:Low-Winter:Looe:Mid' 5.4582420 -2.6597199 13.57620387 0.5513244
'Summer:Noss:Low-Winter:Looe:Mid' 3.2203126 -5.1529047 11.59352994 0.9841118
'Winter:Noss:Low-Winter:Looe:Mid' 23.1366562 14.6989051 31.57440721 0.0000000
'Winter:Noss:Mid-Summer:Noss:Mid' 6.8821346 -1.9152189 15.67948801 0.3046563
'Summer:Beggers:Low-Summer:Noss:Mid' 22.1812804 12.9137680 31.44879289 0.0000000
'Winter:Beggers:Low-Summer:Noss:Mid' 32.9809110 23.7761331 42.18568895 0.0000000
'Summer:Looe:Low-Summer:Noss:Mid' -11.1586386 -20.0580103 -2.25926699 0.0024611
'Winter:Looe:Low-Summer:Noss:Mid' -0.6355045 -9.0340746 7.76306555 1.0000000
'Summer:Noss:Low-Summer:Noss:Mid' -2.8734339 -11.5189785 5.77211077 0.9952838
'Winter:Noss:Low-Summer:Noss:Mid' 17.0429097 8.3348492 25.75097011 0.0000000
'ummer:Beggers:Low-Winter:Noss:Mid' 15.2991459 6.0368175 24.56147417 0.0000044
'Winter:Beggers:Low-Winter:Noss:Mid' 26.0987764 16.8992180 35.29833487 0.0000000
'Summer:Looe:Low-Winter:Noss:Mid' -18.0407732 -26.9347461 -9.14680029 0.0000000
'Winter:Looe:Low-Winter:Noss:Mid' -7.5176391 -15.9104883 0.87521012 0.1311895
'Summer:Noss:Low-Winter:Noss:Mid' -9.7555684 -18.3955558 -1.11558113 0.0120661
'Winter:Noss:Low-Winter:Noss:Mid' 10.1607751 1.4582321 18.86331813 0.0075546
'Winter:Beggers:Low-Summer:Beggers:Low' 10.7996306 1.1494889 20.44977230 0.0135847
'Summer:Looe:Low-Summer:Beggers:Low' -33.3399191 -42.6991986 -23.98063950 0.0000000
'Winter:Looe:Low-Summer:Beggers:Low' -22.8167849 -31.7012251 -13.93234475 0.0000000
'Summer:Noss:Low-Summer:Beggers:Low' -25.0547143 -34.1729784 -15.93645018 0.0000000
'Winter:Noss:Low-Summer:Beggers:Low' -5.1383707 -14.3159312 4.03918965 0.8016093
'Summer:Looe:Low-Winter:Beggers:Low' -44.1395497 -53.4367139 -34.84238539 0.0000000
'Winter:Looe:Low-Winter:Beggers:Low' -33.6164155 -42.4353966 -24.79743448 0.0000000
'Summer:Noss:Low-Winter:Beggers:Low' -35.8543449 -44.9088405 -26.79984933 0.0000000
'Winter:Noss:Low-Winter:Beggers:Low' -15.9380013 -25.0522081 -6.82379462 0.0000007
'Winter:Looe:Low-Summer:Looe:Low' 10.5231341 2.0234102 19.02285801 0.0030441
'Summer:Noss:Low-Summer:Looe:Low' 8.2852048 -0.4586370 17.02904655 0.0830012
'Winter:Noss:Low-Summer:Looe:Low' 28.2015483 19.3958886 37.00720806 0.0000000
'Summer:Noss:Low-Winter:Looe:Low' -2.2379294 -10.4715150 5.99565630 0.9992360
'Winter:Noss:Low-Winter:Looe:Low' 17.6784142 9.3792090 25.97761940 0.0000000
'Winter:Noss:Low-Summer:Noss:Low' 19.9163435 11.3672927 28.46539437 0.0000000", header = TRUE)
NOTE: In tukey HSD direct output, 'p_adj' is 'p adj', but when writing read.table cannot use spaces for the same column.
Post edit : @jared_mamrot produced a code to solve the issue (shown as correct answer below) , but my length_tukey2 <- read.table() was incorrectly formatted. I had to modify his function to fit extraction of TukeyHSD results. Below i will illustrate how I extracted TukeyHSD results for a specific treatment interaction effect, and then how jared_mamrots code is utilised to perform CldList in a specific order.
length.mod.max <- aov(length ~ season * site * height, data=data)
summary(length.mod.max)
length_Tukey <- TukeyHSD(length.mod.max)
length_Tukey
# Extract the Tukey results
length_tukey_results <- length_Tukey$`season:site:height`
# Convert to a data frame and make row names a new column
length_tukey_results <- as.data.frame(length_tukey_results)
length_tukey_results$Comparison <- rownames(length_tukey_results)
# move 'Comparison' to the first column
length_tukey_results <- length_tukey_results[, c(ncol(length_tukey_results), 1:(ncol(length_tukey_results) - 1))]
# View the result
View(length_tukey_results)
###############################################################################
################################################################################
library(rcompanion)
#######################
## jared_mamrot code ##
cldList2 <- function (formula = NULL, data = NULL, comparison = NULL, p.value = NULL,
threshold = 0.05, print.comp = FALSE, desired_order = desired_order, ...)
{
if (!is.null(formula)) {
p.value = eval(parse(text = paste0("data", "$", all.vars(formula[[2]])[1])))
comparison = eval(parse(text = paste0("data", "$", all.vars(formula[[3]])[1])))
}
FLAG = 0
Comparison = data[data[[p.value]] <= threshold,]
Comparison2 <- Comparison
Comparison2$Comparison <- paste(gsub(".*-", "", Comparison$Comparison),
gsub("-.*", "", Comparison$Comparison),
sep = "-")
Comparison <- rbind(Comparison, Comparison2)
order_df = Comparison[order(-rowSums(sapply(seq_along(desired_order), function(i) {
i * grepl(desired_order[i], Comparison[[comparison]])})),
Comparison[[comparison]], decreasing = TRUE),]
Comparison = order_df[[p.value]]
names(Comparison) <- order_df[[comparison]]
if (sum(data[data[[p.value]] <= threshold,][[p.value]], na.rm = TRUE) == 0) {
FLAG = 1
}
if (print.comp == TRUE) {
Y = data.frame(Comparisons = Comparison, p.value = p.value,
Value = Comparison, Threshold = threshold)
cat("\n", "\n")
print(Y)
cat("\n", "\n")
}
MCL = multcompView::multcompLetters(Comparison)
Group = names(MCL$Letters)
Letter = as.character(MCL$Letters)
if (FLAG == 0) {
MonoLetter = as.character(MCL$monospacedLetters)
}
if (FLAG == 1) {
MonoLetter = Letter
}
Z = data.frame(Group, Letter, MonoLetter)
return(Z)
}
###############################################################################
################################################################################
desired_order <- c(
"Summer:Beggers:Mid", "Summer:Beggers:Low",
"Winter:Beggers:Mid", "Winter:Beggers:Low",
"Summer:Looe:Mid", "Summer:Looe:Low",
"Winter:Looe:Mid", "Winter:Looe:Low",
"Summer:Noss:Mid", "Summer:Noss:Low",
"Winter:Noss:Mid", "Winter:Noss:Low"
)
# Use cldList2 to get compact letter display
length_cld2 <- cldList2(
data = length_tukey_results,
p.value = "p adj",
comparison = "Comparison",
threshold = 0.05,
desired_order = desired_order
)
# View results
print(length_cld2)
# Group Letter MonoLetter
#1 Summer:Beggers:Mid ab ab
#2 Summer:Beggers:Low c c
#3 Winter:Beggers:Mid d d
#4 Winter:Beggers:Low d d
#5 Summer:Looe:Mid ef ef
#6 Summer:Looe:Low e e
#7 Winter:Looe:Mid ef ef
#8 Winter:Looe:Low fg fg
#9 Summer:Noss:Mid afg a fg
#10 Summer:Noss:Low ef ef
#11 Winter:Noss:Mid ag a g
#12 Winter:Noss:Low bc bc
I've adapted the cldList function to allow you to input desired_order
, and I think the output is correct, but I'm not certain:
library(rcompanion)
cldList2 <- function (formula = NULL, data = NULL, comparison = NULL, p.value = NULL,
threshold = 0.05, print.comp = FALSE, desired_order = desired_order, ...)
{
if (!is.null(formula)) {
p.value = eval(parse(text = paste0("data", "$", all.vars(formula[[2]])[1])))
comparison = eval(parse(text = paste0("data", "$", all.vars(formula[[3]])[1])))
}
FLAG = 0
Comparison = data[data[[p.value]] <= threshold,]
Comparison2 <- Comparison
Comparison2$diff <- paste(gsub(".*-", "", Comparison$diff),
gsub("-.*", "", Comparison$diff),
sep = "-")
Comparison <- rbind(Comparison, Comparison2)
order_df = Comparison[order(-rowSums(sapply(seq_along(desired_order), function(i) {
i * grepl(desired_order[i], Comparison[[comparison]])})),
Comparison[[comparison]], decreasing = TRUE),]
Comparison = order_df[[p.value]]
names(Comparison) <- order_df[[comparison]]
if (sum(data[data[[p.value]] <= threshold,][[p.value]], na.rm = TRUE) == 0) {
FLAG = 1
}
if (print.comp == TRUE) {
Y = data.frame(Comparisons = Comparison, p.value = p.value,
Value = Comparison, Threshold = threshold)
cat("\n", "\n")
print(Y)
cat("\n", "\n")
}
MCL = multcompView::multcompLetters(Comparison)
Group = names(MCL$Letters)
Letter = as.character(MCL$Letters)
if (FLAG == 0) {
MonoLetter = as.character(MCL$monospacedLetters)
}
if (FLAG == 1) {
MonoLetter = Letter
}
Z = data.frame(Group, Letter, MonoLetter)
return(Z)
}
length_tukey2 <- read.table(text = "
diff lwr upr p adj
'Winter:Beggers:Mid-Summer:Beggers:Mid' 29.4223913 19.8928280 38.95195464 0.0000000
'Summer:Looe:Mid-Summer:Beggers:Mid' -17.0816085 -26.3374620 -7.82575506 0.0000001
'Winter:Looe:Mid-Summer:Beggers:Mid' -15.2041608 -24.1435742 -6.26474731 0.0000018
'Summer:Noss:Mid-Summer:Beggers:Mid' -9.1104143 -18.3054013 0.08457279 0.0548154
'Winter:Noss:Mid-Summer:Beggers:Mid' -2.2282797 -11.4180417 6.96148231 0.9997435
'Summer:Beggers:Low-Summer:Beggers:Mid' 13.0708662 3.4300630 22.71166931 0.0005807
'Winter:Beggers:Low-Summer:Beggers:Mid' 23.8704968 14.2899835 33.45101004 0.0000000
'Summer:Looe:Low-Summer:Beggers:Mid' -20.2690529 -29.5565237 -10.98158210 0.0000000
'Winter:Looe:Low-Summer:Beggers:Mid' -9.7459188 -18.5546802 -0.93715738 0.0157650
'Summer:Noss:Low-Summer:Beggers:Mid' -11.9838481 -21.0283902 -2.93930611 0.0009105
'Winter:Noss:Low-Summer:Beggers:Mid' 7.9324954 -1.1718230 17.03681388 0.1602939
'Summer:Looe:Mid-Winter:Beggers:Mid' -46.5039998 -55.7168884 -37.29111130 0.0000000
'Winter:Looe:Mid-Winter:Beggers:Mid' -44.6265521 -53.5214723 -35.73163191 0.0000000
'Summer:Noss:Mid-Winter:Beggers:Mid' -38.5328056 -47.6845420 -29.38106919 0.0000000
'Winter:Noss:Mid-Winter:Beggers:Mid' -31.6506710 -40.7971576 -22.50418438 0.0000000
'Summer:Beggers:Low-Winter:Beggers:Mid' -16.3515252 -25.9510865 -6.75196384 0.0000017
'Winter:Beggers:Low-Winter:Beggers:Mid' -5.5518946 -15.0909053 3.98711623 0.7580746
'Summer:Looe:Low-Winter:Beggers:Mid' -49.6914442 -58.9360971 -40.44679139 0.0000000
'Winter:Looe:Low-Winter:Beggers:Mid' -39.1683101 -47.9319149 -30.40470528 0.0000000
'Summer:Noss:Low-Winter:Beggers:Mid' -41.4062395 -50.4068079 -32.40567100 0.0000000
'Winter:Noss:Low-Winter:Beggers:Mid' -21.4898959 -30.5505309 -12.42926090 0.0000000
'Winter:Looe:Mid-Summer:Looe:Mid' 1.8774477 -6.7235900 10.47848551 0.9999087
'Summer:Noss:Mid-Summer:Looe:Mid' 7.9711942 -0.8951762 16.83756468 0.1275696
'Winter:Noss:Mid-Summer:Looe:Mid' 14.8533288 5.9923772 23.71428043 0.0000028
'Summer:Beggers:Low-Summer:Looe:Mid' 30.1524747 20.8245691 39.48038029 0.0000000
'Winter:Beggers:Low-Summer:Looe:Mid' 40.9521053 31.6865253 50.21768526 0.0000000
'Summer:Looe:Low-Summer:Looe:Mid' -3.1874444 -12.1496903 5.77480151 0.9916068
'Winter:Looe:Low-Summer:Looe:Mid' 7.3356897 -1.1294751 15.80085454 0.1664206
'Summer:Noss:Low-Summer:Looe:Mid' 5.0977604 -3.6124910 13.80801170 0.7513767
'Winter:Noss:Low-Summer:Looe:Mid' 25.0141039 16.2417979 33.78640992 0.0000000
'Summer:Noss:Mid-Winter:Looe:Mid' 6.0937465 -2.4417567 14.62924969 0.4524766
'Winter:Noss:Mid-Winter:Looe:Mid' 12.9758811 4.4460069 21.50575525 0.0000430
'Summer:Beggers:Low-Winter:Looe:Mid' 28.2750269 19.2610315 37.28902233 0.0000000
'Winter:Beggers:Low-Winter:Looe:Mid' 39.0746575 30.1251736 48.02414145 0.0000000
'Summer:Looe:Low-Winter:Looe:Mid' -5.0648921 -13.6999452 3.57016094 0.7486876
'Winter:Looe:Low-Winter:Looe:Mid' 5.4582420 -2.6597199 13.57620387 0.5513244
'Summer:Noss:Low-Winter:Looe:Mid' 3.2203126 -5.1529047 11.59352994 0.9841118
'Winter:Noss:Low-Winter:Looe:Mid' 23.1366562 14.6989051 31.57440721 0.0000000
'Winter:Noss:Mid-Summer:Noss:Mid' 6.8821346 -1.9152189 15.67948801 0.3046563
'Summer:Beggers:Low-Summer:Noss:Mid' 22.1812804 12.9137680 31.44879289 0.0000000
'Winter:Beggers:Low-Summer:Noss:Mid' 32.9809110 23.7761331 42.18568895 0.0000000
'Summer:Looe:Low-Summer:Noss:Mid' -11.1586386 -20.0580103 -2.25926699 0.0024611
'Winter:Looe:Low-Summer:Noss:Mid' -0.6355045 -9.0340746 7.76306555 1.0000000
'Summer:Noss:Low-Summer:Noss:Mid' -2.8734339 -11.5189785 5.77211077 0.9952838
'Winter:Noss:Low-Summer:Noss:Mid' 17.0429097 8.3348492 25.75097011 0.0000000
'Summer:Beggers:Low-Winter:Noss:Mid' 15.2991459 6.0368175 24.56147417 0.0000044
'Winter:Beggers:Low-Winter:Noss:Mid' 26.0987764 16.8992180 35.29833487 0.0000000
'Summer:Looe:Low-Winter:Noss:Mid' -18.0407732 -26.9347461 -9.14680029 0.0000000
'Winter:Looe:Low-Winter:Noss:Mid' -7.5176391 -15.9104883 0.87521012 0.1311895
'Summer:Noss:Low-Winter:Noss:Mid' -9.7555684 -18.3955558 -1.11558113 0.0120661
'Winter:Noss:Low-Winter:Noss:Mid' 10.1607751 1.4582321 18.86331813 0.0075546
'Winter:Beggers:Low-Summer:Beggers:Low' 10.7996306 1.1494889 20.44977230 0.0135847
'Summer:Looe:Low-Summer:Beggers:Low' -33.3399191 -42.6991986 -23.98063950 0.0000000
'Winter:Looe:Low-Summer:Beggers:Low' -22.8167849 -31.7012251 -13.93234475 0.0000000
'Summer:Noss:Low-Summer:Beggers:Low' -25.0547143 -34.1729784 -15.93645018 0.0000000
'Winter:Noss:Low-Summer:Beggers:Low' -5.1383707 -14.3159312 4.03918965 0.8016093
'Summer:Looe:Low-Winter:Beggers:Low' -44.1395497 -53.4367139 -34.84238539 0.0000000
'Winter:Looe:Low-Winter:Beggers:Low' -33.6164155 -42.4353966 -24.79743448 0.0000000
'Summer:Noss:Low-Winter:Beggers:Low' -35.8543449 -44.9088405 -26.79984933 0.0000000
'Winter:Noss:Low-Winter:Beggers:Low' -15.9380013 -25.0522081 -6.82379462 0.0000007
'Winter:Looe:Low-Summer:Looe:Low' 10.5231341 2.0234102 19.02285801 0.0030441
'Summer:Noss:Low-Summer:Looe:Low' 8.2852048 -0.4586370 17.02904655 0.0830012
'Winter:Noss:Low-Summer:Looe:Low' 28.2015483 19.3958886 37.00720806 0.0000000
'Summer:Noss:Low-Winter:Looe:Low' -2.2379294 -10.4715150 5.99565630 0.9992360
'Winter:Noss:Low-Winter:Looe:Low' 17.6784142 9.3792090 25.97761940 0.0000000
'Winter:Noss:Low-Summer:Noss:Low' 19.9163435 11.3672927 28.46539437 0.0000000",
header = TRUE)
desired_order <- c(
"Summer:Beggers:Mid", "Summer:Beggers:Low",
"Winter:Beggers:Mid", "Winter:Beggers:Low",
"Summer:Looe:Mid", "Summer:Looe:Low",
"Winter:Looe:Mid", "Winter:Looe:Low",
"Summer:Noss:Mid", "Summer:Noss:Low",
"Winter:Noss:Mid", "Winter:Noss:Low"
)
# Use cldList2 to get compact letter display
length_cld2 <- cldList2(
data = length_tukey2,
p.value = "adj",
comparison = "diff",
threshold = 0.05,
desired_order = desired_order
)
# View results
print(length_cld2)
#> Group Letter MonoLetter
#> 1 Summer:Beggers:Mid ab ab
#> 2 Summer:Beggers:Low c c
#> 3 Winter:Beggers:Mid d d
#> 4 Winter:Beggers:Low d d
#> 5 Summer:Looe:Mid ef ef
#> 6 Summer:Looe:Low e e
#> 7 Winter:Looe:Mid ef ef
#> 8 Winter:Looe:Low fg fg
#> 9 Summer:Noss:Mid afg a fg
#> 10 Summer:Noss:Low ef ef
#> 11 Winter:Noss:Mid ag a g
#> 12 Winter:Noss:Low bc bc
Created on 2025-05-14 with reprex v2.1.1
Is this the expected outcome with this data? What are the letters expected to be for the comparisons?