Half borders (left/bottom axes only) in ggplot2

6 517 просмотров
Перейти к первому непрочитанному сообщению

Rudolf Cardinal

не прочитано,
15 мар. 2011 г., 07:07:3015.03.2011
– ggp...@googlegroups.com
Dear all,

A quick and simple technique post, and apologies if this is obvious/already implemented somewhere else.

I was trying to have ggplot2 display only left and bottom ("L"-shaped) borders, rather than a rectangle or no border, and saw on the web that this has been a problem for others. My solution (based on the ggplot2 source code in theme-elements.r) is pasted below, and is accessible directly from R using:

   source("http://egret.psychol.cam.ac.uk/statistics/R/extensions/rnc_ggplot2_border_themes.r")

This code allows the use of one of the following ggplot2 elements:

    opts( panel.border = theme_L_border() )

    opts( panel.border = theme_left_border() )

    opts( panel.border = theme_bottom_border() )

or, to put it into a more concrete example:

    library(ggplot2)
    source("http://egret.psychol.cam.ac.uk/statistics/R/extensions/rnc_ggplot2_border_themes.r")
    df = data.frame(x=c(1,2,3),y=c(4,5,6))
    ggplot(data=df, aes(x=x, y=y)) + geom_point() + theme_bw() + opts( panel.border = theme_L_border() )
   


Note that the order can be significant; for example, if you specify the L border option and then a theme, the theme settings will override the border option, so you need to specify the theme (if any) before the border option, as above.

The code is shown below.

all the best,
Rudolf.


# Rudolf Cardinal, March 2011
# Simple extensions to ggplot2 (v0.8.7); see http://www.psychol.cam.ac.uk/statistics/R/

theme_L_border <- function(colour = "black", size = 1, linetype = 1) {
  structure(
    function(x = 0, y = 0, width = 1, height = 1, ...) {
      polylineGrob(
        x=c(x+width, x, x), y=c(y,y,y+height), ..., default.units = "npc",
        gp=gpar(lwd=size, col=colour, lty=linetype),
      )
    },
    class = "theme",
    type = "box",
    call = match.call()
  )
}

theme_bottom_border <- function(colour = "black", size = 1, linetype = 1) {
  structure(
    function(x = 0, y = 0, width = 1, height = 1, ...) {
      polylineGrob(
        x=c(x, x+width), y=c(y,y), ..., default.units = "npc",
        gp=gpar(lwd=size, col=colour, lty=linetype),
      )
    },
    class = "theme",
    type = "box",
    call = match.call()
  )
}

theme_left_border <- function(colour = "black", size = 1, linetype = 1) {
  structure(
    function(x = 0, y = 0, width = 1, height = 1, ...) {
      polylineGrob(
        x=c(x, x), y=c(y,y+height), ..., default.units = "npc",
        gp=gpar(lwd=size, col=colour, lty=linetype),
      )
    },
    class = "theme",
    type = "box",
    call = match.call()
  )
}


Brandon Hurr

не прочитано,
15 мар. 2011 г., 07:25:3115.03.2011
– Rudolf Cardinal, ggp...@googlegroups.com
Ooooooh, very nice. Thanks for sharing. 

Brandon

--
You received this message because you are subscribed to the ggplot2 mailing list.
Please provide a reproducible example: http://gist.github.com/270442
 
To post: email ggp...@googlegroups.com
To unsubscribe: email ggplot2+u...@googlegroups.com
More options: http://groups.google.com/group/ggplot2

baptiste auguie

не прочитано,
15 мар. 2011 г., 14:21:2715.03.2011
– Rudolf Cardinal, ggp...@googlegroups.com
Nice, thanks!

Just a thought, perhaps it'd be useful to generalise this to any type
of partial frame. There's a function in gridExtra that I wrote for
similar purposes; maybe the "type" could be given as a parameter.

library(gridExtra)
example(borderGrob)

Best,

