Explore data
library(knitr)
knitr::opts_chunk$set(comment=" ", warning=F, cache=T)
options(knitr.kable.NA = '')
library(tidyverse)
library(ggsignif)
library(ggforce)
library(broom)
library(multcomp) #Multiple comparisons package - for general linear hypothesis testing
library(emmeans) #Estimated marginal means aka least square means. use old version for glmmADMB: install_version("emmeans", version = "1.3.1", repos = "http://cran.us.r-project.org")
library(glmmTMB) #generalized linear mixed models with Template Model Builder
#overwrite function to make emmeans and multcomp play nice
modelparm.glmmTMB <- function (model, coef. = function(x) fixef(x)[[component]],
vcov. = function(x) vcov(x)[[component]],
df = NULL, component="cond", ...) {
multcomp:::modelparm.default(model, coef. = coef., vcov. = vcov.,
df = df, ...)
}
signif.num <- function(x) {
symnum(x, corr = FALSE, na = FALSE, legend = FALSE,
cutpoints = c(0, 0.001, 0.01, 0.05, 0.1, 1),
symbols = c("***", "**", "*", ".", " "))
}
Read data
setwd("~/MyDocs/MEGA/UCI/Schiedea/Analysis/HybridSeeds")
tubes <- read_csv("pollentubes_kaahoo_extra.csv") %>% mutate(across(ends_with("sp"), as.factor)) %>%
pivot_longer(starts_with(c("mid","bottom")), names_to=c("location","stigma"), names_sep="_", values_to="n_tubes") %>%
pivot_wider(names_from="location", values_from="n_tubes") %>%
drop_na(mid, bottom) %>% #one entry has mid but no bottom count
mutate(vial=as.character(vial),
momcross = toupper(str_sub(momsp,1,1)),
dadcross = toupper(str_sub(dadsp,1,1)),
observer="SGW") %>%
bind_rows(read_csv("pollentubes_kaahoo.csv") %>% #edited from pollentubes.csv
separate(cross, into=c("momcross","dadcross"), sep="x") %>%
mutate(observer="SZ")) %>%
mutate(
hr = factor(paste0(hr,"hr"), levels=c("4hr","24hr")),
ratioraw = bottom/mid,
adjmid = ifelse(bottom > mid, bottom, mid),
ratio = bottom/adjmid,
justmid = mid - bottom,
momid = paste(momcross, momid),
dadid = paste(dadcross, dadid),
cross = factor(paste0(momcross,"x",dadcross), levels=c("KxK","KxH","HxH","HxK")),
crosshr = factor(paste0(cross, hr), levels = paste(rep(levels(cross),each=2), levels(hr), sep=""))) %>%
mutate_if(is.character, as.factor)
str(tubes)
tibble [515 × 24] (S3: tbl_df/tbl/data.frame)
$ line : num [1:515] 1 1 1 2 2 2 3 3 4 4 ...
$ emasculation_date: Date[1:515], format: "2022-01-07" "2022-01-07" ...
$ pollination_date : Date[1:515], format: "2022-01-10" "2022-01-10" ...
$ momsp : Factor w/ 1 level "hook": 1 1 1 1 1 1 1 1 1 1 ...
$ momid : Factor w/ 12 levels "H 794-2","H 866-1",..: 2 2 2 2 2 2 2 2 2 2 ...
$ dadsp : Factor w/ 2 levels "hook","kaal": 1 1 1 1 1 1 1 1 1 1 ...
$ dadid : Factor w/ 20 levels "H 3--15","H 794-2",..: 2 2 2 2 2 2 2 2 2 2 ...
$ vial : Factor w/ 415 levels "100A","100B",..: 38 38 38 42 42 42 46 46 50 50 ...
$ hr : Factor w/ 2 levels "4hr","24hr": 1 1 1 1 1 1 2 2 2 2 ...
$ count_date : Date[1:515], format: "2022-03-01" "2022-03-01" ...
$ notes : Factor w/ 3 levels "JP: changed cross from KxH > KxK",..: NA NA NA NA NA NA NA NA NA NA ...
$ stigma : Factor w/ 5 levels "1","2","3","4",..: 1 2 3 1 2 3 1 2 1 2 ...
$ mid : num [1:515] 0 0 2 0 0 0 4 4 5 5 ...
$ bottom : num [1:515] 0 0 1 0 0 0 3 5 9 4 ...
$ momcross : Factor w/ 2 levels "H","K": 1 1 1 1 1 1 1 1 1 1 ...
$ dadcross : Factor w/ 2 levels "H","K": 1 1 1 1 1 1 1 1 1 1 ...
$ observer : Factor w/ 2 levels "SGW","SZ": 1 1 1 1 1 1 1 1 1 1 ...
$ grains : num [1:515] NA NA NA NA NA NA NA NA NA NA ...
$ ratioraw : num [1:515] NaN NaN 0.5 NaN NaN NaN 0.75 1.25 1.8 0.8 ...
$ adjmid : num [1:515] 0 0 2 0 0 0 4 5 9 5 ...
$ ratio : num [1:515] NaN NaN 0.5 NaN NaN NaN 0.75 1 1 0.8 ...
$ justmid : num [1:515] 0 0 1 0 0 0 1 -1 -4 1 ...
$ cross : Factor w/ 4 levels "KxK","KxH","HxH",..: 3 3 3 3 3 3 3 3 3 3 ...
$ crosshr : Factor w/ 8 levels "KxK4hr","KxK24hr",..: 5 5 5 5 5 5 6 6 6 6 ...
tube.contrasts <- c("HxH4hr - HxH24hr == 0",
"HxK4hr - HxK24hr == 0",
"HxH4hr - HxK4hr == 0",
"HxH24hr - HxK24hr == 0",
"KxH4hr - KxH24hr == 0",
"KxK4hr - KxK24hr == 0",
"KxH4hr - KxK4hr == 0",
"KxH24hr - KxK24hr == 0",
"HxH4hr - KxK4hr == 0",
"HxH24hr - KxK24hr == 0",
"HxH4hr+HxK4hr - KxK4hr-KxH4hr == 0",
"HxH24hr+HxK24hr - KxK24hr-KxH24hr == 0")
Inventory of crosses
with(tubes, table(cross, hr, observer))
, , observer = SGW
hr
cross 4hr 24hr
KxK 0 0
KxH 0 0
HxH 36 35
HxK 38 39
, , observer = SZ
hr
cross 4hr 24hr
KxK 62 55
KxH 63 38
HxH 46 26
HxK 43 34
with(tubes, table(cross, momid, observer))
, , observer = SGW
momid
cross H 794-2 H 866-1 H 866-2 H 879 2-2 H 879 N-5 H 899 2E-1 K 116-2 K 116-3
KxK 0 0 0 0 0 0 0 0
KxH 0 0 0 0 0 0 0 0
HxH 25 22 0 0 0 24 0 0
HxK 27 24 0 0 0 26 0 0
momid
cross K 140-6 K 892-3 K 892-4 K 892-5
KxK 0 0 0 0
KxH 0 0 0 0
HxH 0 0 0 0
HxK 0 0 0 0
, , observer = SZ
momid
cross H 794-2 H 866-1 H 866-2 H 879 2-2 H 879 N-5 H 899 2E-1 K 116-2 K 116-3
KxK 0 0 0 0 0 0 13 0
KxH 0 0 0 0 0 0 33 21
HxH 0 0 11 61 0 0 0 0
HxK 0 0 17 39 21 0 0 0
momid
cross K 140-6 K 892-3 K 892-4 K 892-5
KxK 0 24 56 24
KxH 21 23 0 3
HxH 0 0 0 0
HxK 0 0 0 0
with(tubes, table(dadid, momid))
momid
dadid H 794-2 H 866-1 H 866-2 H 879 2-2 H 879 N-5 H 899 2E-1 K 116-2
H 3--15 0 0 0 16 0 0 0
H 794-2 0 10 0 0 0 12 0
H 866-2 12 0 0 45 0 12 0
H 879 2-2 0 0 0 0 0 0 9
H 879 G 2-2 0 0 11 0 0 0 0
H 879 N-5 0 0 0 0 0 0 14
H 892-1 0 0 0 0 0 0 0
H 892-3 0 0 0 0 0 0 10
H 899 2E-1 13 12 0 0 0 0 0
K 115-2 0 0 0 0 0 0 0
K 116-1 13 12 0 0 0 0 0
K 116-2 0 12 0 0 0 0 0
K 116-3 0 0 0 0 0 14 0
K 140-6 0 0 3 5 0 0 0
K 169-7 0 0 0 10 0 0 0
K 3587-1 0 0 0 0 0 0 13
K 879-2 0 0 0 15 18 0 0
K 892-3 0 0 0 6 3 0 0
K 892-4 0 0 0 0 0 12 0
K 892-5 14 0 14 3 0 0 0
momid
dadid K 116-3 K 140-6 K 892-3 K 892-4 K 892-5
H 3--15 0 0 0 0 0
H 794-2 0 0 0 0 0
H 866-2 0 0 23 0 3
H 879 2-2 0 0 0 0 0
H 879 G 2-2 0 0 0 0 0
H 879 N-5 20 21 0 0 0
H 892-1 1 0 0 0 0
H 892-3 0 0 0 0 0
H 899 2E-1 0 0 0 0 0
K 115-2 0 0 0 36 0
K 116-1 0 0 0 0 0
K 116-2 0 0 24 0 0
K 116-3 0 0 0 14 24
K 140-6 0 0 0 6 0
K 169-7 0 0 0 0 0
K 3587-1 0 0 0 0 0
K 879-2 0 0 0 0 0
K 892-3 0 0 0 0 0
K 892-4 0 0 0 0 0
K 892-5 0 0 0 0 0
tubes %>% pivot_longer(c(momid, dadid), values_to = "genotype", values_ptypes = character()) %>%
count(genotype, name) %>% pivot_wider(values_from="n") %>% arrange(genotype) %>%
kable(caption="Number of stigmas split by paternal or maternal genotype")
Number of stigmas split by paternal or maternal
genotype
| H 3–15 |
16 |
|
| H 794-2 |
22 |
52 |
| H 866-1 |
|
46 |
| H 866-2 |
95 |
28 |
| H 879 2-2 |
9 |
100 |
| H 879 G 2-2 |
11 |
|
| H 879 N-5 |
55 |
21 |
| H 892-1 |
1 |
|
| H 892-3 |
10 |
|
| H 899 2E-1 |
25 |
50 |
| K 115-2 |
36 |
|
| K 116-1 |
25 |
|
| K 116-2 |
36 |
46 |
| K 116-3 |
52 |
21 |
| K 140-6 |
14 |
21 |
| K 169-7 |
10 |
|
| K 3587-1 |
13 |
|
| K 879-2 |
33 |
|
| K 892-3 |
9 |
47 |
| K 892-4 |
12 |
56 |
| K 892-5 |
31 |
27 |
Plot raw data
Pollen tubes
mytheme <- theme(legend.text=element_text(size=rel(1)), legend.position="right", axis.text = element_text(colour="black", size=rel(1)), text=element_text(size=14), axis.ticks.x = element_blank())
timecolors <- scale_color_brewer(palette=3, type="qual", labels=c("4 hr","24 hr"))
crosslabs <- gsub("x", " x ",levels(tubes$cross), fixed=T)
(tubeplot.mid <-
ggplot(tubes, aes(x=cross, y=mid, color=hr)) +
labs(x="", y="Pollen tubes at middle of style", color="Time") +
geom_violin(position=position_dodge(), draw_quantiles=c(0.25,0.5,0.75), size=0.5, bw=1) +
geom_sina(bw=0.1) +
scale_x_discrete(labels=crosslabs) +
theme_classic() + mytheme + timecolors)

