33

Вопрос по ggplot2, r – Отображение текста под графиком, сгенерированным ggplot2

Я пытаюсь отобразить некоторую информацию о данных ниже графика, созданного вggplot2, Я хотел бы построить N-переменную, используя координату оси X графика, но координата Y должна составлять 10% от нижней части экрана. Фактически желаемые координаты Y уже находятся в кадре данных как переменная y_pos.

Я могу думать о 3 подходах, используяggplot2:

1) Создайте пустой график под фактическим графиком, используйте тот же масштаб, а затем используйте geom_text, чтобы нанести данные на пустой график.Этот подход вроде работает, но чрезвычайно сложно.

2) Использованиеgeom_text чтобы построить данные, но каким-то образом использовать координату Y в процентах от экрана (10%). Это заставит цифры отображаться под графиком. Я не могу понять правильный синтаксис.

3) Используйте grid.text для отображения текста. Я могу легко установить его на уровне 10% от нижней части экрана, но я не могу понять, как установить координату X в соответствии с графиком. Я пытался использовать grconvert для захвата начальной позиции X, но не смог заставить это работать.

Ниже приведен базовый график с фиктивными данными:

graphics.off()      # close graphics windows   

library(car)
library(ggplot2)  #load ggplot
library(gridExtra) #load Grid
library(RGraphics) # support of the "R graphics" book, on CRAN

#create dummy data
test= data.frame(
  Group = c("A", "B", "A","B", "A", "B"), 
  x = c(1 ,1,2,2,3,3 ),
  y = c(33,25,27,36,43,25),
  n=c(71,55,65,58,65,58),
  y_pos=c(9,6,9,6,9,6)
  )

#create ggplot
p1 <- qplot(x, y, data=test, colour=Group) +
  ylab("Mean change from baseline") + 
  geom_line()+
  scale_x_continuous("Weeks", breaks=seq(-1,3, by = 1) ) +
  opts( 
        legend.position=c(.1,0.9))

#display plot
p1

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

    p1 <- qplot(x, y, data=test, colour=Group) +
  ylab("Mean change from baseline") + 
  geom_line()+
  scale_x_continuous("Weeks", breaks=seq(-1,3, by = 1) ) +
  opts( plot.margin = unit(c(0,2,2,1), "lines"),
        legend.position=c(.1,0.9))+
  geom_text(data = test,aes(x=x,y=y_pos,label=n))

p1

Другой подход к отображению чисел заключается в создании фиктивного графика под фактическим графиком. Вот код:

graphics.off()      # close graphics windows   

library(car)
library(ggplot2)  #load ggplot
library(gridExtra) #load Grid
library(RGraphics) # support of the "R graphics" book, on CRAN

#create dummy data
test= data.frame(
  group = c("A", "B", "A","B", "A", "B"), 
  x = c(1 ,1,2,2,3,3 ),
  y = c(33,25,27,36,43,25),
  n=c(71,55,65,58,65,58),
  y_pos=c(15,6,15,6,15,6)
  )


p1 <- qplot(x, y, data=test, colour=group) +
  ylab("Mean change from baseline") + 
  opts(plot.margin = unit(c(1,2,-1,1), "lines")) +
  geom_line()+
  scale_x_continuous("Weeks", breaks=seq(-1,3, by = 1) ) +
  opts(legend.position="bottom",
       legend.title=theme_blank(),
       title.text="Line plot using GGPLOT") 
p1

p2 <- qplot(x, y, data=test, geom="blank")+
  ylab(" ")+
  opts(     plot.margin = unit(c(0,2,-2,1), "lines"),
            axis.line = theme_blank(), 
            axis.ticks = theme_segment(colour = "white"),           
            axis.text.x=theme_text(angle=-90,colour="white"),
            axis.text.y=theme_text(angle=-90,colour="white"),
            panel.background = theme_rect(fill = "transparent",colour = NA), 
            panel.grid.minor = theme_blank(),      
            panel.grid.major = theme_blank()
            )+
  geom_text(data = test,aes(x=x,y=y_pos,label=n)) 
p2

