r ggplot2 аннотировать диапазон точек и сегмент в одной грани

Я создаю трехгранный график с ggplot со следующими данными

library(ggplot2)

test<-as.data.frame(c(1,2,3,4,1,2,3,4,1,2,3,4))
colnames(test)<-"e12"
test$e23<-c(NaN,NaN,NaN,NaN,2,3,4,5,2,3,4,5)
test$e34<-c(NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,3,4,5,6)
test$Age<-c(1,2,3,4,1,2,3,4,1,2,3,4)
test$facet<-c(1,1,1,1,2,2,2,2,3,3,3,3)

ggplot(test, aes(x=Age)) + 
  facet_grid( ~ facet) +
  geom_line(aes(y = e12), size=0.25, colour="red", linetype="dashed") +
  geom_point(aes(y = e12), size=2.5, shape=21, fill="red", colour=NA) +
  geom_line(aes(y = e23), size=0.25, colour="blue", linetype="dashed") +
  geom_point(aes(y = e23), size=2.5, shape=21, fill="blue", colour=NA) +
  geom_line(aes(y = e34), size=0.25, colour="green", linetype="dashed") +
  geom_point(aes(y = e34), size=2.5, shape=21, fill="green", colour=NA) +
  annotate("pointrange", x=3.05, y=6.1, ymin=6.1, ymax=6.1, colour="red", size=0.5) +
  annotate("segment", x=2.8, xend=3.4, y=6.1, yend=6.1, colour="red", size=0.5, linetype="dashed") +
  annotate("text", x=3.6, y=6.1, parse=T, label="e[1%;%2]", size=3.1, family="Calibri", colour="black") +
  theme(strip.text = element_text(face="bold", size=rel(1)),
        strip.background = element_rect(fill="white", colour="white", size=1)) +
  scale_x_continuous(limits=c(0.5,4.5), breaks=seq(1, 4, 1), minor_breaks=seq(1, 4, 1), expand = c(0, 0)) + 
  scale_y_continuous(limits=c(0,6.5), breaks=seq(0, 6.5, 1), minor_breaks=seq(0,6.5,0.2), expand = c(0, 0))

Однако это создает 2 проблемы:

  1. Я хотел бы, чтобы аннотации (диапазон точек, сегмент и текст) отображались только в одном аспекте. Я видел, как создать фрейм данных для аннотирования только текста в одном аспекте, но хотел бы знать, возможно ли это для сегментов и диапазонов точек.

  2. Текст должен читаться как e1;2 с 1;2 в нижнем индексе, несмотря на то, что ставится ";" в математике вызывает ошибки.

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


person user2568648    schedule 28.04.2015    source источник
comment
На самом деле вы не используете ggplot2 так, как его следует использовать: на самом деле нет необходимости строить каждую строку отдельно, как вы это делаете. Сказав это, я не уверен, каков на самом деле ваш желаемый результат. Если сюжет, который вы найдете здесь, подойдет, буду рад сообщить вы, как я это сделал. Просто дай мне знать.   -  person Stibu    schedule 28.04.2015
comment
Спасибо, это было бы подходящим решением, хотя с легендой, перекрывающей правую грань, использование legend.position было бы предпочтительнее.   -  person user2568648    schedule 29.04.2015


Ответы (1)


Создать график точно так, как вы хотите, может быть сложно, но часто полезно не слишком возиться с деталями ggplot. Итак, я могу показать вам, как создать следующий сюжет:

То, как вы используете gpgplot, отличается от того, как оно (насколько я понимаю) предназначено для использования. Вы пишете команду для каждой линии, которую хотите построить. Но идея ggplot состоит в том, чтобы поместить все данные во фрейм данных, а затем сопоставить столбцы фрейма данных с графическими элементами. Вам могут быть полезны следующие ресурсы: страница ggplot2 и Поваренная книга для R, где вы найдете массу хороших примеров с ggplot2.

Таким образом, первым шагом является подготовка данных для построения графика. Предполагая, что test определено, как в вашем примере, следующий код будет соответствующим образом форматировать данные:

library(reshape2)
plot.test <- melt(test,id=c("Age","facet"))
plot.test <- subset(plot.test,!is.na(value))

Посмотрите plot.test и документацию melt, чтобы лучше понять этот шаг. Первая строка помещает данные в другую форму. Вместо одного столбца на кривую (e_12,e_23,e_34) у вас будет один столбец со всеми значениями и столбец, указывающий, к какой кривой относится значение. Затем вторая строка отбрасывает все неопределенные значения, которые не нужны.

Теперь, когда данные готовы, график можно построить следующим образом:

e.labs <- c(expression(e["1;2"]),expression(e["2;3"]),expression(e["3;4"]))

ggplot(plot.test,aes(x=Age,y=value,colour=variable)) +
  facet_grid(.~facet) +
  geom_line(size=0.25, linetype="dashed") + 
  geom_point(size=2.5) + 
  theme(strip.text = element_text(face="bold", size=rel(1)),
        strip.background = element_rect(fill="white", colour="white", size=1),
        legend.position=c(0.93,0.15)) +
  scale_colour_discrete(labels=e.labs)

Как видите, geom_line и geom_point нужно вызывать только один раз. Отображение данных выполняется внутри команды ggplot. В нем говорится, что переменная Age должна использоваться в качестве оси x, а переменная value (которая содержит данные из столбцов e_12 и т. д. из исходного фрейма данных) должна использоваться в качестве оси y. Столбец variable, в котором указано, поступают ли данные из столбца e_12, e_23 или e_34, используется для установки разных цветов. Поскольку эти отображения одинаковы для точек и линий, их можно определить глобально в ggplot(), а не внутри функций geom_.

Если вы используете ggplot правильно, то есть присваиваете столбцы графическим объектам, легенды создаются автоматически. Код содержит только два оператора для настройки легенды: scale_colour_discrete используется для изменения меток в легенде, legend.position внутри theme используется для перемещения легенды на графике по вашему запросу.

Если вы также хотите заменить метки оси Y и заголовок легенды на что-то значимое, вы можете использовать функцию labs. Просто добавьте следующее к вашему графику

+ labs(y="my y label",colour="my legend title")

Я не удосужился включить вашу настройку осей x и y, так как кажется, что вы уже знаете, как это сделать.

person Stibu    schedule 29.04.2015
comment
Спасибо большое-намного эффективнее! Я думаю, что понимание melt очень поможет мне, поскольку организация моих фреймов данных кажется большой частью проблемы. - person user2568648; 29.04.2015