(tubeplot.bottom <-
ggplot(tubes, aes(x=cross, y=bottom, color=hr)) +
labs(x="", y="Pollen tubes at bottom of style", color="Time") +
geom_violin(position=position_dodge(), draw_quantiles=c(0.25,0.5,0.75), size=0.5, bw=1) +
geom_sina(bw=0.1)+
scale_x_discrete(labels=crosslabs) +
theme_classic() + mytheme + timecolors)

(tubeplot.ratio <-
ggplot(tubes, aes(x=cross, y=ratio, color=hr)) +
labs(x="", y="Ratio of pollen tubes at bottom : middle of style",color="Time") +
geom_violin(position=position_dodge(), draw_quantiles=c(0.25,0.5,0.75), size=0.5, bw=0.1) +
geom_sina(bw=0.1)+
scale_y_continuous(expand = expansion(add=c(0,0.01)), breaks = scales::pretty_breaks(n = 5)) +
scale_x_discrete(labels=crosslabs) +
theme_classic() + mytheme + timecolors)

(tubeplot.justmid <-
ggplot(tubes, aes(x=cross, y=justmid, color=hr)) +
labs(x="", y="Difference of pollen tubes at middle and bottom of style",color="Time") +
geom_violin(position=position_dodge(), draw_quantiles=c(0.25,0.5,0.75), size=0.5, bw=1) +
geom_sina(bw=1) +
scale_x_discrete(labels=crosslabs) +
theme_classic() + mytheme + timecolors)

