2013-04-21 98 views
8

下图显示了我用下面的代码创建的图表。我强调了缺失或重叠的标签。有没有办法告诉ggplot2不重叠标签?如何防止两个标签在条形图中重叠?

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

您可以在特定坐标处绘制文本。这不是最好的方法,但它会完成工作。 – 2013-04-21 02:47:52

+0

@Ricardo:这是一个想法,但酒吧可以是任何高度。 – Martin 2013-04-22 14:58:11

回答

10

可以使用知名population pyramid的变体。

一些样本数据(代码由Didzis Elferts的回答启发):

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) 

计算算分数,每星期,然后一类转换为负值:

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

绘制曲线。请注意,y轴标签适合在基线的任一侧显示正值。

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

情节:

plot

对于你需要动态地确定合适的y轴刻度标签生产的目的。

5

一种解决方案,以避免重叠是用来酒吧和文本躲闪位置。为避免缺失值,您可以设置ylim。这里是一个例子。

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

制造新的样本数据(由@agstudy的代码启发)。

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) 

从库plyr使用功能ddply()取得了新的数据帧text.df的标签。列count包含每个组合WeekStatus中的观察值的数目。然后添加列ypos,其中包含每周加累计数count加15。这将用于y位置。用Not-Shippedypos替换为-10。

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 

现在使用新的数据框标记geom_text()

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

基于Didzis情节,你也可以通过保持在y轴上固定的位置,并通过着色相同颜色的图例中的文本增加可读性。

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