2013-07-02 13 views
5

Ich brauche schwarze und weiße Farbe für meine Boxplots in R. Ich möchte den Boxplot mit Linien und Punkten füllen. Ein Beispiel:Colorfill Boxplot in R-Kran mit Linien, Punkten oder ähnlichem

enter image description here

stelle ich mir ggplot2 das tun könnte, aber ich kann keine Möglichkeit, es zu tun.

Vielen Dank im Voraus für Ihre Hilfe!

+0

Einige googeln aufgetaucht [diese Diskussion von r-help] (http://r.789695.n4.nabble.com/How-to-fill-bar-plot-with-textile-rather-than-color- td847003.html), das klingt ziemlich schwierig. – Thomas

Antwort

4

Ich denke, es ist schwer, dies mit ggplot2 zu tun, da es keine Shading-Polygon (Gris Limitatipn) verwenden. Aber Sie können Schattierungslinie Feature im Grundplot, von Dichte und Winkel Argumente in einigen Plot-Funktionen (ploygon, barplot, ..) verwendet werden.

Das Problem, dass boxplot diese Funktion nicht verwenden. Also hack ich es, oder besser hack ich bxp intern von Boxplot verwendet. Der Hack besteht darin, der Funktion bxp zwei Argumente (Winkel und Dichte) hinzuzufügen und sie intern in den Aufruf der Funktion xypolygon hinzuzufügen (Dies geschieht in 2 Zeilen).

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

} 

Hier ein Beispiel. Es sollte beachtet werden, dass es in der alleinigen Verantwortung des Benutzers liegt, sicherzustellen, dass die Legende dem Plot entspricht . Also füge ich etwas Code hinzu, um die Legende und den Boxplot-Code neu anzuordnen.

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

Super! Funktioniert super! Vielen Dank! – user2427949

4

Ich dachte, das eine große Frage war und überlegte, ob es möglich wäre dies in der Basis R zu tun und die karierte Optik zu erhalten. Also habe ich einen Code zusammengestellt, der sich auf boxplot.stats und polygon stützt (die schräge Linien zeichnen kann). Hier ist die Lösung, die wirklich nicht zur Primetime bereit ist, aber eine Lösung ist, mit der man basteln könnte, um sie allgemeiner zu machen.

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, ...) 
} 

Einige Beispiele in Aktion:

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

EDIT: Ich wollte, dass man hinzufügen könnte auch Punkte als Füllung erhalten, indem man im Grunde ein Muster aus Punkten zeichnet, dann sie ein „Donut“ -förmigen Polygon bedeckt, etwa so:

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

Aber Mischen dass mit schrägen Linien in einer einzigen Plot-Funktion ein bisschen schwierig sein würde, und ist in der Regel ein bisschen mehr challeng ing, aber es fängt an, dich dorthin zu bringen.