baptiste

Rudolf Cardinal

не прочитано,
16 мар. 2011 г., 06:04:4916.03.2011
– baptiste auguie, ggp...@googlegroups.com
Dear Baptiste,

Good idea! I've added a theme_border(type=..., ...) function (pasted
below, and the web version of the source now has all four). The type
parameter matches your "library(gridExtra); example(borderGrob)" code.
Example use:

source("http://egret.psychol.cam.ac.uk/statistics/R/extensions/rnc_ggplot2_border_themes.r")
df = data.frame(x=c(1,2,3),y=c(4,5,6))
ggplot(data=df, aes(x=x, y=y)) + geom_point() + theme_bw() + opts(

panel.border = theme_border(type=9) )

all the best,
Rudolf.

# Rudolf Cardinal, March 2011
# Simple extensions to ggplot2 (v0.8.7); see http://www.psychol.cam.ac.uk/statistics/R/

theme_L_border<- function(colour = "black", size = 1, linetype = 1) {

# use with e.g. "ggplot(...) + opts( panel.border=theme_L_border() ) + ..."


structure(
function(x = 0, y = 0, width = 1, height = 1, ...) {
polylineGrob(
x=c(x+width, x, x), y=c(y,y,y+height), ..., default.units = "npc",
gp=gpar(lwd=size, col=colour, lty=linetype),
)
},
class = "theme",
type = "box",
call = match.call()
)
}

theme_bottom_border<- function(colour = "black", size = 1, linetype = 1) {

# use with e.g. "ggplot(...) + opts( panel.border=theme_bottom_border() ) + ..."


structure(
function(x = 0, y = 0, width = 1, height = 1, ...) {
polylineGrob(
x=c(x, x+width), y=c(y,y), ..., default.units = "npc",
gp=gpar(lwd=size, col=colour, lty=linetype),
)
},
class = "theme",
type = "box",
call = match.call()
)
}

theme_left_border<- function(colour = "black", size = 1, linetype = 1) {

# use with e.g. "ggplot(...) + opts( panel.border=theme_left_border() ) + ..."


structure(
function(x = 0, y = 0, width = 1, height = 1, ...) {
polylineGrob(
x=c(x, x), y=c(y,y+height), ..., default.units = "npc",
gp=gpar(lwd=size, col=colour, lty=linetype),
)
},
class = "theme",
type = "box",
call = match.call()
)
}

theme_border<- function(type, colour = "black", size = 1, linetype = 1) {
# use with e.g. "ggplot(...) + opts( panel.border=theme_border(type=9) ) + ..."


structure(
function(x = 0, y = 0, width = 1, height = 1, ...) {

# types from: library(gridExtra); example(borderGrob)
# 1=none, 2=bottom, 3=right, 4=top
# 5=left, 6=B+R, 7=T+R, 8=T+L
# 9=B+L, 10=T+B, 11=L+R, 12=T+B+R
# 13=T+L+R, 14=T+B+L, 15=B+L+R, 16=T+B+L+R
xlist<- c()
ylist<- c()
idlist<- c()
if (type==1) { # blank; can't pass absence of coordinates, so pass a single point and use an invisible line
xlist<- c(x,x)
ylist<- c(y,y)
idlist<- c(1,1)
linetype<- "blank"
}
if (type==2 || type==6 || type==9 || type==10 || type==12 || type==14 || type==15 || type==16) { # bottom
xlist<- append(xlist, c(x, x+width))
ylist<- append(ylist, c(y, y))
idlist<- append(idlist, c(1,1))
}
if (type==4 || type==7 || type==8 || type==10 || type==12 || type==13 || type==14 || type==16) { # top
xlist<- append(xlist, c(x, x+width))
ylist<- append(ylist, c(y+height, y+height))
idlist<- append(idlist, c(2,2))
}
if (type==5 || type==8 || type==9 || type==11 || type==13 || type==14 || type==15 || type==16) { # left
xlist<- append(xlist, c(x, x))
ylist<- append(ylist, c(y, y+height))
idlist<- append(idlist, c(3,3))
}
if (type==3 || type==6 || type==7 || type==11 || type==12 || type==13 || type==15 || type==16) { # right
xlist<- append(xlist, c(x+width, x+width))
ylist<- append(ylist, c(y, y+height))
idlist<- append(idlist, c(4,4))
}
polylineGrob(
x=xlist, y=ylist, id=idlist, ..., default.units = "npc",


gp=gpar(lwd=size, col=colour, lty=linetype),
)
},
class = "theme",
type = "box",
call = match.call()
)
}