(tubeplot.mid.bottom <-
ggplot(tubes, aes(x=bottom, y=mid)) +
labs(x="Pollen tubes at bottom of style", y="Pollen tubes at middle of style", color="Cross", linetype="Time") +
geom_abline(slope=1, size=1) +
geom_point(color="grey") +
stat_ellipse(aes(linetype=hr, color=cross), size=1) +
coord_fixed(xlim=c(0,NA),ylim=c(0,NA))+
scale_color_discrete(labels=crosslabs)+ scale_linetype_discrete(labels=c("4 hr","24 hr"))+
theme_classic()+theme(legend.text=element_text(size=rel(1)), legend.position="right", axis.text = element_text(colour="black", size=rel(1)), text=element_text(size=14)))

Models
Pollen tubes at middle of style
#Quasi-Poisson (NB1), log link, zero inflation
mod <- glmmTMB(mid~cross*hr + (1|momid) + (1|dadid), data=tubes, family="poisson")
summary(mod)
Family: poisson ( log )
Formula: mid ~ cross * hr + (1 | momid) + (1 | dadid)
Data: tubes
AIC BIC logLik deviance df.resid
2356.1 2398.5 -1168.0 2336.1 505
Random effects:
Conditional model:
Groups Name Variance Std.Dev.
momid (Intercept) 0.3110 0.5577
dadid (Intercept) 0.1884 0.4341
Number of obs: 515, groups: momid, 12; dadid, 20
Conditional model:
Estimate Std. Error z value Pr(>|z|)
(Intercept) 1.45293 0.29999 4.843 1.28e-06 ***
crossKxH -0.06835 0.26864 -0.254 0.79915
crossHxH -0.14991 0.44239 -0.339 0.73471
crossHxK -1.18796 0.38278 -3.103 0.00191 **
hr24hr 0.12162 0.07449 1.633 0.10254
crossKxH:hr24hr -0.03452 0.11629 -0.297 0.76658
crossHxH:hr24hr 0.40353 0.09862 4.092 4.28e-05 ***
crossHxK:hr24hr 1.15566 0.14760 7.830 4.89e-15 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
crosshr.x <- data.frame(crosshr=levels(tubes$crosshr), x=rep(1:4, each=2)+rep(c(-0.25, 0.25), 4))
cont <- glmmTMB(mid~crosshr + (1|momid) + (1|dadid), data=tubes, family="poisson") %>%
glht(linfct = mcp(crosshr=tube.contrasts)) %>%
summary(test=adjusted(type="fdr")) %>% tidy %>%
separate(contrast, c("lvl1", "lvl2"), sep = " - ", extra="merge") %>%
mutate(signif = adj.p.value < 0.05,
stars = signif.num(adj.p.value),
height = c(rep(c(1,1,2,3),2),4,5,NA,NA),
x1 = crosshr.x[match(lvl1, crosshr.x$crosshr),"x"],
x2 = crosshr.x[match(lvl2, crosshr.x$crosshr),"x"])
kable(cont[,-c(1,4, 7, 9,11:13)], digits=c(0,0,3,3,3,8), caption="Contrasts")
Contrasts
| HxH4hr |
HxH24hr |
-0.525 |
0.065 |
0.000 |
*** |
| HxK4hr |
HxK24hr |
-1.277 |
0.127 |
0.000 |
*** |
| HxH4hr |
HxK4hr |
1.038 |
0.248 |
0.000 |
*** |
| HxH24hr |
HxK24hr |
0.286 |
0.240 |
0.466 |
|
| KxH4hr |
KxH24hr |
-0.087 |
0.089 |
0.565 |
|
| KxK4hr |
KxK24hr |
-0.122 |
0.074 |
0.246 |
|
| KxH4hr |
KxK4hr |
-0.068 |
0.269 |
0.799 |
|
| KxH24hr |
KxK24hr |
-0.103 |
0.264 |
0.799 |
|
| HxH4hr |
KxK4hr |
-0.150 |
0.442 |
0.799 |
|
| HxH24hr |
KxK24hr |
0.254 |
0.441 |
0.799 |
|
| HxH4hr + HxK4hr |
KxK4hr - KxH4hr |
-1.270 |
0.715 |
0.227 |
|
| HxH24hr + HxK24hr |
KxK24hr - KxH24hr |
0.324 |
0.706 |
0.799 |
|
timefills <- scale_fill_brewer(palette=3, type="qual", labels=c("24 hr","4 hr"), direction=-1)
cld.mod <- ref_grid(mod) %>%
emmeans(~ cross*hr) %>%
summary %>%
mutate(response = exp(emmean), uSE = exp(emmean+SE), lSE = exp(emmean-SE))
kable(cld.mod[, -c(3:7)], digits=1, caption = "Estimated marginal means")
Estimated marginal means
| KxK |
4hr |
4.3 |
5.8 |
3.2 |
| KxH |
4hr |
4.0 |
5.3 |
3.0 |
| HxH |
4hr |
3.7 |
5.0 |
2.7 |
| HxK |
4hr |
1.3 |
1.7 |
1.0 |
| KxK |
24hr |
4.8 |
6.5 |
3.6 |
| KxH |
24hr |
4.4 |
5.8 |
3.2 |
| HxH |
24hr |
6.2 |
8.4 |
4.6 |
| HxK |
24hr |
4.7 |
6.1 |
3.6 |
(mid.emplot <- ggplot(cld.mod, aes(y=response, x=cross, fill=hr)) +
geom_signif(y_position=cont$height+max(cld.mod$uSE), xmin = cont$x1, xmax = cont$x2, annotations=cont$stars, vjust=0.5) +
geom_col(position=position_dodge2()) +
geom_linerange(aes(ymin=lSE, ymax=uSE), position=position_dodge2(0.9)) +
labs(x="", y="Pollen tubes at middle of style",fill="Time") +
scale_y_continuous(limits=c(0,NA), expand = expansion(add=c(0,0.5)), breaks = scales::pretty_breaks(n = 8)) +
scale_x_discrete(labels=crosslabs) +
theme_classic() + mytheme + timefills)

