Аннотирование текста на отдельной грани в ggplot2

Я хочу комментировать текст на последней грани графика следующим кодом:

library(ggplot2)
p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p <- p + facet_grid(. ~ cyl)
p <- p + annotate("text", label = "Test", size = 4, x = 15, y = 5)
print(p)

enter image description here

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

Ответ 1

Обычно вы делаете что-то вроде этого:

ann_text <- data.frame(mpg = 15,wt = 5,lab = "Text",
                       cyl = factor(8,levels = c("4","6","8")))
p + geom_text(data = ann_text,label = "Text")

Он должен работать без полного указания фактор-переменной, но, вероятно, будет вызывать некоторые предупреждения:

enter image description here

Ответ 2

Вот сюжет без текстовых аннотаций:

library(ggplot2)

p <- ggplot(mtcars, aes(mpg, wt)) +
  geom_point() +
  facet_grid(. ~ cyl) +
  theme(panel.spacing = unit(1, "lines"))
p

plot without text annotations

Давайте создадим дополнительный фрейм данных для хранения текстовых аннотаций:

dat_text <- data.frame(
  label = c("4 cylinders", "6 cylinders", "8 cylinders"),
  cyl   = c(4, 6, 8)
)
p + geom_text(
  data    = dat_text,
  mapping = aes(x = -Inf, y = -Inf, label = label),
  hjust   = -0.1,
  vjust   = -1
)

plot with text annotations at edges

Кроме того, мы можем вручную указать положение каждой метки:

dat_text <- data.frame(
  label = c("4 cylinders", "6 cylinders", "8 cylinders"),
  cyl   = c(4, 6, 8),
  x     = c(20, 27.5, 25),
  y     = c(4, 4, 4.5)
)

p + geom_text(
  data    = dat_text,
  mapping = aes(x = x, y = y, label = label)
)

plot with manually positioned text labels

Мы также можем маркировать участки по двум аспектам:

dat_text <- data.frame(
  cyl   = c(4, 6, 8, 4, 6, 8),
  am    = c(0, 0, 0, 1, 1, 1)
)
dat_text$label <- sprintf(
  "%s, %s cylinders",
  ifelse(dat_text$am == 0, "automatic", "manual"),
  dat_text$cyl
)
p +
  facet_grid(am ~ cyl) +
  geom_text(
    size    = 5,
    data    = dat_text,
    mapping = aes(x = Inf, y = Inf, label = label),
    hjust   = 1.05,
    vjust   = 1.5
  )

facet by two variables

Заметки:

  • Вы можете использовать -Inf и Inf для позиционирования текста по краям панели.
  • Вы можете использовать hjust и vjust для настройки выравнивания текста.
  • Во фрейме данных текстовой метки dat_text должен быть столбец, который работает с вашим facet_grid() или facet_wrap().

Ответ 3

Если кто-то ищет простой способ пометить фасеты для отчетов или публикаций, пакет egg (CRAN) имеет довольно изящный tag_facet() & tag_facet_outside() функции.

library(ggplot2)

p <- ggplot(mtcars, aes(qsec, mpg)) + 
  geom_point() + 
  facet_grid(. ~ am) +
  theme_bw(base_size = 12)

# install.packages('egg', dependencies = TRUE)
library(egg)

Отметить внутри

# Default
tag_facet(p)

Примечание. Если вы хотите сохранить текст и фон полосы, попробуйте добавить strip.text и strip.background обратно в theme.

# align top right & use Roman numerals
tag_facet(p, x = Inf, y = Inf, 
          hjust = 1.5,
          tag_pool = as.roman(1:nlevels(factor(mtcars$am))))

# Align bottom left & use capital letters
tag_facet(p, 
          x = -Inf, y = -Inf, 
          vjust = -1,
          open = "", close = ")",
          tag_pool = LETTERS)

# Define your own tags
my_tag <- c("i) 4 cylinders", "ii) 6 cyls")
tag_facet(p, 
          x = -Inf, y = -Inf, 
          vjust = -1, hjust = -0.25,
          open = "", close = "",
          fontface = 4,
          size = 5,
          family = "serif",
          tag_pool = my_tag)

