简体   繁体   English

将水平图例包裹在多行中

[英]Wrap horizontal legend across multiple rows

Suppose I have data like the following: 假设我有以下数据:

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

When plotting a legend with strings this long, sometimes it can be a challenge to get the legend to fit nicely. 当用字符串绘制这个漫长的传奇时,有时候让传说很合适可能是一个挑战。 If I have to I can always abbreviate the strings to shorten them, but I was wondering if it's possible (most likely using some grid magic) to 'wrap' a legend across multiple rows or columns. 如果必须的话,我总是可以缩短字符串以缩短它们,但我想知道是否有可能(最有可能使用一些grid魔法)将图例“包裹”在多个行或列中。 For instance, say I position the legend on the bottom, horizontally: 例如,假设我将图例水平放置在底部:

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

Is it possible to get this legend to display as two rows of three, rather than one row of six? 是否有可能将此图例显示为两行三行,而不是一行六行?

To wrap long strings, use strwrap . 要包装长字符串,请使用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.

Try this. 试试这个。 I wrote this for very long titles but it works for any long string. 我为很长的标题写了这个,但它适用于任何长字符串。 You still have to figure out the linelength for your instance. 你仍然需要弄清楚你的实例的线长。

# 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 original 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 using splittitle 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")

The earlier mentioned splittitle almost works, but for example 前面提到的splittitle 几乎可以工作,但是例如

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

does not really give you what you want... 并没有真正给你你想要的东西......

One trick is to use RGraphics::splitString which 一个技巧是使用RGraphics::splitString

"Splits a single string into multiple lines (by inserting line breaks) so that the output will fit within the current viewport." “将一个字符串拆分成多行(通过插入换行符),以便输出适合当前视口。”

Then you just change the viewport temporarily. 然后,您只需暂时更改视口。 The function below did the trick for me, but is still only a quick & dirty -solution. 下面的函数为我做了诀窍,但仍然只是一个快速和肮脏的解决方案。 I used it to wrap a legend title. 我用它来包装一个传奇标题。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM