2013-04-21 4 views
8

Das Bild unten zeigt ein Diagramm, das ich mit dem folgenden Code erstellt habe. Ich habe die fehlenden oder überlappenden Labels hervorgehoben. Gibt es eine Möglichkeit, ggplot2 zu sagen, dass es keine überlappenden Labels gibt?Wie verhindert man, dass sich zwei Etiketten in einem Balkendiagramm überlappen?

enter image description here

week = c(0, 1, 1, 1, 1, 2, 2, 3, 4, 5) 
statuses = c('Shipped', 'Shipped', 'Shipped', 'Shipped', 'Not-Shipped', 'Shipped', 'Shipped', 'Shipped', 'Not-Shipped', 'Shipped') 

dat <- data.frame(Week = week, Status = statuses) 

p <- qplot(factor(Week), data = dat, geom = "bar", fill = factor(Status)) 
p <- p + geom_bar() 
# Below is the most important line, that's the one which displays the value 
p <- p + stat_bin(aes(label = ..count..), geom = "text", vjust = -1, size = 3) 
p 
+0

können Sie Text an bestimmten Koordinaten plotten. Es ist nicht der beste Ansatz, aber es wird den Job erledigen. –

+0

@Ricardo: Das ist eine Idee, aber die Bar könnte von jeder Höhe sein. – Martin

Antwort

10

Sie können population pyramid eine Variante des bekannten verwenden.

Einige Beispieldaten (Code inspiriert von Didzis Elferts' Antwort):

set.seed(654) 
week <- sample(0:9, 3000, rep=TRUE, prob = rchisq(10, df = 3)) 
status <- factor(rbinom(3000, 1, 0.15), labels = c("Shipped", "Not-Shipped")) 
data.df <- data.frame(Week = week, Status = status) 

Compute-Scores für jede Woche zählen, dann eine Kategorie auf negative Werte konvertieren:

library("plyr") 
plot.df <- ddply(data.df, .(Week, Status), nrow) 
plot.df$V1 <- ifelse(plot.df$Status == "Shipped", 
        plot.df$V1, -plot.df$V1) 

die Handlung zeichnen. Beachten Sie, dass die Y-Achsenbeschriftungen angepasst sind, um positive Werte auf beiden Seiten der Grundlinie anzuzeigen.

library("ggplot2") 
ggplot(plot.df) + 
    aes(x = as.factor(Week), y = V1, fill = Status) + 
    geom_bar(stat = "identity", position = "identity") + 
    scale_y_continuous(breaks = 100 *  -1:5, 
        labels = 100 * c(1, 0:5)) + 
    geom_text(aes(y = sign(V1) * max(V1)/30, label = abs(V1))) 

Das Grundstück:

plot

Für die Produktion müssen Sie die entsprechenden y-Achsen-Tick-Beschriftungen dynamisch zu bestimmen.

5

Eine Lösung Überschneidungen zu vermeiden ist ausweichen Position Bars und Texte zu nutzen. Um fehlende Werte zu vermeiden, können Sie ylim einstellen. Hier ein Beispiel.

enter image description here

## I create some more realistic data similar to your picture 
week <- sample(0:5,1000,rep=TRUE) 
statuses <- gl(2,1000,labels=c('Not-Shipped', 'Shipped')) 
dat <- data.frame(Week = week, Status = statuses) 

## for dodging 
dodgewidth <- position_dodge(width=0.9) 
## get max y to set ylim 
ymax <- max(table(dat$Week,dat$Status))+20 
ggplot(dat,aes(x = factor(Week),fill = factor(Status))) + 
    geom_bar(position = dodgewidth) + 
    stat_bin(geom="text", position= dodgewidth, aes(label=..count..), 
      vjust=-1,size=5)+ 
    ylim(0,ymax) 
7

Hergestellt neue Datendatei (durch Code von @agstudy inspiriert).

week <- sample(0:5,1000,rep=TRUE,prob=c(0.2,0.05,0.15,0.5,0.03,0.1)) 
statuses <- gl(2,1000,labels=c('Not-Shipped', 'Shipped')) 
dat <- data.frame(Week = week, Status = statuses) 

Funktion Mit ddply() von Bibliothek plyr gemacht neuen Datenrahmen text.df für Etiketten. Die Spalte count enthält die Anzahl der Beobachtungen in jeder Kombination von Week und Status. Dann wird die Spalte ypos hinzugefügt, die die kumulative Summe von count für jede Woche plus 15 enthält. Dies wird für die y-Position verwendet. Für Not-Shipped mit -10 ersetzt.

library(plyr) 
text.df<-ddply(dat,.(Week,Status),function(x) data.frame(count=nrow(x))) 
text.df<-ddply(text.df,.(Week),transform,ypos=cumsum(count)+15) 
text.df$ypos[text.df$Status=="Not-Shipped"]<- -10 

Jetzt werden die Etiketten mit geom_text() unter Verwendung eines neuen Datenrahmens geplottet.

ggplot(dat,aes(as.factor(Week),fill=Status))+geom_bar()+ 
    geom_text(data=text.df,aes(x=as.factor(Week),y=ypos,label=count)) 

enter image description here

3

Basierend auf Didzis Grundstück Sie auch die Lesbarkeit, indem sie die Position auf der y-Achse konstant und durch Färben des Textes in der gleichen Farbe wie die Legende erhöhen könnten.

library(ggplot2) 
week <- sample(0:5,1000,rep=TRUE,prob=c(0.2,0.05,0.15,0.5,0.03,0.1)) 
statuses <- gl(2,1000,labels=c('Not-Shipped', 'Shipped')) 
dat <- data.frame(Week = week, Status = statuses) 


library(plyr) 
text.df<-ddply(dat,.(Week,Status),function(x) data.frame(count=nrow(x))) 
text.df$ypos[text.df$Status=="Not-Shipped"]<- -15 
text.df$ypos[text.df$Status=="Shipped"]<- -55 

p <- ggplot(dat,aes(as.factor(Week),fill=Status))+geom_bar()+ 
geom_text(data=text.df,aes(x=as.factor(Week),y=ypos,label=count),colour=ifelse(text.df$Status=="Not-Shipped","#F8766D","#00BFC4")) 

enter image description here

Verwandte Themen