-
Notifications
You must be signed in to change notification settings - Fork 1
/
generate_lmer_table.R
96 lines (78 loc) · 3.73 KB
/
generate_lmer_table.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# Ensure required packages are loaded
library(lme4)
library(car)
library(effectsize)
library(kableExtra)
library(webshot)
generate_lmer_table <- function(data, formula_str, output_label = "lmer_table", caption_label = "Linear mixed effects model") {
# Silly workaround to make sure formula_str updates in the global environment
formula_str <<- formula_str
# Parse formula from string
formula_obj <<- as.formula(formula_str)
formula_obj <- as.formula(formula_str)
# Fit a linear mixed-effects model
fit <<- lm(formula_obj, data = data)
fit <- lmer(formula_obj, data = data)
# Calculate effect sizes for the model - partial omega squared
effect_size <<- effectsize(fit, data = data)
effect_size <- effectsize(fit)
# Obtain ANOVA table for the model
lmer_summary <- Anova(fit, type = 3, test = "F")
# Create a vector to store custom term names
term_names <- character()
# Get terms from the model and ask the user for custom labels
model_terms <- rownames(lmer_summary)
for (term in model_terms) {
cat(sprintf("Current term: %s\n", term))
term_names[term] <- readline(prompt = "Enter custom label or press enter to keep current name: ")
if (term_names[term] == "") {
term_names[term] <- term
}
}
# Extract model parameters
fixef_table <- fixef(fit)
se_table <- sqrt(diag(vcov(fit)))
f_table <- lmer_summary[,"F"]
df_table <- lmer_summary[,"Df"]
df_res_table <- lmer_summary[,"Df.res"]
pval_table <- lmer_summary[,"Pr(>F)"]
# Extract effect sizes and associated confidence intervals
es <- effect_size$Std_Coefficient[1:nrow(effect_size)]
ci_low <- effect_size$CI_low[1:nrow(effect_size)]
ci_high <- effect_size$CI_high[1:nrow(effect_size)]
# Create a significance notation based on p-value thresholds
p_value_signif <- ifelse(pval_table < 0.001, "***",
ifelse(pval_table < 0.01, "**",
ifelse(pval_table < 0.05, "*",
ifelse(pval_table < 0.06, ".", ""))))
# Create a summary table
lm_table <- data.frame(Coefficients = format(fixef_table, scientific = TRUE, digits = 3),
EffectSize = ifelse(es < -0.010, sprintf("%.3f", es),
ifelse(es < 0.010, "<0.010", sprintf("%.3f", es))),
EffectSizeCI = sprintf("[%s, %s]", format(ci_low, digits = 2), format(ci_high, digits = 2)),
FValue = format(f_table, digits = 3),
DF = sprintf("(%s, %s)", format(df_table, digits = 1), format(df_res_table, digits = 1)),
pValue = ifelse(pval_table < 0.0001, "<0.0001", sprintf("%.3f", pval_table)),
Significance = p_value_signif) %>%
rownames_to_column(var = "Term") %>%
mutate(Term = term_names[Term])
# Export the table for a scientific publication
html_file_name <- paste0(output_label, ".html")
png_file_name <- paste0(output_label, ".png")
kable(lm_table, align = c("l", "c", "c", "c", "c", "c", "c", "l"),
caption = caption_label) %>%
kable_classic(full_width = FALSE) %>%
column_spec(1, bold = TRUE) %>%
column_spec(2:3, width = "2cm") %>%
column_spec(4, width = "3cm") %>%
column_spec(5, width = "1.3cm") %>%
column_spec(6, width = "1.3cm") %>%
column_spec(7, width = "2cm") %>%
row_spec(0, bold = TRUE) %>%
save_kable(file = html_file_name)
webshot(url = html_file_name, file = png_file_name, selector = "table", zoom = 2)
cat("HTML and PNG generated successfully!\n")
return(png_file_name)
}
# Usage
# generate_lmer_table(data = d, formula_str = "y ~ x*z + (1|id)", output_label = "lmer_table", caption_label = "Linear mixed effects model")