Pollen tubes at bottom of style
#Quasi-Poisson (NB1), log link, zero inflation
mod <- glmmTMB(bottom~cross*hr + (1|momid) + (1|dadid), data=tubes, family="poisson")
summary(mod)
Family: poisson ( log )
Formula: bottom ~ cross * hr + (1 | momid) + (1 | dadid)
Data: tubes
AIC BIC logLik deviance df.resid
1986.6 2029.1 -983.3 1966.6 505
Random effects:
Conditional model:
Groups Name Variance Std.Dev.
momid (Intercept) 0.4547 0.6743
dadid (Intercept) 0.5061 0.7114
Number of obs: 515, groups: momid, 12; dadid, 20
Conditional model:
Estimate Std. Error z value Pr(>|z|)
(Intercept) 1.2431 0.4056 3.065 0.002175 **
crossKxH -1.5379 0.4365 -3.523 0.000426 ***
crossHxH -0.4829 0.6069 -0.796 0.426201
crossHxK -2.9025 0.5257 -5.521 3.36e-08 ***
hr24hr 0.3079 0.0842 3.657 0.000255 ***
crossKxH:hr24hr 0.6037 0.1784 3.385 0.000713 ***
crossHxH:hr24hr 0.9775 0.1234 7.922 2.34e-15 ***
crossHxK:hr24hr 1.9668 0.2669 7.368 1.73e-13 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cont <- glmmTMB(bottom~crosshr + (1|momid) + (1|dadid), data=tubes, family="poisson") %>%
glht(linfct = mcp(crosshr=tube.contrasts)) %>%
summary(test=adjusted(type="fdr")) %>% tidy %>%
separate(contrast, c("lvl1", "lvl2"), sep = " - ", extra="merge") %>%
mutate(signif = adj.p.value < 0.05,
stars = signif.num(adj.p.value),
height = c(rep(c(1,1,2,3),2),4,5,NA,NA),
x1 = crosshr.x[match(lvl1, crosshr.x$crosshr),"x"],
x2 = crosshr.x[match(lvl2, crosshr.x$crosshr),"x"])
kable(cont[,-c(1,4, 7, 9,11:13)], digits=c(0,0,3,3,3,8), caption="Contrasts")
Contrasts
| HxH4hr |
HxH24hr |
-1.285 |
0.090 |
0.000 |
*** |
| HxK4hr |
HxK24hr |
-2.275 |
0.253 |
0.000 |
*** |
| HxH4hr |
HxK4hr |
2.420 |
0.427 |
0.000 |
*** |
| HxH24hr |
HxK24hr |
1.430 |
0.385 |
0.000 |
*** |
| KxH4hr |
KxH24hr |
-0.912 |
0.157 |
0.000 |
*** |
| KxK4hr |
KxK24hr |
-0.308 |
0.084 |
0.001 |
*** |
| KxH4hr |
KxK4hr |
-1.538 |
0.436 |
0.001 |
*** |
| KxH24hr |
KxK24hr |
-0.934 |
0.429 |
0.044 |
* |
| HxH4hr |
KxK4hr |
-0.483 |
0.607 |
0.465 |
|
| HxH24hr |
KxK24hr |
0.495 |
0.604 |
0.465 |
|
| HxH4hr + HxK4hr |
KxK4hr - KxH4hr |
-1.848 |
0.933 |
0.064 |
. |
| HxH24hr + HxK24hr |
KxK24hr - KxH24hr |
0.493 |
0.893 |
0.581 |
|
cld.mod <- ref_grid(mod) %>%
emmeans(~ cross*hr) %>%
summary %>%
mutate(response = exp(emmean), uSE = exp(emmean+SE), lSE = exp(emmean-SE))
kable(cld.mod[, -c(3:7)], digits=1, caption = "Estimated marginal means")
Estimated marginal means
| KxK |
4hr |
3.5 |
5.2 |
2.3 |
| KxH |
4hr |
0.7 |
1.1 |
0.5 |
| HxH |
4hr |
2.1 |
3.2 |
1.4 |
| HxK |
4hr |
0.2 |
0.3 |
0.1 |
| KxK |
24hr |
4.7 |
7.1 |
3.1 |
| KxH |
24hr |
1.9 |
2.8 |
1.2 |
| HxH |
24hr |
7.7 |
11.7 |
5.1 |
| HxK |
24hr |
1.9 |
2.7 |
1.3 |
(bottom.emplot <- ggplot(cld.mod, aes(y=response, x=cross, fill=hr)) +
geom_signif(y_position=cont$height+max(cld.mod$uSE), xmin = cont$x1, xmax = cont$x2, annotations=cont$stars, vjust=0.5) +
geom_col(position=position_dodge2()) +
geom_linerange(aes(ymin=lSE, ymax=uSE), position=position_dodge2(0.9)) +
labs(x="", y="Pollen tubes at bottom of style",fill="Time") +
scale_y_continuous(limits=c(0,NA), expand = expansion(add=c(0,0.5)), breaks = scales::pretty_breaks(n = 8)) +
scale_x_discrete(labels=crosslabs) +
theme_classic() + mytheme + timefills)

