Her kommer noen eksempler på figurer og automatiske tabeller, Hvis du trykker på “show” boksene på høyre side får du opp koden, hvis du vil ta en titt. Her har jeg brukt en rosa palett her (for gøy, men lite fargeblindvennlig) men det finnes selvsagt uendelig mange fine fargekombinasjoner, sjekk for eksempel pakken RColorBrewer, og Viridis. For disse eksemplene har jeg brukt pakkene: RColorBrewer, reshape2, ggdist, cowplot, ggpubr, og selvfølgelig tidyverse. Jeg anbefaler å sjekke The R Graph Gallery og from Data to Viz for inspirasjon og tilgjengelig kode for ulike figurer som kan lages i R.
Vi kan for eksempel visualisere korrelasjoner mellom de kognitive domenene ved å lage en heatmap. Det er flere muligheter, enten med den innebygde funksjonen heatmap() eller med ggplot2 funksjonen geom_tile(). Her er den aller enkleste varianten med default farger først:
# Load the data
loaddata <- readRDS("cogdat.rds")
# Select only variables you want to correlate
cogdat <- loaddata %>%
select(5:13)
# Run Pearson correlation (default)
cor_matrix <- cor(cogdat)
# Make heatmap using heatmap()
heatmap(cor_matrix)
Selvom det er en lettvint måte å få oversikt over korrelasjonene, så mangler den en del nyttig informasjon. Her er en litt mer avansert variant med ggplot2 og geom_tile() som har mange muligheter for tilpasninger:
# From wide to long, remove all "_" in variable names
cor_matrix_melt <- melt(cor_matrix,
varnames = c("Variable1", "Variable2"),
value.name = "Correlation") %>%
mutate(across(c(Variable1, Variable2), ~str_replace_all(., "_", " ")))
# Make a heatmap using geom_tile()
heatmap_V1 <- ggplot(cor_matrix_melt, aes(x = Variable1, y = Variable2, fill = Correlation)) +
geom_tile() +
scale_fill_gradientn(colors = brewer.pal(9, "RdPu"), name = "Correlation") +
labs(title = "Correlation between cognitive domains") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, vjust = 1,size = 12, hjust = 1),
axis.text.y = element_text(size = 12),
axis.title = element_blank(),
plot.title = element_text(size = 20, face = "bold", hjust = 1),
panel.grid = element_blank()) +
coord_fixed()
heatmap_V1
Man kan også vise selve korrelasjonen i hver “tile”, samt vise kun diagonalen sånn at det ikke blir dobbelt opp:
# Select lower diagonal
cor_matrix_melt_diag <- cor_matrix_melt %>%
filter(as.numeric(as.factor(Variable1)) >= as.numeric(as.factor(Variable2)))
variables_order <- levels(factor(cor_matrix_melt$Variable1))
variables_order <- rev(variables_order)
# Plot updated heatmap using geom_tile()
heatmap_V2 <- ggplot(cor_matrix_melt_diag, aes(x = Variable1, y = Variable2, fill = Correlation)) +
geom_tile() +
geom_text(aes(label = sprintf("%.2f", Correlation)), color = "black", size = 3) +
scale_fill_gradientn(colors = brewer.pal(9, "RdPu"), name = "Correlation") +
labs(title = "Correlation between cognitive domains") +
scale_x_discrete(limits = variables_order) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, vjust = 1,
size = 12, hjust = 1),
axis.text.y = element_text(size = 12),
axis.title = element_blank(),
plot.title = element_text(size = 20, face = "bold", hjust = 1),
panel.grid = element_blank()) +
coord_fixed()
heatmap_V2
Hvis man vil visualisere korrelasjonen mellom 2 variabler kan man bruke scatterplot. Min favoritt inkluderer regresjonslinjen med confidence interval, en liten tekst som viser korrelasjonsstyrken, og densities på sidene så man kan se distribusjonen per gruppe:
# Set color palette for each group
col_palette <- c("CTRL" = "#999999", "BD" = "#F768A1","SCZ" = "#4B0082")
# Order the groups according to preferred sequence
datacor <- loaddata %>%
mutate(diag_group = factor(diag_group, levels = c("CTRL", "BD", "SCZ", ordered = TRUE)))
# Create main scatterplot
pmain <- ggplot(datacor, aes(x = psychomotor_ps, y = semantic_fluency, color = diag_group))+
geom_point(shape = 16, size = 3, alpha = 0.7) +
geom_smooth(method = lm, color = "grey", fill = "grey", se = TRUE)+
guides(color = guide_legend(override.aes = list(size = 5))) +
annotate("text", x = 4, y = -2, label = "r = .48", color = "#404040", size = 4) +
labs(y = "Semantic fluency",
x = "Psychomotor processing speed",
color = "Group") +
scale_color_manual(values = col_palette) +
theme_classic() +
theme(legend.position.inside = c(0.1,0.85),
legend.title = element_blank(),
legend.text = element_text(size = 12),
axis.text = element_text(size = 12),
legend.key = element_blank(),
axis.title = element_text(size = 12, face = "bold")) +
border()
# Create densities along x-axis
xdens <- axis_canvas(pmain, axis = "x") +
geom_density(data = datacor, aes(x = psychomotor_ps, fill = diag_group),
alpha = 0.7, linewidth = 0.2) +
scale_fill_manual(values = col_palette)
# Create densities along y-axis
ydens <- axis_canvas(pmain, axis = "y", coord_flip = TRUE) +
geom_density(data = datacor, aes(x = psychomotor_ps, fill = diag_group),
alpha = 0.7, linewidth = 0.2) +
scale_fill_manual(values = col_palette) +
coord_flip()
# Add densities to main plot, pmain
addx <- insert_xaxis_grob(pmain, xdens, grid::unit(.2, "null"), position = "top")
final_scatterplot <- insert_yaxis_grob(addx, ydens, grid::unit(.2, "null"), position = "right")
# Use ggdraw to print final plot
ggdraw(final_scatterplot)
Vi bruker ofte line-charts for å vise gjennomsnittsskårer på tvers av kognitive tester/domener mellom ulike grupper. Man kan lage fine line-charts i R, for eksempel noe som dette (PS: disse skårene er ikke centered på friske kontroller men hele samplet):
# Summarise (mean) by group across all cognitive domains
sumvars <- loaddata %>%
group_by(diag_group) %>%
summarise(across(verbal_learning:cognitive_control,
mean,
na.rm = FALSE,
.names = "{.col}"))
# Take dataset from wide to long, reorder variables according to preference
longline <- sumvars %>%
pivot_longer(cols = 2:10,
names_to = "cog_domain",
values_to = "cog_score") %>%
mutate(cog_domain = str_replace_all(cog_domain, "_", " ")) %>%
mutate(cog_domain = factor(cog_domain, levels = c("fine motor speed",
"psychomotor ps",
"mental ps",
"attention",
"verbal learning",
"verbal memory",
"semantic fluency",
"working memory",
"cognitive control"), ordered = TRUE),
diag_group = factor(diag_group, levels = c("CTRL",
"BD",
"SCZ", ordered = TRUE)))
# Make line-chart
linechart_V1 <- ggplot(longline, aes(x=cog_domain, y=cog_score, group=diag_group)) +
geom_line(aes(color = diag_group), size = 1)+
labs(title = "Performance across domains",
x = "",
y = "Z-score") +
geom_point(aes(color = diag_group)) +
geom_hline(yintercept = 0, linetype = "dashed", color = "#333333") +
theme_minimal()+
scale_color_manual(values=c("#999999", "#F768A1", "#4B0082")) +
theme(axis.text.x = element_text(size = 12, angle = 45, vjust = 0.5),
axis.text.y = element_text(size = 12),
axis.title = element_text(size = 12),
plot.title = element_text(size = 20, face = "bold", hjust = 0.5),
legend.text = element_text(size = 12),
legend.title = element_blank())
linechart_V1
Her kan det være mer informativt hvis man legger til errorbars. Det er litt mer komplisert, her har jeg en funksjon jeg bruker for å summere variablene så jeg får en ny dataframe med mean, median, sem, og ci:
# Function to extract summary statistics
fn_summary_SE <- function(data, measurevar, groupvars) {
data %>%
group_by(across(all_of(groupvars))) %>%
summarise(
N = n(),
mean = mean(!!sym(measurevar), na.rm = TRUE),
sd = sd(!!sym(measurevar), na.rm = TRUE),
sem = sd / sqrt(N),
ci = sem * qt(0.975, N - 1), # Assuming a 95% confidence interval
.groups = 'drop'
)
}
# From wide to long, reorder variables
longdat <- loaddata %>%
pivot_longer(cols = 5:13, names_to = "cog_domain", values_to = "cog_score") %>%
mutate(cog_domain = str_replace_all(cog_domain, "_", " ")) %>%
mutate(cog_domain = factor(cog_domain,
levels = c("fine motor speed",
"psychomotor ps",
"mental ps",
"attention",
"verbal learning",
"verbal memory",
"semantic fluency",
"working memory",
"cognitive control"),
ordered = TRUE),
diag_group = factor(diag_group, levels = c("CTRL", "BD", "SCZ", ordered = TRUE)))
# Create new dataset using function
sumrepdat <- fn_summary_SE(longdat, measurevar = "cog_score",
groupvars = c("diag_group", "cog_domain"))
# Plot the summarized data with error bars representing confidence interval
linechart_V2 <- ggplot(sumrepdat, aes(x = cog_domain, y = mean, group = diag_group)) +
geom_line(aes(color = diag_group), size = 1) +
geom_point(aes(color = diag_group)) +
geom_errorbar(aes(ymin = mean - ci, ymax = mean + ci, color = diag_group), width = 0.2) +
geom_hline(yintercept = 0, linetype = "dashed", color = "#333333") +
labs(title = "Performance across domains", x = "", y = "Z-score") +
theme_minimal() +
scale_color_manual(values = c("#999999", "#F768A1", "#4B0082")) +
theme(axis.text.x = element_text(size = 12, angle = 45, vjust = 0.5),
axis.text.y = element_text(size = 12),
axis.title = element_text(size = 12),
plot.title = element_text(size = 20, face = "bold", hjust = 0.5),
legend.text = element_text(size = 12),
legend.title = element_blank())
linechart_V2
Det er litt mer informativt, for eksempel ser vi overlapp mellom BD og SCZ på attention, og mellom BD og CTRL på verbal learning og memory! Videre så vil jeg bare vise et eksempel på interactive plots som er såå kule. Her har jeg forsøkt å gjenskape samme plot med pakken plotly. Det er kanskje litt mer en “hack”, og jeg fikk mye hjelp av Chat-GPT her. Beveg musen over datapunktene så får du statistiske detaljer opp som mean, SD, SEM, CI og N:
# Create custom hover text
sumrepdathover <- sumrepdat %>%
mutate(hover_text = paste(
"Group: ", diag_group, "<br>",
"Domain: ", cog_domain, "<br>",
"Mean: ", round(mean, 2), "<br>",
"SD: ", round(sd, 2), "<br>",
"SEM: ", round(sem, 2), "<br>",
"CI: ±", round(ci, 2), "<br>",
"N: ", N, sep = ""))
# Make interactive plot
line2_plotly <- plot_ly(sumrepdathover, x = ~cog_domain, y = ~mean, type = 'scatter', mode = 'lines+markers',
color = ~diag_group, colors = c("#999999", "#F768A1", "#1D006C"),
text = ~hover_text, hoverinfo = 'text',
error_y = ~list(array = ci)) %>%
layout(title = list(text = "<b>Performance across domains</b>", font = list(size = 25, family = "Arial", color = "black"),x = 0.5, xanchor = "center", yanchor = "top"),
xaxis = list(title = "",tickfont = list(size = 14),tickangle = -45,automargin = TRUE),
yaxis = list(title = "Z-score",tickfont = list(size = 14),zeroline = FALSE),
legend = list(title = list(text = "Group", font = list(size = 14)),
font = list(size = 14), x = 1, y = 0.5),
hoverlabel = list(font = list(size = 12)),
shapes = list(list(type = "line",
x0 = 0, x1 = 1, xref = "paper",
y0 = 0, y1 = 0, yref = "y",
line = list(color = "#333333", dash = "dot"))),
margin = list(t = 100)) %>%
style(line = list(width = 4))
line2_plotly
Hvis man vil ta en nærmere titt på spesifikke kognitive domener kan vi for eksempel lage raincloudplots. Disse har blitt veldig populære fordi de viser mange ulike aspekter av dataene, som distribusjonen, individuelle datapunkter, og median/IQR. Her finnes det ulike funksjoner, her har jeg brukt pakken ggdist og funksjoner som stat_slab() og stat_dotsinterval():
# Get cognitive data and diagnostic group
cogdata <- loaddata %>%
mutate(diag_group = factor(diag_group,
levels = c("SCZ", "BD", "CTRL", ordered = TRUE))) %>%
select(4:13)
# Make it rain!
raincloud <- ggplot(cogdata, aes(x = psychomotor_ps, y = diag_group, fill = diag_group))+
stat_slab(aes(thickness = after_stat(pdf*n)),
scale = 0.9, alpha = 0.7) +
stat_dotsinterval(side = "bottom",
scale = 0.7,
slab_size = NA, position = "dodge") +
scale_fill_manual(values = col_palette) +
scale_color_manual(values = col_palette) +
labs(title="psychomotor processing speed",
x = "Z-score",
y = "") +
theme_minimal(base_size = 12) +
theme(legend.position = "none",
panel.grid.major.y = element_blank(),
plot.title = element_text(size = 20, face = "bold", hjust = 0.5))
raincloud
En lignende variant er violin plot, som viser distribusjonen rundt en boxplot. Her har jeg lagt til statistiske resultater med pakken ggsignif:
# Make some music!
violin <- ggplot(cogdata, aes(x = diag_group, y = psychomotor_ps, fill = diag_group)) +
geom_violin(trim = FALSE, alpha = 0.7) +
geom_boxplot(width = 0.1, alpha = 0.4, fill = "white") +
geom_hline(yintercept = 0.0, color = "#404040", linetype = "dotted") +
geom_signif(comparisons = list(c("SCZ", "CTRL")), map_signif_level = TRUE,
y_position = 4.2, size = 0.6, textsize = 8, vjust = 0.5) +
geom_signif(comparisons = list(c("BD", "CTRL")), map_signif_level = TRUE,
y_position = 3.4, size = 0.6, textsize = 8, vjust = 0.5) +
labs(y = "",
title = "Psychomotor processing speed",
x = "") +
scale_fill_manual(values = col_palette) +
scale_color_manual(values = col_palette) +
theme_minimal() +
theme(panel.grid = element_blank(),
legend.position="none",
plot.title = element_text(size = 20, hjust = 0.5, face = "bold"),
axis.text = element_text(size = 14),
plot.margin = margin(20, 1, 1, 1))
violin
Her kommer eksempeler på hvordan automatiske tabeller kan lages i R. Først ute er kognitive data.
# Load packages
library(gtsummary)
library(gt)
library(flextable)
# Load data
loaddata <- readRDS("cogdat.rds")
# Prepare data
dataprep <- loaddata %>%
mutate(diag_group = factor(diag_group, levels = c("CTRL", "BD", "SCZ")),
sex_female = ifelse(sex == "female", 1, 0),
sex_female = as.logical(sex_female))
# Select relevant columns
selected_columns <- dataprep %>%
select(fine_motor_speed, psychomotor_ps, mental_ps,
attention, verbal_learning, verbal_memory,
semantic_fluency, working_memory, cognitive_control, diag_group)
# Make custom table
custom_table_V1 <- selected_columns %>%
tbl_summary(by = "diag_group", label = list(fine_motor_speed ~ "Fine-motor speed",
psychomotor_ps ~ "Psychomotor speed",
mental_ps ~ "Mental speed",
attention ~ "Attention",
verbal_learning ~ "Verbal learning",
verbal_memory ~ "Verbal memory",
semantic_fluency ~ "Semantic fluency",
working_memory ~ "Working memory",
cognitive_control ~ "Cognitive control"),
missing = "no", statistic = list(all_continuous() ~ "{mean} ({sd})"),
digits = all_continuous() ~ 2) %>%
modify_header(label ~ "**Characteristic**", stat_1 ~ "**CTRL** (N = {n})", stat_2 ~ "**BD** (N = {n})", stat_3 ~ "**SCZ** (N = {n})") %>%
modify_caption("<div style='text-align: left;'><strong>Table 1.</strong> Cognitive data</div>")
custom_table_V1
| Characteristic | CTRL (N = 770)1 | BD (N = 289)1 | SCZ (N = 343)1 |
|---|---|---|---|
| Fine-motor speed | 0.31 (0.57) | -0.14 (1.01) | -0.43 (1.18) |
| Psychomotor speed | 0.41 (0.84) | -0.02 (0.96) | -0.57 (0.95) |
| Mental speed | 0.26 (0.73) | -0.05 (0.95) | -0.43 (1.00) |
| Attention | 0.12 (0.95) | -0.16 (0.89) | -0.30 (0.87) |
| Verbal learning | 0.27 (0.84) | 0.14 (0.99) | -0.41 (1.04) |
| Verbal memory | 0.23 (0.85) | 0.12 (0.92) | -0.44 (1.09) |
| Semantic fluency | 0.37 (0.86) | 0.06 (0.98) | -0.63 (0.86) |
| Working memory | 0.33 (0.96) | -0.13 (0.90) | -0.42 (0.92) |
| Cognitive control | 0.26 (0.65) | -0.10 (1.01) | -0.39 (1.10) |
| 1 Mean (SD) | |||
Det er mulig å legge til en kolonne med statistisk analyse med funksjonen add_p(), Den velger automatisk en statistisk test basert på dataene, og hvilken test den har kjørt havner i footnote på tabellen:
# Make custom table with statistics
custom_table_V2 <- selected_columns %>%
tbl_summary(by = "diag_group",
label = list(fine_motor_speed ~ "Fine-motor speed",
psychomotor_ps ~ "Psychomotor speed",
mental_ps ~ "Mental speed",
attention ~ "Attention",
verbal_learning ~ "Verbal learning",
verbal_memory ~ "Verbal memory",
semantic_fluency ~ "Semantic fluency",
working_memory ~ "Working memory",
cognitive_control ~ "Cognitive control"),
missing = "no", statistic = list(all_continuous() ~ "{mean} ({sd})"),
digits = all_continuous() ~ 2) %>%
add_p() %>% # Automatically selects an appropriate test for each variable
modify_header(label ~ "**Characteristic**",
stat_1 ~ "**CTRL** (N = {n})",
stat_2 ~ "**BD** (N = {n})",
stat_3 ~ "**SCZ** (N = {n})",
p.value ~ "**p-value**") %>%
modify_caption("<div style='text-align: left;'><strong>Table 1.</strong> Cognitive data</div>")
custom_table_V2
| Characteristic | CTRL (N = 770)1 | BD (N = 289)1 | SCZ (N = 343)1 | p-value2 |
|---|---|---|---|---|
| Fine-motor speed | 0.31 (0.57) | -0.14 (1.01) | -0.43 (1.18) | <0.001 |
| Psychomotor speed | 0.41 (0.84) | -0.02 (0.96) | -0.57 (0.95) | <0.001 |
| Mental speed | 0.26 (0.73) | -0.05 (0.95) | -0.43 (1.00) | <0.001 |
| Attention | 0.12 (0.95) | -0.16 (0.89) | -0.30 (0.87) | <0.001 |
| Verbal learning | 0.27 (0.84) | 0.14 (0.99) | -0.41 (1.04) | <0.001 |
| Verbal memory | 0.23 (0.85) | 0.12 (0.92) | -0.44 (1.09) | <0.001 |
| Semantic fluency | 0.37 (0.86) | 0.06 (0.98) | -0.63 (0.86) | <0.001 |
| Working memory | 0.33 (0.96) | -0.13 (0.90) | -0.42 (0.92) | <0.001 |
| Cognitive control | 0.26 (0.65) | -0.10 (1.01) | -0.39 (1.10) | <0.001 |
| 1 Mean (SD) | ||||
| 2 Kruskal-Wallis rank sum test | ||||
Hvis du åpner kodeboksen her ser du hvordan man kan lagre den formatterte tabellen direkte i et word dokument:
# Save to word file
library(flextable)
tbl <- as_flex_table(custom_table_V2)
# save_as_docx(tbl, path = "/Users/linnssaether/Documents/RStudio_archive/project_3/tables/table_cogdata.docx")
Til slutt et eksempel med demografisk info og kliniske variabler. Her bruker jeg data fra en av mine artikler for å lage tabellen.
# Load data
sample_data <- read_rds("cogCRP_basFU_FINALsamp_addedDUP_051223.rds")
# Prepare data
dataprep <- sample_data %>%
mutate(diag_group = factor(diag_group, levels = c("SZ", "BD", "HC")),
sex_female = ifelse(sex == "female", 1, 0),
sex_female = as.logical(sex_female))
# Select columns
selected_columns <- dataprep %>%
select(age, sex_female, educat, IQwasi_2test, BMI,
PANSSNegative, PANSSPositive, PANSSDisorgConcrete, PANSSExcited, PANSSDepressed,
YMRS, GAF_S, GAF_F, DUP, DDD_AP, DDD_AD, DDD_AE, DDD_LIT, DDD_tot, diag_group)
# Make custom table
custom_table_sample <- selected_columns %>%
tbl_summary(by = "diag_group", label = list(age ~ "Age",
sex_female ~ "Sex (female)",
educat ~ "Education (years)",
IQwasi_2test ~ "WASI IQ (2-subtests)",
BMI ~ "BMI (kg/m²)",
PANSSNegative ~ "PANSS Negative",
PANSSPositive ~ "PANSS Positive",
PANSSDisorgConcrete ~ "PANSS Disorganized",
PANSSExcited ~ "PANSS Excited",
PANSSDepressed ~ "PANSS Depressed",
GAF_S ~ "GAF Symptom",
GAF_F ~ "GAF Function",
DUP ~"Duration of untreated illness",
DDD_AP ~ "Antipsychotics, DDD",
DDD_AD ~ "Antidepressants, DDD",
DDD_AE ~ "Antiepileptics, DDD",
DDD_LIT ~ "Lithium, DDD",
DDD_tot ~ "Total, DDD"),
type = list(PANSSExcited = "continuous", DDD_LIT = "continuous"), missing = "no", statistic = list(all_continuous() ~ "{mean} ({sd})"),
digits = all_continuous() ~ 2) %>%
add_p() %>%
modify_caption("<div style='text-align: left;'><strong>Table 1.</strong> Sample characteristics</div>")
custom_table_sample
| Characteristic | SZ N = 1331 |
BD N = 881 |
HC N = 2201 |
p-value2 |
|---|---|---|---|---|
| Age | 26.19 (6.80) | 28.63 (8.66) | 33.56 (9.31) | <0.001 |
| Sex (female) | 52 (39%) | 52 (59%) | 107 (49%) | 0.014 |
| Education (years) | 12.74 (2.81) | 13.56 (2.22) | 14.50 (2.06) | <0.001 |
| WASI IQ (2-subtests) | 102.98 (14.28) | 111.57 (11.88) | 113.76 (9.49) | <0.001 |
| BMI (kg/m²) | 24.22 (4.27) | 24.51 (4.30) | 24.79 (3.71) | 0.3 |
| PANSS Negative | 12.95 (5.62) | 8.56 (3.12) | NA (NA) | <0.001 |
| PANSS Positive | 10.06 (4.03) | 5.66 (2.49) | NA (NA) | <0.001 |
| PANSS Disorganized | 5.51 (2.42) | 4.20 (1.72) | NA (NA) | <0.001 |
| PANSS Excited | 5.24 (1.57) | 5.03 (1.39) | NA (NA) | 0.5 |
| PANSS Depressed | 8.62 (2.99) | 8.11 (3.02) | NA (NA) | 0.2 |
| YMRS | 5.52 (4.95) | 3.22 (5.00) | NA (NA) | <0.001 |
| GAF Symptom | 43.23 (13.64) | 59.10 (10.68) | NA (NA) | <0.001 |
| GAF Function | 45.44 (14.13) | 55.88 (12.05) | NA (NA) | <0.001 |
| Duration of untreated illness | 112.88 (193.88) | 59.18 (184.46) | NA (NA) | <0.001 |
| Antipsychotics, DDD | 1.31 (0.74) | 0.89 (0.66) | NA (NA) | <0.001 |
| Antidepressants, DDD | 1.41 (0.64) | 1.56 (0.90) | NA (NA) | 0.7 |
| Antiepileptics, DDD | 0.42 (0.25) | 0.84 (0.54) | NA (NA) | 0.050 |
| Lithium, DDD | NA (NA) | 1.08 (0.34) | NA (NA) | |
| Total, DDD | 1.78 (1.07) | 1.69 (1.08) | NA (NA) | 0.5 |
| 1 Mean (SD); n (%) | ||||
| 2 Kruskal-Wallis rank sum test; Pearson’s Chi-squared test | ||||
Men det er ikke så pent med NA(NA). Her fikk jeg hjelp av ChatGPT for å erstatte NA med blank space:
# Replace NA (NA) with empty cells
custom_table_noNA <- custom_table_sample %>%
modify_table_body( ~ .x %>% mutate(across(where(is.character), ~ if_else(. == "NA (NA)", "", .))))
custom_table_noNA
| Characteristic | SZ N = 1331 |
BD N = 881 |
HC N = 2201 |
p-value2 |
|---|---|---|---|---|
| Age | 26.19 (6.80) | 28.63 (8.66) | 33.56 (9.31) | <0.001 |
| Sex (female) | 52 (39%) | 52 (59%) | 107 (49%) | 0.014 |
| Education (years) | 12.74 (2.81) | 13.56 (2.22) | 14.50 (2.06) | <0.001 |
| WASI IQ (2-subtests) | 102.98 (14.28) | 111.57 (11.88) | 113.76 (9.49) | <0.001 |
| BMI (kg/m²) | 24.22 (4.27) | 24.51 (4.30) | 24.79 (3.71) | 0.3 |
| PANSS Negative | 12.95 (5.62) | 8.56 (3.12) | <0.001 | |
| PANSS Positive | 10.06 (4.03) | 5.66 (2.49) | <0.001 | |
| PANSS Disorganized | 5.51 (2.42) | 4.20 (1.72) | <0.001 | |
| PANSS Excited | 5.24 (1.57) | 5.03 (1.39) | 0.5 | |
| PANSS Depressed | 8.62 (2.99) | 8.11 (3.02) | 0.2 | |
| YMRS | 5.52 (4.95) | 3.22 (5.00) | <0.001 | |
| GAF Symptom | 43.23 (13.64) | 59.10 (10.68) | <0.001 | |
| GAF Function | 45.44 (14.13) | 55.88 (12.05) | <0.001 | |
| Duration of untreated illness | 112.88 (193.88) | 59.18 (184.46) | <0.001 | |
| Antipsychotics, DDD | 1.31 (0.74) | 0.89 (0.66) | <0.001 | |
| Antidepressants, DDD | 1.41 (0.64) | 1.56 (0.90) | 0.7 | |
| Antiepileptics, DDD | 0.42 (0.25) | 0.84 (0.54) | 0.050 | |
| Lithium, DDD | 1.08 (0.34) | |||
| Total, DDD | 1.78 (1.07) | 1.69 (1.08) | 0.5 | |
| 1 Mean (SD); n (%) | ||||
| 2 Kruskal-Wallis rank sum test; Pearson’s Chi-squared test | ||||
Sånn, mye bedre! Vi bruker stort sett de samme variablene (med TOP data i det minste), så hver gang du skal ha en tabell kan du derfor bare enkelt kjøre samme kode. Copy-paste koden her i et eget script, og modifiser det etter dine behov.