将水平图例包裹在多行中

时间:2011-06-21 22:11:49

标签: r ggplot2 legend

假设我有以下数据:

    lab <- "A really really long string!"
    dat <- data.frame(grp = paste(1:6,lab),x=1:6,y=runif(6))

当用字符串绘制这个漫长的图例时,有时候让图例很好地适应可能是一个挑战。如果必须的话,我总是可以缩短字符串以缩短它们,但我想知道是否有可能(最有可能使用一些grid魔法)将图例“包裹”在多个行或列中。例如,假设我将图例水平放置在底部:

    ggplot(dat,aes(x=x,y=y,colour=grp)) + geom_point() + 
        opts(legend.position="bottom",legend.direction="horizontal")

是否可以将此图例显示为两行三行,而不是一行六行?

3 个答案:

答案 0 :(得分:5)

试试这个。我为很长的标题写了这个,但它适用于任何长字符串。 你仍然需要弄清楚你的实例的线长。

# splits title of plot if to long
splittitle=function(title,linelength=40)
{
    spltitle<-strsplit(title,' ')
    splt<-as.data.frame(spltitle)
    title2<-NULL
    title3<-NULL
    titlelength<-round(nchar(title)/round(nchar(title)/linelength))
    dimsplt<-dim(splt)
    n=1
    doonce2=0
    for(m in 1:round(nchar(title)/linelength)){
  doonce=0
    doonce2=0
    for(l in n:dimsplt[1]){
        if(doonce==0){title2<-title3}
        title2=paste(title2,splt[l,],sep=' ')
        if(doonce2==0){if(nchar(title2)>=(titlelength*m)){title3=paste(title2,'\n',sep='')
        n<-(l+1)
        doonce2=1}
        }
        doonce=1
    }
    }
    title2
}

lab <- "A really really long string!A really really long string!A really really long string!A really really long string!A really really long string!A really really long string!A really really long string!A really really long string!"
lab2<-splittitle(lab)
cat(lab)
cat(lab2)


library('ggplot2')

1原作

dat <- data.frame(grp = paste(1:6,lab2),x=1:6,y=runif(6))

ggplot(dat,aes(x=x,y=y,colour=grp)) + geom_point() + 
    opts(legend.position="bottom",legend.direction="horizontal")

2使用splittitle

dat <- data.frame(grp = paste(1:6,lab2),x=1:6,y=runif(6))
ggplot(dat,aes(x=x,y=y,colour=grp)) + geom_point() + 
    opts(legend.position="bottom",legend.direction="horizontal")

答案 1 :(得分:5)

要包装长字符串,请使用strwrap

lipsum <- "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ullamcorper tellus vitae libero placerat aliquet egestas tortor semper. Maecenas pellentesque euismod tristique. Donec semper interdum magna, commodo vehicula ante hendrerit vitae. Maecenas at diam sollicitudin magna mollis lobortis. In nibh elit, tincidunt eu lobortis ac, molestie a felis. Proin turpis leo, iaculis non commodo quis, venenatis at justo. Duis in magna vel erat fringilla gravida quis non nisl. Nunc lacus magna, varius eu luctus vel, luctus tristique sapien. Suspendisse mi dolor, vestibulum at facilisis elementum, lacinia vitae metus. Etiam ut nisl urna, vel tempus mi. In hac habitasse platea dictumst. Quisque pretium volutpat felis, nec tempor diam faucibus at. Praesent volutpat posuere sapien, eu vulputate risus molestie vitae. Proin iaculis quam non leo porttitor hendrerit."

strwrap(lipsum)
cat(strwrap(lipsum), sep = "\n")
# Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ullamcorper tellus
# vitae libero placerat aliquet egestas tortor semper. Maecenas pellentesque euismod
# tristique. Donec semper interdum magna, commodo vehicula ante hendrerit vitae. Maecenas
# at diam sollicitudin magna mollis lobortis. In nibh elit, tincidunt eu lobortis ac,
# molestie a felis. Proin turpis leo, iaculis non commodo quis, venenatis at justo. Duis
# in magna vel erat fringilla gravida quis non nisl. Nunc lacus magna, varius eu luctus
# vel, luctus tristique sapien. Suspendisse mi dolor, vestibulum at facilisis elementum,
# lacinia vitae metus. Etiam ut nisl urna, vel tempus mi. In hac habitasse platea
# dictumst. Quisque pretium volutpat felis, nec tempor diam faucibus at. Praesent
# volutpat posuere sapien, eu vulputate risus molestie vitae. Proin iaculis quam non leo
# porttitor hendrerit.

答案 2 :(得分:2)

前面提到的splittitle 几乎有效,但例如是

> splittitle("abc defg hi jkl m", 6)
[1] " abc defg\n hi\n jkl m"

并没有真正给你你想要的东西......

一个技巧是使用RGraphics::splitString

  

“将单个字符串拆分为多行(通过插入换行符)   以便输出适合当前视口。“

然后您只需暂时更改视口。下面的功能为我做了诀窍,但仍然只是一个快速的&amp;脏 - 解决方案。我用它来包装一个传奇标题。

library(RGraphics)
multiLines <- function(text, maxWidth=11) {
  textLen = nchar(text)
  maxHeight = ceiling(textLen/maxWidth)*1.5
  vp=viewport(width=maxWidth,height=maxHeight, default.units="char")
  pushViewport(vp) #activate the viewport
  text2 = splitString(text) #given vp, split the text
  popViewport() #get rid of it
  return(text2)
}