Pollen tubes at bottom : middle of style
#Beta binomial - for overdispersed binomial data. Input is the number of successes and failures.
mod <- glmmTMB(cbind(bottom, adjmid-bottom)~cross*hr + (1|momid) + (1|dadid), data=tubes, family="binomial")
summary(mod)
Family: binomial ( logit )
Formula:
cbind(bottom, adjmid - bottom) ~ cross * hr + (1 | momid) + (1 | dadid)
Data: tubes
AIC BIC logLik deviance df.resid
1637.5 1680.0 -808.8 1617.5 505
Random effects:
Conditional model:
Groups Name Variance Std.Dev.
momid (Intercept) 0.1652 0.4065
dadid (Intercept) 0.4298 0.6556
Number of obs: 515, groups: momid, 12; dadid, 20
Conditional model:
Estimate Std. Error z value Pr(>|z|)
(Intercept) 0.9038 0.3395 2.662 0.00776 **
crossKxH -2.2759 0.4466 -5.096 3.47e-07 ***
crossHxH -0.8376 0.4972 -1.685 0.09205 .
crossHxK -2.7801 0.4470 -6.219 5.00e-10 ***
hr24hr 0.8585 0.1858 4.621 3.82e-06 ***
crossKxH:hr24hr 0.4220 0.2766 1.526 0.12710
crossHxH:hr24hr 1.0905 0.2386 4.571 4.86e-06 ***
crossHxK:hr24hr 0.6268 0.3416 1.835 0.06654 .
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cont <- glmmTMB(cbind(bottom, adjmid-bottom)~crosshr + (1|momid) + (1|dadid), data=tubes, family="binomial") %>%
glht(linfct = mcp(crosshr=tube.contrasts)) %>%
summary(test=adjusted(type="fdr")) %>% tidy %>%
separate(contrast, c("lvl1", "lvl2"), sep = " - ", extra="merge") %>%
mutate(signif = adj.p.value < 0.05,
stars = signif.num(adj.p.value),
height = c(rep(c(1,1,2,3),2),4,5,NA,NA),
x1 = crosshr.x[match(lvl1, crosshr.x$crosshr),"x"],
x2 = crosshr.x[match(lvl2, crosshr.x$crosshr),"x"])
kable(cont[,-c(1,4, 7, 9,11:13)], digits=c(0,0,3,3,3,8), caption="Contrasts")
Contrasts
| HxH4hr |
HxH24hr |
-1.949 |
0.151 |
0.000 |
*** |
| HxK4hr |
HxK24hr |
-1.485 |
0.287 |
0.000 |
*** |
| HxH4hr |
HxK4hr |
1.942 |
0.435 |
0.000 |
*** |
| HxH24hr |
HxK24hr |
2.406 |
0.400 |
0.000 |
*** |
| KxH4hr |
KxH24hr |
-1.280 |
0.206 |
0.000 |
*** |
| KxK4hr |
KxK24hr |
-0.859 |
0.186 |
0.000 |
*** |
| KxH4hr |
KxK4hr |
-2.276 |
0.447 |
0.000 |
*** |
| KxH24hr |
KxK24hr |
-1.854 |
0.444 |
0.000 |
*** |
| HxH4hr |
KxK4hr |
-0.838 |
0.497 |
0.110 |
|
| HxH24hr |
KxK24hr |
0.253 |
0.506 |
0.673 |
|
| HxH4hr + HxK4hr |
KxK4hr - KxH4hr |
-1.342 |
0.709 |
0.078 |
. |
| HxH24hr + HxK24hr |
KxK24hr - KxH24hr |
-0.046 |
0.652 |
0.943 |
|
cld.mod <- ref_grid(mod) %>%
emmeans(~ cross*hr) %>%
summary %>%
mutate(response = plogis(emmean), uSE = plogis(emmean+SE), lSE = plogis(emmean-SE))
kable(cld.mod[, -c(3:7)], digits=2, caption = "Estimated marginal means")
Estimated marginal means
| KxK |
4hr |
0.71 |
0.78 |
0.64 |
| KxH |
4hr |
0.20 |
0.27 |
0.15 |
| HxH |
4hr |
0.52 |
0.60 |
0.43 |
| HxK |
4hr |
0.13 |
0.18 |
0.10 |
| KxK |
24hr |
0.85 |
0.89 |
0.80 |
| KxH |
24hr |
0.48 |
0.57 |
0.39 |
| HxH |
24hr |
0.88 |
0.91 |
0.84 |
| HxK |
24hr |
0.40 |
0.48 |
0.33 |
(ratio.emplot <- ggplot(cld.mod, aes(y=response, x=cross, fill=hr)) +
geom_signif(y_position=cont$height/15+1, xmin = cont$x1, xmax = cont$x2, annotations=cont$stars, vjust=0.5) +
geom_col(position=position_dodge2()) +
geom_linerange(aes(ymin=lSE, ymax=uSE), position=position_dodge2(0.9)) +
labs(x="", y="Ratio of pollen tubes at bottom : middle of style",fill="Time") +
scale_y_continuous(expand = expansion(add=c(0,0.05)), breaks = seq(0,1, by=0.2)) +
scale_x_discrete(labels=crosslabs) +
theme_classic() + mytheme + timefills)

