Как автоматизировать dunn_test и ggboxplot?

Я работаю над кадром данных (называемым df), который выглядит примерно так (здесь сокращено по практическим причинам):

Наблюдаемый Шеннон ИнвСимпсон Ровность Месяц 688 4.553810 23.365814 0,6969632 февраль 749 4.381557 15.162467 0,6619927 февраль 610 3.829187 11.178981 0,5970548 февраль 665 4.201113 16.284009 0,6463463 Маршировать 839 5.185554 43.198709 0,7702601 Маршировать 757 4.782258 31.011366 0,7213751 Маршировать 516 3.239304 4.765211 0,5186118 апрель ... ... ... ... ...

Я запускаю апостериорный тест, используя тест Данна, затем добавляю позиции 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() уже бы очень помогла, потому что я не знаю, с чего начать...

Заранее спасибо за любой совет, который у вас есть. :)

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
70
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вот функция, которая принимает строку символов в качестве аргумента. Вы можете вызвать эту функцию для каждой из переменных.

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.

Спасибо за ваш ответ, однако при запуске я получаю следующую ошибку: Ошибка в select(): ! Невозможно создать подмножество несуществующих столбцов. ✖ Колонка formula(paste(yvariable, "~ Month")) не существует. Backtrace: 1. global dunn_boxplot("Observed") 26. dplyr:::select.data.frame(., !!!syms(c(результат, группа)))

sophiethomas 12.04.2023 03:33

Я сделал ошибку в коде. Теперь это должно работать. Извини за это. Другие ответы тоже хороши.

qdread 12.04.2023 11:30

Большое спасибо @qdread У меня все еще есть ошибка с ggboxplot(df, x = "Month", y = y_variable) : Error in ggboxplot(df, x = "Month", y = y_variable) : object 'y_variable' not found Поэтому вместо этого я использовал ggplotgeom_boxplot. Вот так: bxp <- ggplot2::ggplot(df) + geom_boxplot(aes(x = .data[["Month"]], y = .data[[yvariable]]))

sophiethomas 12.04.2023 20:52

Ага, я нашел еще одну опечатку в моем коде. Я случайно написал y_variable в одном месте, а yvariable в другом. Я не смог протестировать код, потому что вы не предоставили воспроизводимый пример, который упростил бы проверку на наличие ошибок. См. stackoverflow.com/questions/5963269/…

qdread 13.04.2023 01:54

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
}
Ответ принят как подходящий

Просто используйте formula и 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 с каждым новым набором данных :)

sophiethomas 12.04.2023 20:44

Другие вопросы по теме