Я работаю над кадром данных (называемым df), который выглядит примерно так (здесь сокращено по практическим причинам):
Я запускаю апостериорный тест, используя тест Данна, затем добавляю позиции xy и рисую все в виде диаграмм. Это работает, но мой код очень повторяющийся...
library(rstatix)
obs_dunn <- dunn_test(Observed ~ Month, data=df, p.adjust.method = "BH")
obs_dunn <- obs_dunn %>% arrange(p.adj)
obs_dunn <- obs_dunn %>% add_xy_position(x = "Month")
obs_bxp <- ggboxplot(df, x = "Month", y = "Observed" ) +
stat_pvalue_manual(obs_dunn, label = "p.adj.signif", hide.ns = TRUE)
obs_bxp
sh_dunn <- dunn_test(Shannon ~ Month, data=df, p.adjust.method = "BH")
sh_dunn <- sh_dunn %>% arrange(p.adj)
sh_dunn <- sh_dunn %>% add_xy_position(x = "Month")
sh_bxp <- ggboxplot(df, x = "Month", y = "Shannon" ) +
stat_pvalue_manual(sh_dunn, label = "p.adj.signif", hide.ns = TRUE)
sh_bxp
inv_dunn <- dunn_test(InvSimpson ~ Month, data=df, p.adjust.method = "BH")
inv_dunn <- inv_dunn %>% arrange(p.adj)
inv_dunn <- inv_dunn %>% add_xy_position(x = "Month")
inv_bxp <- ggboxplot(df, x = "Month", y = "InvSimpson" ) +
stat_pvalue_manual(inv_dunn, label = "p.adj.signif", hide.ns = TRUE)
inv_bxp
ev_dunn <- dunn_test(Evenness ~ Month, data=df, p.adjust.method = "BH")
ev_dunn <- ev_dunn %>% arrange(p.adj)
ev_dunn <- ev_dunn %>% add_xy_position(x = "Month")
ev_bxp <- ggboxplot(df, x = "Month", y = "Evenness" ) +
stat_pvalue_manual(ev_dunn, label = "p.adj.signif", hide.ns = TRUE)
ev_bxp
Я получаю базовые диаграммы с добавленными звездами значимости, например, вот результат для «Наблюдаемого»:
Это одни и те же строки кода для каждого индекса (Observed, Shannon, InvSimpson, Evenness), поэтому я хотел бы сделать цикл for, но я новичок в этом, и я действительно борюсь.
У вас есть идеи, как я могу запустить цикл для dunn_test()
, add_xy_position()
и ggboxplot()
на моих 4 индексах? Предпочтительно с отдельным кадром данных в качестве вывода для каждого индекса.
Даже просто петля для первого шага dunn_test()
уже бы очень помогла, потому что я не знаю, с чего начать...
Заранее спасибо за любой совет, который у вас есть. :)
Вот функция, которая принимает строку символов в качестве аргумента. Вы можете вызвать эту функцию для каждой из переменных.
dunn_boxplot <- function(yvariable) {
dunn <- dunn_test(formula(paste(yvariable, "~ Month")), data=df, p.adjust.method = "BH") %>%
arrange(p.adj) %>%
add_xy_position(x = "Month")
bxp <- ggboxplot(df, x = "Month", y = yvariable) +
stat_pvalue_manual(dunn, label = "p.adj.signif", hide.ns = TRUE)
}
Вызовите функцию следующим образом. Повторите для остальных трех переменных.
obs_bxp <- dunn_boxplot("Observed")
Главное, на что следует обратить внимание, это то, что ваши четыре блока кода отличаются только именем переменной y. Поэтому он передается в качестве аргумента. Вам нужно использовать formula(paste(...)
, чтобы собрать формулу в виде строки символов, а затем привести ее к классу formula
.
Я сделал ошибку в коде. Теперь это должно работать. Извини за это. Другие ответы тоже хороши.
Большое спасибо @qdread У меня все еще есть ошибка с ggboxplot(df, x = "Month", y = y_variable)
: Error in ggboxplot(df, x = "Month", y = y_variable) : object 'y_variable' not found
Поэтому вместо этого я использовал ggplot
geom_boxplot
. Вот так: bxp <- ggplot2::ggplot(df) + geom_boxplot(aes(x = .data[["Month"]], y = .data[[yvariable]]))
Ага, я нашел еще одну опечатку в моем коде. Я случайно написал y_variable
в одном месте, а yvariable
в другом. Я не смог протестировать код, потому что вы не предоставили воспроизводимый пример, который упростил бы проверку на наличие ошибок. См. stackoverflow.com/questions/5963269/…
qdread показал очень плавный подход. У меня другой подход, с использованием цикла for. Поскольку вы не опубликовали воспроизводимый пример, я не смог протестировать свой код, и он может привести к ошибкам, но он должен дать вам представление. Удачи!
list <- list() # creates empty list
count<-1 # creates an indicator starting with one, increasing by one every iteration, first plot will be saved as first item of list, second plot as second item, ...
for (i in c("Observed","Shannon","InvSimpson","Evenness")){ # i will take the first value in c(...) in the first iteration
# the second value in the second iteration, ...
list[[count]] <- eval(parse(
text=paste0('dunn_test(',i,'~ Month, data=df, p.adjust.method = "BH")') #paste0 pasts a string, eval(parse(text = "string")) executes the string
))
list[[count]] <- list[[count]] %>% arrange(p.adj)
list[[count]] <- list[[count]] %>% add_xy_position(x = "Month")
list[[count]] <- eval(parse(text=paste0('ggboxplot(df, x =,',i,', y = paste0(i)) +
stat_pvalue_manual(',list[[count]],', label = "p.adj.signif", hide.ns = TRUE)')))
count<- count+1 # count indicator increases by 1
}
Просто используйте fo
rmula и data
в качестве аргументов в функции, а также ...
для дополнительных аргументов, таких как bracket.nudge.y=
, чтобы скорректировать глупые n.s
пробелы.
dunn_bxp <- \(fo, data, plot=TRUE, ...) {
vars <- all.vars(fo)
dnn <- rstatix::dunn_test(fo, data=data, p.adjust.method = "BH")
dnn_p <- rstatix::add_xy_position(dnn, x=vars[2])
if (plot) {
p <- ggpubr::ggboxplot(data, x=vars[2], y=vars[1]) +
ggpubr::stat_pvalue_manual(dnn_p, label = "p.adj.signif", hide.ns=TRUE, ...)
print(p)
return(invisible(as.data.frame(dnn[1:8])))
} else {
return(as.data.frame(dnn[1:8]))
}
}
Если plot=TRUE
(по умолчанию), он отображает и невидимо возвращает статистику.
r <- dunn_bxp(fo=observed ~ month, data=df, bracket.nudge.y=-1000)
head(r)
# .y. group1 group2 n1 n2 statistic p p.adj
# 1 observed Apr Aug 3 3 -0.6199874 0.535266078 0.71803318
# 2 observed Apr Dec 3 3 -2.7124449 0.006678888 0.08816133
# 3 observed Apr Feb 3 3 -1.1237272 0.261128784 0.50954093
# 4 observed Apr Jan 3 3 -1.7049654 0.088200884 0.32174752
# 5 observed Apr Jul 3 3 -1.7049654 0.088200884 0.32174752
# 6 observed Apr Jun 3 3 0.7749843 0.438348961 0.64291181
Если plot=FALSE
он просто возвращает статистику.
head(dunn_bxp(fo=observed ~ month, data=df, plot=FALSE))
# .y. group1 group2 n1 n2 statistic p p.adj
# 1 observed Apr Aug 3 3 -0.6199874 0.535266078 0.71803318
# 2 observed Apr Dec 3 3 -2.7124449 0.006678888 0.08816133
# 3 observed Apr Feb 3 3 -1.1237272 0.261128784 0.50954093
# 4 observed Apr Jan 3 3 -1.7049654 0.088200884 0.32174752
# 5 observed Apr Jul 3 3 -1.7049654 0.088200884 0.32174752
# 6 observed Apr Jun 3 3 0.7749843 0.438348961 0.64291181
Данные:
set.seed(557)
df <- data.frame(observed=round(rep(runif (12, 500, 800), each=3) + rep.int(rnorm(12, 0, 64), 3)),
month=rep(month.abb, each=3))
Вау, спасибо, это действительно отличный код, и я смогу легко применить его к другим наборам данных! Чтобы избавиться от ns
, я использовал следующую строку кода между dunn_test
и add_xy_position
: dnn <- dplyr::arrange(.data = dnn, p.adj)
. Таким образом, мне не придется менять bracket.nudge.y
с каждым новым набором данных :)
Спасибо за ваш ответ, однако при запуске я получаю следующую ошибку: Ошибка в
select()
: ! Невозможно создать подмножество несуществующих столбцов. ✖ Колонкаformula(paste(yvariable, "~ Month"))
не существует. Backtrace: 1. global dunn_boxplot("Observed") 26. dplyr:::select.data.frame(., !!!syms(c(результат, группа)))