Luciano Selzer

не прочитано,
16 мар. 2011 г., 09:41:2616.03.2011
– Rudolf Cardinal, ggp...@googlegroups.com
Hi Rudolf, it's very useful what you did. However, IMHO, the way used in  the function to set the borders is kind of hard to use and remember. Wouldn't it be better to use a character vector? Something like type = c("bottom", "top"), or type = "none". Using this approach I would use if( "b" %in% type). You could also add a match.arg call so the abbreviated names can be used.

That's my two cents.

Luciano


2011/3/16 Rudolf Cardinal <rud...@pobox.com>

Rudolf Cardinal

не прочитано,
17 мар. 2011 г., 10:04:3317.03.2011
– Luciano Selzer, ggp...@googlegroups.com
Fair enough, and thanks for the parameter syntax tips. I've renamed the numeric one as theme_border_numerictype(), since it sounds like that's the less convenient; theme_border() now takes the textual parameters you suggest (and they can be abbreviated, as you suggested). Amended code below and full version remains at the URL above. So demo usage now:

library(ggplot2)
df = data.frame( x=c(1,2,3), y=c(4,5,6) )
ggplot(data=df, aes(x=x, y=y)) + geom_point() + theme_bw() + opts( panel.border = theme_border_numerictype(9) )
ggplot(data=df, aes(x=x, y=y)) + geom_point() + theme_bw() + opts( panel.border = theme_border(c("bottom","left")) )
ggplot(data=df, aes(x=x, y=y)) + geom_point() + theme_bw() + opts( panel.border = theme_border(c("b","l")) )

all the best,
Rudolf.


theme_border_numerictype <- function(type, colour = "black", size = 1, linetype = 1) {

  # use with e.g.: ggplot(...) + opts( panel.border=theme_border(type=9) ) + ...
  structure(
    function(x = 0, y = 0, width = 1, height = 1, ...) {
      # numerical types from: library(gridExtra); example(borderGrob)
      # 1=none, 2=bottom, 3=right, 4=top, 5=left, 6=B+R, 7=T+R, 8=T+L, 9=B+L, 10=T+B, 11=L+R, 12=T+B+R, 13=T+L+R, 14=T+B+L, 15=B+L+R, 16=T+B+L+R

      xlist <- c()
      ylist <- c()
      idlist <- c()
      if (type==2 || type==6 || type==9 || type==10 || type==12 || type==14 || type==15 || type==16) { # bottom
        xlist <- append(xlist, c(x, x+width))
        ylist <- append(ylist, c(y, y))
        idlist <- append(idlist, c(1,1))
      }
      if (type==4 || type==7 || type==8 || type==10 || type==12 || type==13 || type==14 || type==16) { # top
        xlist <- append(xlist, c(x, x+width))
        ylist <- append(ylist, c(y+height, y+height))
        idlist <- append(idlist, c(2,2))
      }
      if (type==5 || type==8 || type==9 || type==11 || type==13 || type==14 || type==15 || type==16) { # left
        xlist <- append(xlist, c(x, x))
        ylist <- append(ylist, c(y, y+height))
        idlist <- append(idlist, c(3,3))
      }
      if (type==3 || type==6 || type==7 || type==11 || type==12 || type==13 || type==15 || type==16) { # right
        xlist <- append(xlist, c(x+width, x+width))
        ylist <- append(ylist, c(y, y+height))
        idlist <- append(idlist, c(4,4))
      }
      if (type==1) { # blank; can't pass absence of coordinates, so pass a single point and use an invisible line
        xlist <- c(x,x)
        ylist <- c(y,y)
        idlist <- c(5,5)
        linetype <- "blank"

      }
      polylineGrob(
        x=xlist, y=ylist, id=idlist, ..., default.units = "npc",
        gp=gpar(lwd=size, col=colour, lty=linetype),
      )
    },
    class = "theme",
    type = "box",
    call = match.call()
  )
}

