Как мне показать отдельные точки коробчатой ​​диаграммы в R?

У меня df1:

              Name        Y_N FIPS  score1 score2
 1:        Alabama         0    1   2633      8
 2:         Alaska         0    2    382      1
 3:        Arizona         1    4   2695     41
 4:       Arkansas         1    5   2039     10
 5:     California         1    6  27813    524
 6:       Colorado         0    8   8609    133
 7:    Connecticut         1    9   5390    111
 8:       Delaware         0   10    858      3
 9:        Florida         1   12  14172    215
10:        Georgia         1   13   9847    308
11:         Hawaii         0   15    720      0
12:          Idaho         1   16    845      7

Я хотел бы выполнить T-тест, чтобы увидеть, отличается ли score1 на основе Y_N. Затем я хотел бы противопоставить этих двоих друг другу. Я сделал блок-схему, которая выглядит так:  введите описание изображения здесь

Вместо этого я хочу, чтобы мой график выглядел так, за исключением столбцов уверенности:  введите описание изображения здесь Теперь я хочу перейти с блочной диаграммы на диаграмму, которая показывает все отдельные точки, а затем среднюю горизонтальную линию с 95% доверительные интервалы. Как это сделать? Я также хотел бы добавить текст p-value в угол графика.

Я могу попробовать:

