data<-Behavioral.Trials.All.Data
#Separate trials
T1<- data[data$trial=="1",]
T2<- data[data$trial=="2",]
T3<- data[data$trial=="3",]
data23<- rbind(T2,T3)
#separate experiments
exp1<-(data[data$exp=="1",])
exp2<-(data[data$exp=="2",])
#separate groups
hot<-(data[data$hot=="y",])
control<-(data[data$hot=="n",])
# Reorder subjects based on the 'hot' group
data <- data %>%
mutate(subject = factor(subject, levels = unique(subject[order(hot)])))
ggplot(data, aes(x = trial, y = groomALL, color = hot)) +
stat_summary(fun = mean, geom = "line", aes(group = hot)) +
stat_summary(fun.data = mean_se, geom = "errorbar", width = 0.2) +
stat_summary(fun = mean, geom = "point", size = 3) +
scale_color_manual(values = c("n" = "grey50", "y" = "red")) +
labs(title = "Grooming Bouts Across Trials by Treatment - Raw Data", y = "groomALL", x = "Trial", color="Hot?")
# Experiment 1
p1<-ggplot(exp1, aes(x = factor(trial), y = groomALL, color = hot, group = hot)) +
geom_jitter(width = 0.2, alpha = 0.5, size = 1.8) + # raw data
stat_summary(fun = mean, geom = "line", aes(group = hot), linewidth = 1) + # mean line
stat_summary(fun.data = mean_se, geom = "errorbar", width = 0.2) + # error bars
stat_summary(fun = mean, geom = "point", size = 3, shape = 18) + # mean points
scale_color_manual(values = c("n" = "grey50", "y" = "red")) +
labs(title = "Exp 1 - Data + Means and SE" ,
y = "groomALL",
x = "Trial",
color = "Hot?") +
theme_minimal()
# Experiment 2
p2<-ggplot(exp2, aes(x = factor(trial), y = groomALL, color = hot, group = hot)) +
geom_jitter(width = 0.2, alpha = 0.5, size = 1.8) +
stat_summary(fun = mean, geom = "line", aes(group = hot), linewidth = 1) +
stat_summary(fun.data = mean_se, geom = "errorbar", width = 0.2) +
stat_summary(fun = mean, geom = "point", size = 3, shape = 18) +
scale_color_manual(values = c("n" = "grey50", "y" = "red")) +
labs(title = "Exp 2 - Data + Means and SE",
y = "",
x = "Trial",
color = "Hot?") +
theme_minimal()
library(patchwork)
## Warning: package 'patchwork' was built under R version 4.3.3
# Combine plots and collect shared legend
(p1 + p2) +
plot_layout(ncol = 2, guides = "collect") &
theme(legend.position = "bottom")
#no transformations - count data
modelhot <- glmer( groomALL ~ hot + (1 | subject), data = data, family = poisson)
modelnull<-glmer( groomALL ~ 1 + (1 | subject), data = data, family = poisson)
anova(modelhot,modelnull)
## Data: data
## Models:
## modelnull: groomALL ~ 1 + (1 | subject)
## modelhot: groomALL ~ hot + (1 | subject)
## npar AIC BIC logLik -2*log(L) Chisq Df Pr(>Chisq)
## modelnull 2 1132.5 1138.3 -564.24 1128.5
## modelhot 3 1119.3 1128.0 -556.63 1113.3 15.222 1 9.557e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
anova(modelhot)
## Analysis of Variance Table
## npar Sum Sq Mean Sq F value
## hot 1 15.103 15.103 15.103
#significant effect of hot on groomALL
#Model with trial and experiment (model with all interactions does not converge - too complex for this dataset)
modeli<-glmer( groomALL ~ hot + trial * exp + (1 | subject), data=data, family=poisson)
modelplus <- glmer( groomALL ~ hot + trial + exp + (1 | subject), data=data, family=poisson)
modelexp<- glmer( groomALL ~ hot + trial + (1 | subject), data=data, family=poisson)
modeltrial<-glmer( groomALL ~ hot + exp + (1 | subject), data=data, family=poisson)
anova(modeli, modelplus, modelhot, modelexp, modeltrial)
## Data: data
## Models:
## modelhot: groomALL ~ hot + (1 | subject)
## modeltrial: groomALL ~ hot + exp + (1 | subject)
## modelexp: groomALL ~ hot + trial + (1 | subject)
## modelplus: groomALL ~ hot + trial + exp + (1 | subject)
## modeli: groomALL ~ hot + trial * exp + (1 | subject)
## npar AIC BIC logLik -2*log(L) Chisq Df Pr(>Chisq)
## modelhot 3 1119.3 1128.0 -556.63 1113.3
## modeltrial 4 1113.6 1125.3 -552.79 1105.6 7.6684 1 0.0056196 **
## modelexp 5 1072.5 1087.2 -531.27 1062.5 43.0526 1 5.329e-11 ***
## modelplus 6 1066.9 1084.4 -527.43 1054.9 7.6684 1 0.0056196 **
## modeli 8 1052.7 1076.2 -518.36 1036.7 18.1379 2 0.0001152 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#interaction model is best fit. However, my hypothesis was simple: subjects in the hot treatment was groom more often than those in the control treatment. should i stick to the simple model? or do i need to report all of these interactions if it affects interpretability?
model <- glmer( groomALL ~ hot + trial * exp + (1 | subject), data=data, family=poisson)
library(car)
## Warning: package 'car' was built under R version 4.3.3
## Loading required package: carData
## Warning: package 'carData' was built under R version 4.3.3
##
## Attaching package: 'car'
## The following object is masked from 'package:dplyr':
##
## recode
Anova(model, type="III")
## Analysis of Deviance Table (Type III Wald chisquare tests)
##
## Response: groomALL
## Chisq Df Pr(>Chisq)
## (Intercept) 3.0991 1 0.0783356 .
## hot 19.4448 1 1.035e-05 ***
## trial 36.4974 2 1.188e-08 ***
## exp 4.2887 1 0.0383671 *
## trial:exp 18.0471 2 0.0001205 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#treatment effect persists in the interaction model. Significant interaction for trial*exp, significant effect of trial and exp
# Residuals vs Fitted
plot(model, which = 1) # same as plot(fitted(model), resid(model))
# QQ Plot for normality
qqnorm(resid(model))
qqline(resid(model), col = "red")
# Histogram
hist(resid(model), breaks = 20, main = "Histogram of Residuals", xlab = "Residuals")
shapiro.test(resid(model)) # Note: sensitive to sample size
##
## Shapiro-Wilk normality test
##
## data: resid(model)
## W = 0.98351, p-value = 0.0952
# Plot absolute residuals vs fitted values
plot(fitted(model), abs(resid(model)),
xlab = "Fitted values", ylab = "Absolute Residuals",
main = "Homoscedasticity Check")
abline(lm(abs(resid(model)) ~ fitted(model)), col = "red")
#residuals look okay
library(lmerTest)
#including exp does not improve model
model <- glmer(groomALL ~ hot +
(1 | subject),
data = T1, family=poisson)
nullmodel <- glmer(groomALL ~ 1 +
(1 | subject),
data = T1, family=poisson)
anova(model, nullmodel)
## Data: T1
## Models:
## nullmodel: groomALL ~ 1 + (1 | subject)
## model: groomALL ~ hot + (1 | subject)
## npar AIC BIC logLik -2*log(L) Chisq Df Pr(>Chisq)
## nullmodel 2 290.01 293.67 -143.01 286.01
## model 3 276.85 282.34 -135.43 270.85 15.16 1 9.876e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Anova(model, type="III")
## Analysis of Deviance Table (Type III Wald chisquare tests)
##
## Response: groomALL
## Chisq Df Pr(>Chisq)
## (Intercept) 6.1568 1 0.01309 *
## hot 15.2094 1 9.623e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#significant improvement on the null model, significant effect of treatment in trial 1
#including exp does not improve model
model <- glmer( groomALL ~ hot +
(1 | subject),
data = T2, family=poisson)
nullmodel <- glmer(groomALL ~ 1 +
(1 | subject),
data = T2, family=poisson)
anova(model, nullmodel)
## Data: T2
## Models:
## nullmodel: groomALL ~ 1 + (1 | subject)
## model: groomALL ~ hot + (1 | subject)
## npar AIC BIC logLik -2*log(L) Chisq Df Pr(>Chisq)
## nullmodel 2 358.26 361.92 -177.13 354.26
## model 3 360.25 365.74 -177.12 354.25 0.0106 1 0.9181
summary(model)
## Generalized linear mixed model fit by maximum likelihood (Laplace
## Approximation) [glmerMod]
## Family: poisson ( log )
## Formula: groomALL ~ hot + (1 | subject)
## Data: T2
##
## AIC BIC logLik -2*log(L) df.resid
## 360.2 365.7 -177.1 354.2 43
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -2.8702 -1.3430 -0.0594 0.9798 3.0063
##
## Random effects:
## Groups Name Variance Std.Dev.
## subject (Intercept) 1.058 1.028
## Number of obs: 46, groups: subject, 23
##
## Fixed effects:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 1.64718 0.23507 7.007 2.43e-12 ***
## hoty 0.01058 0.10163 0.104 0.917
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr)
## hoty -0.217
#does not improve upon null model
#including exp does not improve model
model <- glmer( groomALL ~ hot +
(1 | subject),
data = T3, family=poisson)
nullmodel <- glmer( groomALL ~ 1 +
(1 | subject),
data = T3, family=poisson)
anova(model, nullmodel)
## Data: T3
## Models:
## nullmodel: groomALL ~ 1 + (1 | subject)
## model: groomALL ~ hot + (1 | subject)
## npar AIC BIC logLik -2*log(L) Chisq Df Pr(>Chisq)
## nullmodel 2 412.72 416.37 -204.36 408.72
## model 3 405.02 410.51 -199.51 399.02 9.6951 1 0.001848 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Anova(model, type="II")
## Analysis of Deviance Table (Type II Wald chisquare tests)
##
## Response: groomALL
## Chisq Df Pr(>Chisq)
## hot 9.8027 1 0.001743 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#significant improvement on null model, hot grooms significantly more in trial 3
#interaction does not improve model in exp 1
model <- glmer(groomALL ~ hot +
(1 | subject),
data = exp1, family=poisson)
nullmodel <- glmer(groomALL ~ 1 +
(1 | subject),
data = exp1, family=poisson)
anova(model, nullmodel)
## Data: exp1
## Models:
## nullmodel: groomALL ~ 1 + (1 | subject)
## model: groomALL ~ hot + (1 | subject)
## npar AIC BIC logLik -2*log(L) Chisq Df Pr(>Chisq)
## nullmodel 2 509.27 513.74 -252.64 505.27
## model 3 511.26 517.96 -252.63 505.26 0.0135 1 0.9075
Anova(model, type="II")
## Analysis of Deviance Table (Type II Wald chisquare tests)
##
## Response: groomALL
## Chisq Df Pr(>Chisq)
## hot 0.0135 1 0.9074
#treatment not significant in experiment 1
# Experiment 2 treatment model vs null
model <- glmer( groomALL ~ hot +
(1 | subject),
data = exp2, family=poisson)
nullmodel <- glmer( groomALL ~ 1 +
(1 | subject),
data = exp2, family=poisson)
anova(model, nullmodel)
## Data: exp2
## Models:
## nullmodel: groomALL ~ 1 + (1 | subject)
## model: groomALL ~ hot + (1 | subject)
## npar AIC BIC logLik -2*log(L) Chisq Df Pr(>Chisq)
## nullmodel 2 471.04 475.50 -233.52 467.04
## model 3 469.45 476.15 -231.72 463.45 3.5854 1 0.05829 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Anova(model, type="II")
## Analysis of Deviance Table (Type II Wald chisquare tests)
##
## Response: groomALL
## Chisq Df Pr(>Chisq)
## hot 3.7896 1 0.05157 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#Nearly significant effect of treatment. hot treatment=more grooming, not significant.
#combined experiments = larger sample size = more power to make a conclusion. However, patterns don’t match between experiments.
modelside<- glmer(groomALL~ side + (1|subject), data=data, family=poisson)
summary(modelside)
## Generalized linear mixed model fit by maximum likelihood (Laplace
## Approximation) [glmerMod]
## Family: poisson ( log )
## Formula: groomALL ~ side + (1 | subject)
## Data: data
##
## AIC BIC logLik -2*log(L) df.resid
## 1134.0 1142.8 -564.0 1128.0 135
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -3.6134 -1.4693 -0.5606 1.0459 6.7604
##
## Random effects:
## Groups Name Variance Std.Dev.
## subject (Intercept) 1.332 1.154
## Number of obs: 138, groups: subject, 23
##
## Fixed effects:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 1.3535 0.3442 3.933 8.4e-05 ***
## sider 0.3353 0.4934 0.679 0.497
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr)
## sider -0.694
#no effect from which side of experimental tank was nearest the window
library(hms)
## Warning: package 'hms' was built under R version 4.3.3
library(lubridate)
## Warning: package 'lubridate' was built under R version 4.3.3
##
## Attaching package: 'lubridate'
## The following object is masked from 'package:hms':
##
## hms
## The following objects are masked from 'package:base':
##
## date, intersect, setdiff, union
# Step 1: Add ":00" to make it HH:MM:SS
data$time_clean <- paste0(data$time, ":00")
# Step 2: Parse as hms time
data$time_parsed <- hms::as_hms(data$time_clean)
# Step 3: Extract decimal hour
data$hour_decimal <- hour(data$time_parsed) + minute(data$time_parsed)/60
data$hour2 <- data$hour_decimal^2
#output warning based on size of quadratic variables, rescale:
data$hour2_scaled <- (data$hour_decimal^2) / 100 # or /1000
# Then refit
model_quad_scaled <- glmer(groomALL ~ hot + hour2_scaled + (1 | subject),
data = data, family = poisson)
Anova(model_quad_scaled, type="III")
## Analysis of Deviance Table (Type III Wald chisquare tests)
##
## Response: groomALL
## Chisq Df Pr(>Chisq)
## (Intercept) 4.7266 1 0.02970 *
## hot 5.6493 1 0.01746 *
## hour2_scaled 37.5161 1 9.066e-10 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#significant quadratic effect of time of day tested. More grooming occurs during early morning and evening hours and is reduced during midday.
#significant effect of treatment persists when time of day is taken into account.
#hot*time interaction is not significant, results in higher AIC.
#Plot
data$hot <- as.factor(data$hot)
# Center time
data$hour_c <- scale(data$hour_decimal, scale = FALSE)
data$hour2_c <- data$hour_c^2
model_interact <- glmer(groomALL ~ hour_c + hour2_c + hot + (1 | subject),
data = data, family = poisson)
# Create time sequence
hour_seq <- seq(min(data$hour_decimal), max(data$hour_decimal), length.out = 100)
hour_c_seq <- hour_seq - mean(data$hour_decimal)
hour2_c_seq <- hour_c_seq^2
# Create grid for both levels of hot
new_data <- expand.grid(
hour_c = hour_c_seq,
hot = levels(data$hot)
)
# Add hour2 and original hour for plotting
new_data$hour2_c <- new_data$hour_c^2
new_data$hour_decimal <- new_data$hour_c + mean(data$hour_decimal)
new_data$predicted <- predict(model_interact,
newdata = new_data,
type = "response",
re.form = NA)
ggplot(new_data, aes(x = hour_decimal, y = predicted, color = hot)) +
geom_line(linewidth = 1.2) +
labs(title = "Predicted Grooming Across Time of Day by Treatment",
x = "Hour of Day",
y = "Predicted Grooming Count",
color = "Treatment") +
theme_minimal()
modeltank<- glmer(groomALL~ as.factor(tank) + (1|subject), data=data, family=poisson)
summary(modeltank)
## Generalized linear mixed model fit by maximum likelihood (Laplace
## Approximation) [glmerMod]
## Family: poisson ( log )
## Formula: groomALL ~ as.factor(tank) + (1 | subject)
## Data: data
##
## AIC BIC logLik -2*log(L) df.resid
## 1121.2 1141.6 -553.6 1107.2 131
##
## Scaled residuals:
## Min 1Q Median 3Q Max
## -3.6002 -1.4663 -0.5435 0.7652 6.7020
##
## Random effects:
## Groups Name Variance Std.Dev.
## subject (Intercept) 1.26 1.122
## Number of obs: 138, groups: subject, 23
##
## Fixed effects:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 1.99192 0.34335 5.801 6.57e-09 ***
## as.factor(tank)2 -0.31276 0.20353 -1.537 0.1244
## as.factor(tank)3 -0.04776 0.20216 -0.236 0.8132
## as.factor(tank)4 0.46409 0.26185 1.772 0.0763 .
## as.factor(tank)5 -0.97868 0.50559 -1.936 0.0529 .
## as.factor(tank)6 -0.26671 0.15540 -1.716 0.0861 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Correlation of Fixed Effects:
## (Intr) as.()2 as.()3 as.()4 as.()5
## as.fctr(t)2 -0.312
## as.fctr(t)3 -0.317 0.585
## as.fctr(t)4 -0.298 0.447 0.450
## as.fctr(t)5 -0.677 0.216 0.218 0.200
## as.fctr(t)6 -0.373 0.762 0.766 0.585 0.256
#no significant effect of home tank on grooming