[R] [FORGED] Re: draw borders of bars inside of the rectangles in a barplot

Paul Murrell p@u| @end|ng |rom @t@t@@uck|@nd@@c@nz
Tue May 22 22:50:16 CEST 2018


Hi

In addition to Richard's suggestion to add borders to the "only filled" 
bars, you could add "mitred" corners, like this ...


par(ljoin="mitre")
barplot(x, beside=T, border=rep(c('black', 'black'),5),
         space=c(0.08,1), col=rep(c('black', 'white'),5))


It may be overkill, but if the "bleeding" below y=0 is still a bother, 
here's one way you could then clip the bar bottoms ...


par(lwd=5, ljoin="mitre")
barplot(x, beside=T, border=rep(c('black', 'black'),5),
         space=c(0.08,1), col=rep(c('black', 'white'),5))
## Convert to 'grid'
library(gridGraphics)
grid.echo()
## Which grob is the bars?
barpath <- grid.grep("rect", grep=TRUE, viewports=TRUE)
## Which viewport are the bars drawn within?
barvp <- attr(barpath, "vp")
## Get copy of the bars
bars <- grid.get(barpath)
## Remove the bars
grid.remove(barpath)
## Go to the bars viewport
downViewport(barvp)
## Set up a clipping rect
grid.clip(y=unit(0, "native"),
           height=unit(11, "native"),
           just="bottom",
           name="clip")
## Draw the bars again (now clipped)
grid.draw(bars)


You could take it even further and clip each individual bar (so the 
border is only visible "inside" the bar) ...


par(lwd=5, ljoin="mitre")
barplot(x, beside=T, border=rep(c('black', 'black'),5),
         space=c(0.08,1), col=rep(c('black', 'white'),5))
library(gridGraphics)
grid.echo()
barpath <- grid.grep("rect", grep=TRUE, viewports=TRUE)
barvp <- attr(barpath, "vp")
bars <- grid.get(barpath)
grid.remove(barpath)
downViewport(barvp)
## Filled bars
for (i in 1:5) {
     odd <- i*2 - 1
     grid.rect(bars$x[odd], bars$y[1], bars$width[odd], bars$height[odd],
               just=c("left", "bottom"), gp=gpar(fill="black"))
}
## Border bars (clipped)
for (i in 1:5) {
     even <- i*2
     grid.clip(bars$x[even], bars$y[1],
               bars$width[even], bars$height[even],
               just=c("left", "bottom"))
     grid.rect(bars$x[even], bars$y[2],
               bars$width[even], bars$height[even],
               just=c("left", "bottom"), gp=gpar(lwd=5))
}


And, since you mentioned Photoshop/Inkscape, another option to draw 
borders only "inside" the bars is a "variable-width line" from the 
'vwline' package ...


par(lwd=5, ljoin="mitre")
barplot(x, beside=T, border=rep(c('black', 'black'),5),
         space=c(0.08,1), col=rep(c('black', 'white'),5))
library(gridGraphics)
grid.echo()
barpath <- grid.grep("rect", grep=TRUE, viewports=TRUE)
barvp <- attr(barpath, "vp")
bars <- grid.get(barpath)
grid.remove(barpath)
downViewport(barvp)
## Filled bars
for (i in 1:5) {
     odd <- i*2 - 1
     grid.rect(bars$x[odd], bars$y[1], bars$width[odd], bars$height[odd],
               just=c("left", "bottom"), gp=gpar(fill="black"))
}
## Draw vwline with width only "inside"
library(vwline)
for (i in 1:5) {
     even <- i*2
     left <- bars$x[even]
     right <- bars$x[even] +
         convertUnit(bars$width[even], "in",
                     "x", "dimension", "x", "location")
     bottom <- bars$y[2]
     top <- bars$y[2] +
         convertUnit(bars$height[even], "in",
                     "y", "dimension", "y", "location")
     grid.vwline(unit.c(left, left, right, right),
                 unit.c(bottom, top, top, bottom),
                 w=widthSpec(list(left=rep(0, 4),
                                  right=unit(rep(1, 4), "mm"))),
                 open=FALSE)
}


Paul

On 22/05/18 04:05, Richard M. Heiberger wrote:
> I recommend instead of no border, that you use a border with the same
> color as the fill.
> I do this in the likert functions in the HH package.
> 
> Rich
> 
> 
> On Mon, May 21, 2018 at 10:59 AM, Martin Batholdy via R-help
> <r-help using r-project.org> wrote:
>> Dear R-users,
>>
>> I want to draw a barplot with beside=TRUE.
>> One halve of the bars are drawn with a border, while the other halve are drawn without a border (i.e. filled bars vs. non-filled bars next to each other).
>>
>> Because borders are drawn around the bars, doing this leads to one halve of the bars being wider than the other halve, expanding across the 0-point of the y-axis.
>> This problem emerges especially with small figures and rather large border width.
>>
>> Now my question:
>> Is there a way to draw the border inside of the bars instead of surrounding the bars? (similar to border-drawing options in graphics software, like photoshop or inkscape).
>>
>>
>> Here some example code:
>>
>> x <- matrix(c(1:10), 2,5)
>> par(lwd = 5)
>> barplot(x, beside=T, border=rep(c(NA, 'black'),5), space=c(0.08,1), col=rep(c('black', 'white'),5))
>>
>>
>>
>> Thank you!
>> ______________________________________________
>> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.
> 
> ______________________________________________
> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
> 

-- 
Dr Paul Murrell
Department of Statistics
The University of Auckland
Private Bag 92019
Auckland
New Zealand
64 9 3737599 x85392
paul using stat.auckland.ac.nz
http://www.stat.auckland.ac.nz/~paul/




More information about the R-help mailing list