2012-04-04 13 views
28

Próbuję wyświetlić niektóre informacje o danych poniżej wykresu utworzonego w ggplot2. Chciałbym narysować zmienną N za pomocą współrzędnej osi X wykresu, ale współrzędna Y musi wynosić 10% od dołu ekranu. W rzeczywistości pożądane współrzędne Y są już w ramce danych jako zmienna y_pos.Wyświetlanie tekstu poniżej wykresu generowanego przez ggplot2

mogę myśleć 3 podejścia z wykorzystaniem ggplot2:

1) Utwórz pusty wykres poniżej rzeczywistej działce przy użyciu tej samej skali, a następnie użyć geom_text wykreślić dane na pustej działce. This approach rodzaj prac, ale jest niezwykle skomplikowany.

2) Użyj , aby narysować dane, ale w jakiś sposób użyj współrzędnej y jako procent ekranu (10%). To wymusiłoby wyświetlenie liczb poniżej wykresu. Nie mogę znaleźć właściwej składni.

3) Użyj grid.text, aby wyświetlić tekst. Mogę łatwo ustawić go na 10% od dołu ekranu, ale nie mogę wymyślić, jak ustawić współrzędne X, aby dopasować wykres. Próbowałem użyć programu grconvert, aby uchwycić początkową pozycję X, ale nie mogłem tego również wykorzystać.

Poniżej jest podstawowym działka z danymi manekina:

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 

Zmodyfikowany gplot poniżej wyświetla liczby osobników, jednak są one wyświetlane w działce. Zmuszają one do wydłużenia skali Y. Chciałbym wyświetlić te numery PONIŻEJ działki.

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 

Inne podejście do wyświetlania liczb polega na utworzeniu fikcyjnego wykresu poniżej faktycznego wykresu. Oto kod:

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) 
enter code here 

jednak, że jest bardzo skomplikowana i trudno byłoby zmodyfikować dla różnych danych. Idealnie, chciałbym móc przekazać współrzędne Y jako procent ekranu. Z góry dziękuję!

+0

annotation_custom() i kod [stąd] (http://stackoverflow.com/questions/9690648/point-clipped-on-x-axis-in-ggplot) mogą ci pomóc. Zobacz poniżej. –

+0

Zobacz moją odpowiedź poniżej. Jest to zdecydowanie prostsze niż zaakceptowana odpowiedź. –

+0

Najnowsze wersje ggplot2 mają teraz tę funkcjonalność wbudowaną zgodnie z odpowiedzią poniżej: http://stackoverflow.com/a/36036479/170352 –

Odpowiedz

18

Podopts została zastąpiona zastąpiona przez theme; element_blank zastąpił theme_blank; i ggtitle() jest używany zamiast

Sandy- dziękuję bardzo !!!! Robi dokładnie to, co chcę. Chciałbym, abyśmy mogli kontrolować obcinanie w geom.text lub geom.annotate.

Przygotowałem następujący program, jeśli ktokolwiek jest zainteresowany.

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

+1

Bardzo ładne !! Nie zapomnij przyjąć własnej odpowiedzi. –

+0

To nie wygląda tutaj, czy kod nadal działa? – PatrickT

13

Updatedopts() został zastąpiony theme()

W poniższym kodzie, działka baza jest zasysane z szerszego marginesu w dolnej części wykresu. TextGrob jest tworzony, a następnie wstawiany do wykresu za pomocą adnotation_custom(). Z wyjątkiem tego, że tekst nie jest widoczny, ponieważ znajduje się poza panelem wydruku - dane wyjściowe są przycinane do panelu. Ale za pomocą kodu baptysty from here, wycinek może być nadpisany. Pozycja jest pod względem jednostek danych, a obie etykiety tekstowe są wyśrodkowane.

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

Lub przy grid funkcje do tworzenia i umieść etykietę.

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 Lub dodać Grob tekstu przy użyciu funkcji 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

+0

Dziękuję bardzo !!! Rozumiem, że funkcje siatki pozwalają umieszczać tekst w dowolnym miejscu na urządzeniu. Zastanawiam się tylko, czy to możliwe, aby umieścić tekst PONIŻEJ działki, ale w jakiś sposób użyć współrzędnych X z działki. tj. coś podobnego do tego, co można z funkcją tekstową w bazie R. –

+0

Dzięki! Pojawia się błąd: nie można znaleźć funkcji "ggplot_gtable" > gt $ layout $ clip [gt $ layout $ nazwa == "panel"] <- "wyłączony" –

+0

Jest to funkcja w 'ggplot2'. Jakiej wersji ggplot2 używasz? Może być konieczna aktualizacja. Najnowsza wersja to 0.9.0 –

5

Właściwie najlepszą odpowiedzią i najprostszym rozwiązaniem jest użycie pakietu cowplot.

Wersja 0.5.0 pakietu cowplot (na CRAN) obsługuje napisy ggplot2 przy użyciu funkcji add_sub.

Używaj go tak:

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.")) 
12

w aktualnej wersji (> 2.1) ma + labs(caption = "text"), który wyświetla adnotacji poniżej wykresu. To jest tematyczne (właściwości czcionki, wyrównanie do lewej/prawej strony). Zobacz przykłady: https://github.com/hadley/ggplot2/pull/1582.

Powiązane problemy