grid.arrange(p1, p2, heights = c(8.5, 1.5),             nrow=2 )

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

  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceededggplot2Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от Max C
  • Error: User Rate Limit Exceeded

    от Max C
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от Max C
  • Последние версии ggplot2 теперь имеют встроенную функциональность в соответствии с ответом ниже:stackoverflow.com/a/36036479/170352

    от Brandon Bertelsen
  • annotation_custom () и кодfrom here может помочь тебе Увидеть ниже.

    от Sandy Muspratt
  • Смотрите мой ответ ниже. Это определенно проще, чем принятый ответ.

    от Taylor C. White
  • 16

    Текущая версия (& gt; 2.1) имеет

    + labs(caption = "text"), который отображает аннотацию под графиком. Это тема (свойства шрифта, ... влево / вправо). Увидетьhttps://github.com/hadley/ggplot2/pull/1582 Например.

  • 15

    Updated opts() был заменен наtheme()

    В приведенном ниже коде нарисован базовый график с более широким полем внизу графика. TextGrob создается, а затем вставляется в график с помощью annotation_custom (). За исключением того, что текст не виден, потому что он находится за пределами панели графика - вывод обрезается до панели. Но с использованием кода баптистаотсюдаотсечение может быть отменено. Позиция указана в единицах данных, и обе текстовые метки расположены по центру.

    library(ggplot2)
    library(grid)
    
    # Base plot
    df = data.frame(x=seq(1:10), y = seq(1:10))
    p = ggplot(data = df, aes(x = x, y = y)) + geom_point() + ylim(0,10) +
        theme(plot.margin = unit(c(1,1,3,1), "cm"))
    p
    
    # Create the textGrobs
    Text1 = textGrob(paste("Largest x-value is", round(max(df$x), 2), sep = " "))
    Text2 = textGrob(paste("Mean = ", mean(df$x), sep = ""))
    
    p1 = p + annotation_custom(grob = Text1,  xmin = 4, xmax = 4, ymin = -3, ymax = -3) +
            annotation_custom(grob = Text2,  xmin = 8, xmax = 8, ymin = -3, ymax = -3)
    p1
    
    # Code to override clipping
    gt <- ggplotGrob(p1)
    gt$layout$clip[gt$layout$name=="panel"] <- "off"
    grid.draw(gt)
    

    enter image description here

    Или, используяgrid функции для создания и позиционирования метки.

    p
    grid.text((paste("Largest x-value is", max(df$x), sep = " ")),
       x = unit(.2, "npc"), y = unit(.1, "npc"), just = c("left", "bottom"), 
       gp = gpar(fontface = "bold", fontsize = 18, col = "blue"))
    

    enter image description here

    Edit Или добавьте текстовый гроб, используя функции gtable.

    library(ggplot2)
    library(grid)
    library(gtable)
    
    # Base plot
    df = data.frame(x=seq(1:10), y = seq(1:10))
    p = ggplot(data = df, aes(x = x, y = y)) + geom_point() + ylim(0,10) 
    
    # Construct the text grob
    lab = textGrob((paste("Largest x-value is", max(df$x), sep = " ")),
       x = unit(.1, "npc"), just = c("left"), 
       gp = gpar(fontface = "bold", fontsize = 18, col = "blue"))
    
    
    gp = ggplotGrob(p)
    
    # Add a row below the 2nd from the bottom
    gp = gtable_add_rows(gp, unit(2, "grobheight", lab), -2)
    
    # Add 'lab' grob to that row, under the plot panel
    gp = gtable_add_grob(gp, lab, t = -2, l = gp$layout[gp$layout$name == "panel",]$l)
    
    grid.newpage()
    grid.draw(gp)
    

    enter image description here

  • 20

    Edited opts устарела, замененаtheme; element_blank заменилtheme_blank; а такжеggtitle() используется вместоopts(title = ...

    Сэнди- большое спасибо !!!! Это именно то, что я хочу. Мне бы хотелось, чтобы мы могли контролировать отсечение в geom.text или geom.annotate.

    Я собрал следующую программу, если кто-то еще заинтересован.

     rm(list = ls())     # clear objects  
     graphics.off()      # close graphics windows   
    
    library(ggplot2)
    library(gridExtra)
    
    #create dummy data
    test= data.frame(
      group = c("Group 1", "Group 1", "Group 1","Group 2", "Group 2", "Group 2"), 
      x = c(1 ,2,3,1,2,3 ),
      y = c(33,25,27,36,23,25),
      n=c(71,55,65,58,65,58),
      ypos=c(18,18,18,17,17,17)
    
      )
    
    
    p1 <- qplot(x=x, y=y, data=test, colour=group) +
      ylab("Mean change from baseline") + 
      theme(plot.margin = unit(c(1,3,8,1), "lines")) +
      geom_line()+
      scale_x_continuous("Visits", breaks=seq(-1,3) ) +
      theme(legend.position="bottom",
           legend.title=element_blank())+
       ggtitle("Line plot") 
    
    
    # Create the textGrobs 
    for (ii in 1:nrow(test))
    {
      #display numbers at each visit
      p1=p1+ annotation_custom(grob = textGrob(test$n[ii]),  
                               xmin = test$x[ii], 
                               xmax = test$x[ii], 
                               ymin = test$ypos[ii], 
                               ymax = test$ypos[ii])
    
        #display group text
        if (ii %in% c(1,4)) #there is probably a better way 
          {
        p1=p1+ annotation_custom(grob = textGrob(test$group[ii]),  
                                 xmin = 0.85, 
                                 xmax = 0.85, 
                                 ymin = test$ypos[ii], 
                                 ymax = test$ypos[ii])
        }
    
      }
    
    
    
    
      # Code to override clipping
      gt <- ggplot_gtable(ggplot_build(p1))
      gt$layout$clip[gt$layout$name=="panel"] <- "off"
      grid.draw(gt)
    

    enter image description here

  • 5

    На самом деле лучший ответ и самое простое решение - использовать паке

    т cowplot.

    Версия 0.5.0 пакета cowplot (в CRAN) обрабатывает субтитры ggplot2 с помощью функции add_sub.

    Используйте это так:

      diamondsCubed <-ggplot(aes(carat, price), data = diamonds) + 
      geom_point() + 
      scale_x_continuous(trans = cuberoot_trans(), limits = c(0.2, 3),
                         breaks = c(0.2, 0.5, 1, 2, 3)) + 
      scale_y_continuous(trans = log10_trans(), limits = c(350, 15000),
                         breaks = c(350, 1000, 5000, 10000, 15000)) +
      ggtitle('Price log10 by Cube-Root of Carat') +
      theme_xkcd()
    
    
      ggdraw(add_sub(diamondsCubed, "This is an annotation.\nAnnotations can span multiple lines."))