2012-06-20 13 views
22

conjunto de datos:¿Cómo dibujo una flecha en un histograma dibujado usando ggplot2? Aquí es

set.seed(123) 
    myd <- data.frame (class = rep(1:4, each = 100), yvar = rnorm(400, 50,30)) 
    require(ggplot2) 
    m <- ggplot(myd, aes(x = yvar)) 
    p <- m + geom_histogram(colour = "grey40", fill = "grey40", binwidth = 10) + 
     facet_wrap(~class) + theme_bw() 
    p + opts(panel.margin=unit(0 ,"lines")) 

Quiero añadir etiquetas a los bares que cada otoño clase sujeto en y producir algo así como el gráfico procesado post-PowerPoint. ¿Hay forma de hacer esto dentro de R? ......

Editar: podemos pensar en diferentes puntero tales como puntos o barras de error, si la flecha no es imposible

enter image description here

Digamos que el siguiente es sujetos a ser etiquetados:

class name  yvar 
2  subject4 104.0 
3  subject3 8.5 
3  subject1 80.0 
4  subject2 40.0 
4  subject1 115.0 

classd <- data.frame (class = c(2,3,3,4,4), 
name = c ("subject4", "subject3", "subject1", "subject2", "subject1"), 
yvar = c(104.0, 8.5,80.0,40.0, 115.0)) 
+0

que sin duda puede añadir flechas como los de dentro ggplot, pero tendrás que ser más específico. ¿Puede proporcionar algunos datos de muestra sobre los temas que le permitirían determinar en qué barra caerían? – joran

+0

@joran Ok, agregué datos de muestra, gracias – jon

Respuesta

15

actualizaciónopts está en desuso; use theme en su lugar.

Extendiendo la respuesta de bdemarest un poco, creo que esto calcula las alturas de barra programáticamente. Las últimas dos columnas de arrow_pos contienen la información relevante: Freq es la altura de la barra; xval en la posición x del punto medio de la barra. Pero aún así, algunas etiquetas se superponen a las barras.

EDITAR Por defecto cut límites sus intervalos como (b1, b2], mientras que appeas que ggplot2 límites sus intervalos en geom_histogram como [b1, b2). He modificado el código para que ambos vinculen sus intervalos como [b1, b2), es decir, el modo ggplot.

library(ggplot2) 
library(grid) # unit() is in the grid package. 
library(plyr) # Data restructuring 

set.seed(123) 
myd <- data.frame (class = rep(1:4, each = 100), yvar = rnorm(400, 50, 30)) 

arrow_pos = read.table(header=TRUE, stringsAsFactors=FALSE, 
         text="class name  yvar 
          2  subject4 104.0 
          3  subject3 8.5 
          3  subject1 80.0 
          4  subject2 40.0 
          4  subject1 115.0") 

# Calculate the y positions for the labels and arrows 
# For the myd data frame, obtain counts within each bin, but separately for each class 
bwidth <- 10 # Set binwidth 
Min <- floor(min(myd$yvar)/bwidth) * bwidth 
Max <- ceiling(max(myd$yvar)/bwidth) * bwidth 

# Function to do the counting 
func <- function(df) { 
    tab = as.data.frame(table(cut(df$yvar, breaks = seq(Min, Max, bwidth), right = FALSE))) 
    tab$upper = Min + bwidth * (as.numeric(rownames(tab))) 
    return(tab) 
    } 

# Apply the function to each class in myd data frame 
TableOfCounts <- ddply(myd, .(class), function(df) func(df)) 

# Transfer counts of arrow_pos 
arrow_pos$upper <- (floor(arrow_pos$yvar/bwidth) * bwidth) + bwidth 
arrow_pos <- merge(arrow_pos, TableOfCounts, by = c("class", "upper")) 
arrow_pos$xvar <- (arrow_pos$upper - .5 * bwidth)  # x position of the arrow is at the midpoint of the bin 
arrow_pos$class=factor(as.character(arrow_pos$class), 
    levels=c("1", "2", "3", "4")) # Gets rid of warnings. 

ggplot(myd, aes(x=yvar)) + 
    theme_bw() + 
    geom_histogram(colour="grey70", fill="grey70", binwidth=bwidth) + 
    facet_wrap(~ class) + 
    theme(panel.margin=unit(0, "lines")) + 
    geom_text(data=arrow_pos, aes(label=name, x=xvar, y=Freq + 2), size=4) + 
    geom_segment(data=arrow_pos, 
        aes(x=xvar, xend=xvar, y=Freq + 1.5, yend=Freq + 0.25), 
        arrow=arrow(length=unit(2, "mm"))) 

enter image description here

17

Aquí es una solución parcial mediante geom_text() añadir etiquetas y geom_segment() con la opción de añadir arrow flechas.

El inconveniente es que tuve que elegir manualmente las posiciones y para cada flecha y etiqueta. Tal vez alguien más pueda ayudar a descubrir cómo encontrar programáticamente las alturas de barra del histograma.

set.seed(123) 
myd <- data.frame (class = rep(1:4, each = 100), yvar = rnorm(400, 50,30)) 

library(ggplot2) 
library(grid) # unit() is in the grid package. 

arrow_pos = read.table(header=TRUE, stringsAsFactors=FALSE, 
         text="class name  yvar 
          2  subject4 104.0 
          3  subject3 8.5 
          3  subject1 80.0 
          4  subject2 40.0 
          4  subject1 115.0") 

arrow_pos$y = c(3, 5, 9, 13, 1) # Manually enter y position. 
arrow_pos$class = factor(as.character(arrow_pos$class), 
    levels=c("1", "2", "3", "4")) # Gets rid of warnings. 

p1 = ggplot(myd, aes(x=yvar)) + 
    theme_bw() + 
    geom_histogram(colour="grey40", fill="grey40", binwidth=10) + 
    facet_wrap(~ class) + 
    opts(panel.margin=unit(0 ,"lines")) + 
    geom_text(data=arrow_pos, aes(label=name, x=yvar, y=y + 2), size=3) + 
    geom_segment(data=arrow_pos, 
        aes(x=yvar, xend=yvar, y=y + 1.5, yend=y + 0.25), 
        arrow=arrow(length=unit(2, "mm"))) 

png("p1.png", height=600, width=600) 
print(p1) 
dev.off() 

enter image description here

+0

gracias, me gustaría poder aceptar su respuesta ya que primero debe responder e iniciar la idea, sin embargo, para una respuesta rápida que es la respuesta perfecta (como la altura) elijo la segunda respuesta ... pero merezco el token de apreciación – jon

+2

¡Estoy feliz de poder ayudar! Estoy de acuerdo en que @Sandy Muspratt merece el crédito por la solución completa. – bdemarest

Cuestiones relacionadas