Package citations
citation("glmmTMB")
To cite glmmTMB in publications use:
Mollie E. Brooks, Kasper Kristensen, Koen J. van Benthem, Arni
Magnusson, Casper W. Berg, Anders Nielsen, Hans J. Skaug, Martin
Maechler and Benjamin M. Bolker (2017). glmmTMB Balances Speed and
Flexibility Among Packages for Zero-inflated Generalized Linear Mixed
Modeling. The R Journal, 9(2), 378-400.
A BibTeX entry for LaTeX users is
@Article{,
author = {Mollie E. Brooks and Kasper Kristensen and Koen J. {van Benthem} and Arni Magnusson and Casper W. Berg and Anders Nielsen and Hans J. Skaug and Martin Maechler and Benjamin M. Bolker},
title = {{glmmTMB} Balances Speed and Flexibility Among Packages for Zero-inflated Generalized Linear Mixed Modeling},
year = {2017},
journal = {The R Journal},
url = {https://journal.r-project.org/archive/2017/RJ-2017-066/index.html},
pages = {378--400},
volume = {9},
number = {2},
}
citation("emmeans")
To cite package 'emmeans' in publications use:
Lenth R (2022). _emmeans: Estimated Marginal Means, aka Least-Squares
Means_. R package version 1.7.3,
<https://CRAN.R-project.org/package=emmeans>.
A BibTeX entry for LaTeX users is
@Manual{,
title = {emmeans: Estimated Marginal Means, aka Least-Squares Means},
author = {Russell V. Lenth},
year = {2022},
note = {R package version 1.7.3},
url = {https://CRAN.R-project.org/package=emmeans},
}
citation("multcomp")
Please cite the multcomp package by the following reference:
Torsten Hothorn, Frank Bretz and Peter Westfall (2008). Simultaneous
Inference in General Parametric Models. Biometrical Journal 50(3),
346--363.
A BibTeX entry for LaTeX users is
@Article{,
title = {Simultaneous Inference in General Parametric Models},
author = {Torsten Hothorn and Frank Bretz and Peter Westfall},
journal = {Biometrical Journal},
year = {2008},
volume = {50},
number = {3},
pages = {346--363},
}