R-cran中的彩色填充箱图,带有线条,点或类似物

时间:2013-07-02 10:22:31

标签: r colors ggplot2 boxplot

我需要在R中的箱形图中使用黑白颜色。我想用线条和点来填充箱形图。举个例子:

enter image description here

我想ggplot2可以做到这一点,但我找不到任何办法。

提前感谢您的帮助!

2 个答案:

答案 0 :(得分:5)

我认为这是一个很好的问题,并思考是否有可能在基地R中做到这一点,并获得方格的外观。所以我整理了一些依赖于boxplot.statspolygon的代码(可以绘制有角度的线条)。这是解决方案,它实际上还没有为黄金时段做好准备,但是这个解决方案可以通过修改来实现更加通用。

boxpattern <- 
function(y, xcenter, boxwidth, angle=NULL, angle.density=10, ...) {
    # draw an individual box
    bstats <- boxplot.stats(y)
    bxmin <- bstats$stats[1]
    bxq2 <- bstats$stats[2]
    bxmedian <- bstats$stats[3]
    bxq4 <- bstats$stats[4]
    bxmax <- bstats$stats[5]
    bleft <- xcenter-(boxwidth/2)
    bright <- xcenter+(boxwidth/2)
    # boxplot
    polygon(c(bleft,bright,bright,bleft,bleft),
        c(bxq2,bxq2,bxq4,bxq4,bxq2), angle=angle[1], density=angle.density)
    polygon(c(bleft,bright,bright,bleft,bleft),
        c(bxq2,bxq2,bxq4,bxq4,bxq2), angle=angle[2], density=angle.density)
    # lines
    segments(bleft,bxmedian,bright,bxmedian,lwd=3) # median
    segments(bleft,bxmin,bright,bxmin,lwd=1) # min
    segments(xcenter,bxmin,xcenter,bxq2,lwd=1)
    segments(bleft,bxmax,bright,bxmax,lwd=1) # max
    segments(xcenter,bxq4,xcenter,bxmax,lwd=1)
    # outliers
    if(length(bstats$out)>0){
        for(i in 1:length(bstats$out))
            points(xcenter,bstats$out[i])
    }
}

drawboxplots <- function(y, x, boxwidth=1, angle=NULL, ...){
    # figure out all the boxes and start the plot
    groups <- split(y,as.factor(x))
    len <- length(groups)
    bxylim <- c((min(y)-0.04*abs(min(y))),(max(y)+0.04*max(y)))
    xcenters <- seq(1,max(2,(len*(1.4))),length.out=len)
    if(is.null(angle)){
        angle <- seq(-90,75,length.out=len)
        angle <- lapply(angle,function(x) c(x,x))
    }
    else if(!length(angle)==len)
        stop("angle must be a vector or list of two-element vectors")
    else if(!is.list(angle))
        angle <- lapply(angle,function(x) c(x,x))
    # draw plot area
    plot(0, xlim=c(.97*(min(xcenters)-1), 1.04*(max(xcenters)+1)),
        ylim=bxylim, 
        xlab="", xaxt="n",
        ylab=names(y), 
        col="white", las=1)

    axis(1, at=xcenters, labels=names(groups))
    # draw boxplots
    plots <- mapply(boxpattern, y=groups, xcenter=xcenters,
        boxwidth=boxwidth, angle=angle, ...)
}

行动中的一些例子:

mydat <- data.frame(y=c(rnorm(200,1,4),rnorm(200,2,2)),
                    x=sort(rep(1:2,200)))
drawboxplots(mydat$y, mydat$x)

enter image description here

mydat <- data.frame(y=c(rnorm(200,1,4),rnorm(200,2,2),
                        rnorm(200,3,3),rnorm(400,-2,8)),
                    x=sort(rep(1:5,200)))
drawboxplots(mydat$y, mydat$x)

enter image description here

drawboxplots(mydat$y, mydat$x, boxwidth=.5, angle.density=30)

enter image description here

drawboxplots(mydat$y, mydat$x, # specify list of two-element angle parameters
             angle=list(c(0,0),c(90,90),c(45,45),c(45,-45),c(0,90)))

enter image description here

编辑:我想补充说,通过基本上绘制点图案,然后用“甜甜圈”形多边形覆盖它们,也可以获得点作为填充,如下所示:

x <- rep(1:10,10)
y <- sort(x)
plot(y~x, xlim=c(0,11), ylim=c(0,11), pch=20)
outerbox.x <- c(2.5,0.5,10.5,10.5,0.5,0.5,2.5,7.5,7.5,2.5)
outerbox.y <- c(2.5,0.5,0.5,10.5,10.5,0.5,2.5,2.5,7.5,7.5)
polygon(outerbox.x,outerbox.y, col="white", border="white") # donut
polygon(c(2.5,2.5,7.5,7.5,2.5),c(2.5,2.5,2.5,7.5,7.5)) # inner box

enter image description here

但是在一个绘图函数中将它与角度线混合起来会有点困难,而且通常会更具挑战性,但它开始让你到那里。

答案 1 :(得分:4)

我认为用ggplot2很难做到这一点,因为它不使用着色多边形(gris limitatipn)。但您可以在基本图中使用着色线要素,在某些绘图函数(ploygon,barplot,..)中使用密度 angle 参数进行参数化。

boxplot不使用此功能的问题。所以我破解它,或者更确切地说,我破解了boxplot内部使用的bxp。 hack包括向bxp函数添加2个参数(角度和密度),并在xypolygon函数的调用内部添加它们(这发生在2行中)。

my.bxp <- function (all.bxp.argument,angle,density, ...) {
    .....#### bxp code
    xypolygon(xx, yy, lty = boxlty[i], lwd = boxlwd[i], 
    border = boxcol[i],angle[i],density[i])  
    .......## bxp code after
    xypolygon(xx, yy, lty = "blank", col = boxfill[i],angle[i],density[i])      
    ......

}

这是一个例子。应该指出的是,用户完全有责任确保 传说对应于情节。所以我添加了一些代码来重新排列图例和boxplot代码。

enter image description here

require(stats)
set.seed(753)
(bx.p <- boxplot(split(rt(100, 4), gl(5, 20))))
layout(matrix(c(1,2),nrow=1),
       width=c(4,1)) 
angles=c(60,30,40,50,60)
densities=c(50,30,40,50,30)
par(mar=c(5,4,4,0)) #Get rid of the margin on the right side
my.bxp(bx.p,angle=angles,density=densities)
par(mar=c(5,0,4,2)) #No margin on the left side
plot(c(0,1),type="n", axes=F, xlab="", ylab="")
legend("top", paste("region", 1:5),
       angle=angles,density=densities)