theme_border <- function(type = c("left", "right", "bottom", "top", "none"), colour = "black", size = 1, linetype = 1) {
  # use with e.g.: ggplot(...) + opts( panel.border=theme_border(type=c("bottom","left")) ) + ...
  type <- match.arg(type, several.ok=TRUE)

  structure(
    function(x = 0, y = 0, width = 1, height = 1, ...) {
      xlist <- c()
      ylist <- c()
      idlist <- c()
      if ("bottom" %in% type) { # bottom

        xlist <- append(xlist, c(x, x+width))
        ylist <- append(ylist, c(y, y))
        idlist <- append(idlist, c(1,1))
      }
      if ("top" %in% type) { # top

        xlist <- append(xlist, c(x, x+width))
        ylist <- append(ylist, c(y+height, y+height))
        idlist <- append(idlist, c(2,2))
      }
      if ("left" %in% type) { # left

        xlist <- append(xlist, c(x, x))
        ylist <- append(ylist, c(y, y+height))
        idlist <- append(idlist, c(3,3))
      }
      if ("right" %in% type) { # right

        xlist <- append(xlist, c(x+width, x+width))
        ylist <- append(ylist, c(y, y+height))
        idlist <- append(idlist, c(4,4))
      }
      if (length(type)==0 || "none" %in% type) { # blank; can't pass absence of coordinates, so pass a single point and use an invisible line

        xlist <- c(x,x)
        ylist <- c(y,y)
        idlist <- c(5,5)
        linetype <- "blank"

      }
      polylineGrob(
        x=xlist, y=ylist, id=idlist, ..., default.units = "npc",
        gp=gpar(lwd=size, col=colour, lty=linetype),
      )
    },
    class = "theme",
    type = "box",
    call = match.call()
  )
}

Paul

не прочитано,
18 февр. 2013 г., 10:27:4118.02.2013
– ggp...@googlegroups.com
ggplot2 0.9.3 introduced theme_classic() which does what you want.


On Monday, 18 February 2013 13:58:29 UTC+1, 陈文峰 wrote:
There is a much better method to remove the top and right borders of ggplot2.
Ref:
I paste the script here. Everyone can try it. I like it very much!
library(ggplot2)
a <- seq(1,20)
b <- a^0.25
df <- as.data.frame(cbind(a,b)) #base ggplot object
p <- ggplot(df, aes(x = a, y = b))
p + #plots the points  
geom_point() + #theme with white background  
theme_bw() + #eliminates baground, gridlines, and chart border  
theme( plot.background = element_blank() ,
    panel.grid.major = element_blank() ,
    panel.grid.minor = element_blank() ,
    panel.border = element_blank() ,
    panel.background = element_blank() ) +
        #draws x and y axis line  
    theme(axis.line = element_line(color = 'black'))

#generates:

plot output 

Chmel87

не прочитано,
12 янв. 2016 г., 12:15:4612.01.2016
– ggplot2
Hi

Thanks a lot
This is a best solution, many other shared solutions did not work

Thanks again

Krystof

Dne úterý 15. března 2011 12:07:30 UTC+1 Rudolf Cardinal napsal(a):
Ответить всем
Отправить сообщение автору
Переслать
0 новых сообщений