Отметить снаружи

p2 <- ggplot(mtcars, aes(qsec, mpg)) + 
  geom_point() + 
  facet_grid(cyl ~ am, switch = 'y') +
  theme_bw(base_size = 12) +
  theme(strip.placement = 'outside')

tag_facet_outside(p2)

Отредактируйте: добавьте другую альтернативу с помощью пакета stickylabeller package

- '.n' numbers the facets numerically: '"1"', '"2"', '"3"'...
- '.l' numbers the facets using lowercase letters: '"a"', '"b"', '"c"'...
- '.L' numbers the facets using uppercase letters: '"A"', '"B"', '"C"'...
- '.r' numbers the facets using lowercase Roman numerals: '"i"', '"ii"', '"iii"'...
- '.R' numbers the facets using uppercase Roman numerals: '"I"', '"II"', '"III"'...

# devtools::install_github("rensa/stickylabeller")
library(stickylabeller)

ggplot(mtcars, aes(qsec, mpg)) + 
  geom_point() + 
  facet_wrap(. ~ am, 
             labeller = label_glue('({.l}) am = {am}')) +
  theme_bw(base_size = 12)

Created by the reprex package (v0.2.1)

Ответ 4

Я думаю, что для ответа выше lab = "Текст" бесполезен, код ниже также в порядке.

ann_text <- data.frame(mpg = 15,wt = 5,
                       cyl = factor(8,levels = c("4","6","8")))
p + geom_text(data = ann_text,label = "Text" )

Однако, если вы хотите по-разному пометить разные подграфы, это будет нормально:

ann_text <- data.frame(mpg = c(14,15),wt = c(4,5),lab=c("text1","text2"),
                       cyl = factor(c(6,8),levels = c("4","6","8")))
p + geom_text(data = ann_text,aes(label =lab) )

Ответ 5

Немного расшифровав Джоран, отличный ответ прояснит, как работает метка данных.

Вы можете думать о "mpg" и "wt" как о координатах x и y соответственно (я считаю, что легче отслеживать исходные имена переменных, чем переименовывать их, как в Kamil - также отличный ответ). Для каждой метки требуется одна строка, а в столбце "цил" указано, с каким аспектом связана каждая строка.

ann_text<-data.frame(mpg=c(25,15),wt=c(3,5),cyl=c(6,8),label=c("Label 1","Label 2"))

ann_text
>  mpg wt cyl  label
>  25  3   6   Label 1
>  15  5   8   Label 2

p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()
p <- p + facet_grid(. ~ factor(cyl))
p + geom_text(data = ann_text,label=ann_text$label)

plot with labels

Ответ 6

Я не знал о пакете с egg, поэтому вот простое ggplot2 решение ggplot2

library(tidyverse)
library(magrittr)
Data1=data.frame(A=runif(20, min = 0, max = 100), B=runif(20, min = 0, max = 250), C=runif(20, min = 0, max = 300))
Data2=data.frame(A=runif(20, min = -10, max = 50), B=runif(20, min = -5, max = 150), C=runif(20, min = 5, max = 200))
bind_cols(
Data1 %>% gather("Vars","Data_1"),
Data2 %>% gather("Vars","Data_2")
) %>% select(-Vars1) -> Data_combined
Data_combined %>%
  group_by(Vars) %>%
  summarise(r=cor(Data_1,Data_2),
            r2=r^2,
            p=(pt(abs(r),nrow(.)-2)-pt(-abs(r),nrow(.)-2))) %>%
  mutate(rlabel=paste("r:",format(r,digits=3)),
         plabel=paste("p:",format(p,digits=3))) ->
  label_df 
label_df %<>% mutate(x=60,y=190)
Data_combined %>%
  ggplot(aes(x=Data_1,y=Data_2,color=Vars)) +
  geom_point() + 
  geom_smooth(method="lm",se=FALSE) +
  geom_text(data=label_df,aes(x=x,y=y,label=rlabel),inherit.aes = FALSE) + 
  geom_text(data=label_df,aes(x=x,y=y-10,label=plabel),inherit.aes = FALSE) + 
    facet_wrap(~ Vars)