#r #ggplot2
#r #ggplot2
Вопрос:
Я приношу извинения, если этот вопрос уже где-то задавался. Я нашел несколько сообщений на форуме, но без отличных решений для моей текущей ситуации.
У меня есть следующий составленный пример набора данных:
Subject lt;- c(1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3) Condition lt;- c("A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "C", "C", "C", "C", "C", "C") Time lt;- c(1,1,1,2,2,2,1,1,1,2,2,2,1,1,1,2,2,2) Value1 lt;- c(600,550,450,300,325,250,610,545,453,323,299,280,575,560,475,100,140,85) DF1 lt;- data.frame (Subject, Condition, Time, Value1)
Я использую ggplot для отображения этих данных в виде линейного графика с полосами ошибок. Цель этого графика-создать фигуру, готовую к академической публикации. Поэтому, в связи с тем, что у меня большие стандартные отклонения (в реальных данных они еще больше), я хотел бы показать только верхнюю полосу ошибок для условия с самой высокой строкой и нижнюю полосу ошибок для условий с более низкими строками, чтобы попытаться визуально очистить это.
В моем примере фрейма данных есть только одна Value
, однако на самом деле у меня есть 9 переменных значений для каждого Субъекта, в каждом условии, для каждого времени. В результате я хотел бы избежать (если возможно) ручного вычисления среднего и SD для каждой из этих комбинаций.
В настоящее время я использую следующий код ggplot:
PublicationPlot lt;-ggplot(DF1, aes(Time, Value1, shape = Condition)) PublicationPlot stat_summary(fun = mean, geom = "point", size= 2, aes(group = Condition)) stat_summary(fun= mean, geom = "line", aes(group = Condition, linetype = Condition)) stat_summary(fun.data = mean_cl_normal, geom = "errorbar", width = 0.075, aes(group = Condition)) xlab("Measurement Times") ylab("Value 1 (Units)") theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank(), axis.line=element_line(color = "black"), legend.key = element_rect(fill= "white"), axis.title.x = element_text(size = 15), axis.text.x = element_text(size = 13), axis.title.y = element_text(size = 15), axis.text.y = element_text(size = 13), legend.title = element_text( size=12), legend.text=element_text(size=12))
Любая помощь в решении этой проблемы была бы невероятной. Спасибо вам за ваше время и опыт. Я с нетерпением жду возможности поучиться у вас.
Комментарии:
1. если ваша цель состоит в том, чтобы визуально уменьшить беспорядок на графике, возможно, подумайте о другой визуализации-парные измерения гораздо лучше отображаются диаграммами рассеяния — измерение 1 по оси x, измерение 2 по оси y. Затем вы можете огранить или раскрасить по идентификатору. Показывая каждое значение, вы можете лучше идентифицировать выбросы, а ваши данные также лучше и правдивее представлены. Кроме того, вам больше не нужно будет визуализировать неопределенность. (ваши ошибки)
Ответ №1:
Хотя функции сводки в ggplot отлично подходят для быстрого создания часто используемых манипуляций с данными, я часто нахожу, что люди завязывают себя в узлы, пытаясь заставить встроенные функции ggplot делать то, для чего они не были предназначены. Как я часто говорю, вы должны решить, что вы хотите построить, а затем построить это.
В вашем случае это звучит так, как будто вы хотите иметь отдельный фрейм данных с сгруппированными минимумами и максимумами в момент времени 1 и 2. Поэтому вы могли бы сделать что-то вроде этого:
times lt;- lapply(split(DF1, DF1$Time), function(x) do.call(rbind, lapply(split(x$Value1, x$Condition), mean_cl_normal))) DF2 lt;- do.call(rbind, lapply(times, function(x) data.frame(ymin = min(x$ymin), ymax = max(x$ymax)))) DF2$Time lt;- 1:2
Что затем позволяет вам рисовать полосы ошибок напрямую, а не полагаться на stat_summary
:
PublicationPlot lt;-ggplot(DF1, aes(Time, Value1, shape = Condition)) PublicationPlot stat_summary(fun = mean, geom = "point", size= 2, aes(group = Condition)) stat_summary(fun= mean, geom = "line", aes(group = Condition, linetype = Condition)) geom_errorbar(data = DF2, aes(x = Time, ymin = ymin, ymax = ymax), inherit.aes = FALSE, width = 0.075) xlab("Measurement Times") ylab("Value 1 (Units)") theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank(), axis.line=element_line(color = "black"), legend.key = element_rect(fill= "white"), axis.title.x = element_text(size = 15), axis.text.x = element_text(size = 13), axis.title.y = element_text(size = 15), axis.text.y = element_text(size = 13), legend.title = element_text( size=12), legend.text=element_text(size=12))
Комментарии:
1. Я полностью согласен. Я чувствую, что часто люди странно боятся выполнять некоторые преобразования данных:)
Ответ №2:
В дополнение к решению @allan-cameron, вы также можете просто оставить всю сводку-шабанг вне вызова ggplot и просто объединить свои данные в более ранней части конвейера:
library(tidyverse) Subject lt;- c(1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3) Condition lt;- c("A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "C", "C", "C", "C", "C", "C") Time lt;- c(1,1,1,2,2,2,1,1,1,2,2,2,1,1,1,2,2,2) Value1 lt;- c(600,550,450,300,325,250,610,545,453,323,299,280,575,560,475,100,140,85) DF1 lt;- data.frame (Subject, Condition, Time, Value1) DF1 %gt;% group_by(Condition, Time) %gt;% summarise( m = mean(Value1), SD = sd(Value1), upper = m SD, lower = m - SD ) %gt;% ungroup() %gt;% group_by(Time) %gt;% mutate(upper = max(upper), lower = min(lower)) %gt;% ggplot(aes(x = Time, y = m)) geom_point(aes(shape = Condition)) geom_line(aes(lty = Condition)) geom_errorbar(aes(ymin = lower, ymax = upper), width = .075) xlab("Measurement Times") ylab("Value 1 (Units)") theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank(), axis.line=element_line(color = "black"), legend.key = element_rect(fill= "white"), axis.title.x = element_text(size = 15), axis.text.x = element_text(size = 13), axis.title.y = element_text(size = 15), axis.text.y = element_text(size = 13), legend.title = element_text( size=12), legend.text=element_text(size=12)) #gt; `summarise()` has grouped output by 'Condition'. You can override using the `.groups` argument.
Это решение основано на других пакетах tidyverse, которые заменяют пределы ваших ошибок на относительный максимум. С академической точки зрения, SD условия C во второй раз теряется таким образом, поэтому вам может потребоваться немного другое решение для этого, которое сохраняет ошибки, которые не перекрываются.
Вот решение, которое делает именно это:
DF1 lt;- data.frame (Subject, Condition, Time, Value1) DF1 %gt;% group_by(Condition, Time) %gt;% summarise( m = mean(Value1), SD = sd(Value1), upper = m SD, lower = m - SD ) %gt;% ungroup() %gt;% group_by(Time) %gt;% mutate(upper = map_dbl(upper, ~ if (any(upper gt; .) amp; !any(. gt; m amp; . lt; upper)) { . } else{ max(upper[mlt;= .]) }), lower = map_dbl(lower, ~ if (any(lower lt; .) amp; !any(. lt; m amp; . gt; lower)) { . } else{ min(lower[mgt;= .]) })) %gt;% ggplot(aes(x = Time, y = m)) geom_point(aes(shape = Condition)) geom_line(aes(lty = Condition)) geom_errorbar(aes(ymin = lower, ymax = upper), width = .075) xlab("Measurement Times") ylab("Value 1 (Units)") theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank(), axis.line=element_line(color = "black"), legend.key = element_rect(fill= "white"), axis.title.x = element_text(size = 15), axis.text.x = element_text(size = 13), axis.title.y = element_text(size = 15), axis.text.y = element_text(size = 13), legend.title = element_text( size=12), legend.text=element_text(size=12)) #gt; `summarise()` has grouped output by 'Condition'. You can override using the `.groups` argument.
По сути, вы используете верхний или нижний предел max/min, который не относится к среднему значению, которое выше/ниже предела, на который вы проводите тестирование.
Редактировать: Я только что увидел, что ваша функция сводки использует t-CI, сгенерированный функцией mean_cl_normal, вот решение, которое тоже это делает.
library(tidyverse) Subject lt;- c(1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3) Condition lt;- c("A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "C", "C", "C", "C", "C", "C") Time lt;- c(1,1,1,2,2,2,1,1,1,2,2,2,1,1,1,2,2,2) Value1 lt;- c(600,550,450,300,325,250,610,545,453,323,299,280,575,560,475,100,140,85) DF1 lt;- data.frame (Subject, Condition, Time, Value1) DF1 %gt;% group_by(Condition, Time) %gt;% summarise( m = mean(Value1), SD = sd(Value1), upper = m qt((1 .95)/2, n()-1) * SD/sqrt(n()), lower = m - qt((1 .95)/2, n()-1) * SD/sqrt(n()) ) %gt;% ungroup() %gt;% group_by(Time) %gt;% mutate(upper = map_dbl(upper, ~ if (any(upper gt; .) amp; !any(. gt; m amp; . lt; upper)) { . } else{ max(upper[mlt;= .]) }), lower = map_dbl(lower, ~ if (any(lower lt; .) amp; !any(. lt; m amp; . gt; lower)) { . } else{ min(lower[mgt;= .]) })) %gt;% ggplot(aes(x = Time, y = m)) geom_point(aes(shape = Condition)) geom_line(aes(lty = Condition)) geom_errorbar(aes(ymin = lower, ymax = upper), width = .075) xlab("Measurement Times") ylab("Value 1 (Units)") theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank(), axis.line=element_line(color = "black"), legend.key = element_rect(fill= "white"), axis.title.x = element_text(size = 15), axis.text.x = element_text(size = 13), axis.title.y = element_text(size = 15), axis.text.y = element_text(size = 13), legend.title = element_text( size=12), legend.text=element_text(size=12)) #gt; `summarise()` has grouped output by 'Condition'. You can override using the `.groups` argument.