2012-06-20 3 views
22

Ecco set di dati:Come disegnare una freccia su un istogramma disegnato usando ggplot2?

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

voglio aggiungere etichette ai bar che ogni classe soggetto rientrano in e produrre qualcosa come il grafico elaborato post-powerpoint. C'è un modo per farlo in R? ......

Edit: possiamo pensare di puntatore diverso, come punto o errore di bar, se la freccia non è impossibile

enter image description here

Diciamo che segue è soggetti ad essere etichettati:

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

si può certamente aggiungere frecce come quelle da dentro ggplot, ma dovrete essere più specifico. Puoi fornire alcuni dati di esempio sui soggetti che ti permetteranno di determinare in quale barra cadranno? – joran

+0

@joran Ok ho aggiunto dati di esempio grazie – jon

risposta

15

Aggiornamentoopts è deprecato; utilizzare invece theme.

Estendendo la risposta di bdemarest un po ', penso che questo calcoli le altezze della barra in modo programmatico. Le ultime due colonne di arrow_pos contengono le informazioni pertinenti: Freq è l'altezza della barra; xval nella posizione x del punto medio della barra. Ma ancora, alcune delle etichette si sovrappongono alle barre.

EDIT Per default cut delimita suoi intervalli (b1, b2], mentre appeas che delimita ggplot2 propri intervalli in geom_histogram come [b1, b2). Ho modificato il codice in modo che entrambi legassero i loro intervalli come [b1, b2), cioè il 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

Ecco soluzione parziale utilizzando geom_text() aggiungere etichette e geom_segment() con la possibilità di aggiungere arrow frecce.

Lo svantaggio è che dovevo scegliere manualmente le posizioni y per ogni freccia e etichetta. Forse qualcun altro può aiutare a capire come trovare in modo programmatico le altezze della barra dell'istogramma.

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

grazie, vorrei poter accettare la tua risposta in quanto tu sei il primo a rispondere e iniziare l'idea, tuttavia per quidd veloce che risposta è la risposta perfetta (come l'altezza) che sto scegliendo la seconda risposta ... ma merita il token di apprezzamento – jon

+2

Sono felice di poterti aiutare! Sono d'accordo che @Sandy Muspratt merita il credito per la soluzione completa. – bdemarest