text(x = max(df1$Y_N)+1, 
     y = min(df1$score1)+20000, 
     labels = paste0(
                     "\np-value = ",
                     round(coef_lm[2,4],5),            
     pos = 4)

Но я понимаю, что coef_lm[2,4],5 - это тестовая статистика линейной модели. Как мне получить доступ к результатам t-теста?


person Evan    schedule 30.03.2020    source источник
comment
Теперь, когда вы предоставили свою очень красивую краску для фигуры, пожалуйста, посмотрите мою правку.   -  person Ian Campbell    schedule 30.03.2020


Ответы (4)


Я не уверен, почему вы добавили этот лишний пункт в свой код. Но в исходных данных вы можете использовать ggplot2 и ggpubr.

Редактировать. Теперь он больше похож на ваш рисунок краской.

ggplot(df1,aes(x = as.factor(Y_N), y = score1)) + 
  geom_jitter(position = position_jitter(0.1)) + 
  stat_summary(fun.data = "mean_cl_normal", geom = "errorbar", width = 0.3) +
  stat_summary(fun = "mean", geom = "errorbar",  aes(ymax = ..y.., ymin = ..y..), col = "red", width = 0.5) +
  stat_compare_means(method="t.test") + 
  xlab("Group") + ylab("Score 1")

введите описание изображения здесь

Исходные данные

df1 <- structure(list(Name = structure(1:12, .Label = c("Alabama", "Alaska", 
"Arizona", "Arkansas", "California", "Colorado", "Connecticut", 
"Delaware", "Florida", "Georgia", "Hawaii", "Idaho"), class = "factor"), 
    Y_N = c(0L, 0L, 1L, 1L, 1L, 0L, 1L, 0L, 1L, 1L, 0L, 1L), 
    FIPS = c(1L, 2L, 4L, 5L, 6L, 8L, 9L, 10L, 12L, 13L, 15L, 
    16L), score1 = c(2633L, 382L, 2695L, 2039L, 27813L, 8609L, 
    5390L, 858L, 14172L, 9847L, 720L, 845L), score2 = c(8L, 1L, 
    41L, 10L, 524L, 133L, 111L, 3L, 215L, 308L, 0L, 7L)), class = "data.frame", row.names = c("1:", 
"2:", "3:", "4:", "5:", "6:", "7:", "8:", "9:", "10:", "11:", 
"12:"))
person Ian Campbell    schedule 30.03.2020
comment
Спасибо, Ян! Мне было интересно, хочу ли я проводить t-тест не на основе столбца Y_N, а вместо этого на основе того, если столбец score2 больше 100, как я могу это сделать? - person Evan; 01.04.2020
comment
Добавьте аргумент col = "red" в строку 3. - person Ian Campbell; 01.04.2020

В качестве альтернативы, не устанавливая ggpubr, вы можете вычислить значение p вне ggplot2 и использовать функцию annotate для добавления значения p в график:

pval <- t.test(score1~Y_N,data = df)$p.value

library(ggplot2)
ggplot(df, aes(x = as.factor(Y_N), y = score1, fill = as.factor(Y_N), color = as.factor(Y_N)))+
  geom_boxplot(alpha = 0.3, color = "black", outlier.shape = NA)+
  geom_jitter(show.legend = FALSE)+
  annotate(geom = "text", label = paste("p.value: ",round(pval,3)), x = 1.5, y = max(df$score1)*0.9)

введите описание изображения здесь

РЕДАКТИРОВАТЬ: без коробчатой ​​диаграммы

В качестве альтернативы блочной диаграмме, если вы хотите иметь отдельные точки и полосу, представляющую среднее значение, вы можете сначала вычислить среднее значение для каждой группы в наборе данных ne (здесь я использую для этого пакет dplyr):

library(dplyr)
Mean_df <- df %>% group_by(Y_N) %>% summarise(Mean = mean(score1))

# A tibble: 2 x 2
    Y_N  Mean
  <int> <dbl>
1     0 2640.
2     1 8972.

Затем вы можете построить отдельные точки, используя geom_jitter, и среднее значение, используя geom_errobar, вызвав новый набор данных Mean_df:

library(ggplot2)
ggplot(df, aes(x = as.factor(Y_N), y = score1))+
  geom_jitter(show.legend = FALSE, width = 0.2)+
  geom_errorbar(inherit.aes = FALSE, data = Mean_df, 
                aes(x = as.factor(Y_N),ymin = Mean, ymax = Mean),
                color = "red",width = 0.2)+
  annotate(geom = "text", label = paste("p.value: ",round(pval,3)), 
           x = 1.5, y = max(df$score1)*0.9)

введите описание изображения здесь


Воспроизводимый пример

structure(list(Name = c("Alabama", "Alaska", "Arizona", "Arkansas", 
"California", "Colorado", "Connecticut", "Delaware", "Florida", 
"Georgia", "Hawaii", "Idaho"), Y_N = c(0L, 0L, 1L, 1L, 1L, 0L, 
1L, 0L, 1L, 1L, 0L, 1L), FIPS = c(1L, 2L, 4L, 5L, 6L, 8L, 9L, 
10L, 12L, 13L, 15L, 16L), score1 = c(2633L, 382L, 2695L, 2039L, 
27813L, 8609L, 5390L, 858L, 14172L, 9847L, 720L, 845L), score2 = c(8L, 
1L, 41L, 10L, 524L, 133L, 111L, 3L, 215L, 308L, 0L, 7L)), row.names = c(NA, 
-12L), class = c("data.table", "data.frame"))
person dc37    schedule 30.03.2020
comment
Спасибо за помощь! Как я могу это сделать без коробчатого графика? - person Evan; 30.03.2020
comment
@ Эван, я отредактировал свой ответ. Сообщите мне, если это то, что вы ищете - person dc37; 30.03.2020
comment
Как мне изменить метку оси X, чтобы она не говорила as.factor, и как получить шкалы ошибок? - person Evan; 30.03.2020
comment
Вам стоит взглянуть на ответ @IanCampbell. он ответит на все ваши вопросы. Вы должны подтвердить его / ее ответ. - person dc37; 30.03.2020

dd <- structure(list(Name = c("Alabama", "Alaska", "Arizona", "Arkansas",  "California", "Colorado", "Connecticut", "Delaware", "Florida",  "Georgia", "Hawaii", "Idaho"), Y_N = c(0L, 0L, 1L, 1L, 1L, 0L,  1L, 0L, 1L, 1L, 0L, 1L), FIPS = c(1L, 2L, 4L, 5L, 6L, 8L, 9L,  10L, 12L, 13L, 15L, 16L), score1 = c(2633L, 382L, 2695L, 2039L,  27813L, 8609L, 5390L, 858L, 14172L, 9847L, 720L, 845L), score2 = c(8L,  1L, 41L, 10L, 524L, 133L, 111L, 3L, 215L, 308L, 0L, 7L)), row.names = c(NA,  -12L), class = c("data.table", "data.frame"))

## frame
boxplot(score1 ~ Y_N, dd, border = NA)

## 95% ci, medians
sp <- split(dd$score1, dd$Y_N)
sapply(seq_along(sp), function(ii) {
  x <- sp[[ii]]
  arrows(ii, quantile(x, 0.025), ii, quantile(x, 0.975), code = 3, angle = 90, length = 0.1)
  segments(ii - 0.05, median(x), ii + 0.05, col = 'red', lwd = 2)
})

points(dd$Y_N + 1, dd$score1, col = dd$Y_N + 1)

## t-test
lbl <- sprintf('p = %s', format.pval(t.test(score1 ~ Y_N, dd)$p.value, digits = 2))
mtext(lbl, at = par('usr')[2], adj = 1)

введите описание изображения здесь

person rawr    schedule 30.03.2020

Один из ваших вопросов касается того, как получить доступ к статистике t.test. Вот ответ на этот вопрос. Предположим, у вас есть данные такого типа:

set.seed(12)
YN <- sample(0:1, 100, replace = T)    
score1 <- sample(500:1500, 100, replace = T)
df <- data.frame(YN, score1)

И предположим, что вы запускаете и сохраняете t.test следующим образом:

test <- tapply(df$score1, df$YN, t.test)

Затем вы можете постепенно получить доступ к тестовой статистике, как показано здесь для уровня фактора 0:

test$`0`$p.value #   p-value
test$`0`$conf.int #  confidence interval
test$`0`$estimate #  estimate
test$`0`$statistic # statistic

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

df1 <- do.call(rbind, lapply(test, function(x) c(
  statistic = unname(x$statistic),
  ci = unname(x$conf.int),
  est = unname(x$estimate),
  pval = unname(x$p.value))))

Вывод такой:

  statistic      ci1      ci2      est         pval
0  22.31155 837.3901 1003.263 920.3265 5.484012e-27
1  22.91558 870.5426 1037.810 954.1765 3.543693e-28
person Chris Ruehlemann    schedule 30.03.2020
comment
Интересное использование tapply. Однако почему у вас два значения p? И как получить p.value разницы между двумя группами (я думаю, именно это и ищет OP)? t.test(....)$p.value не проще? - person dc37; 30.03.2020