[R] Multiple symbols per single line in a legend
Jim Lemon
jim at bitwrit.com.au
Thu Jan 14 19:27:18 CET 2010
On 01/13/2010 01:50 AM, Primoz PETERLIN wrote:
> Hello everybody,
>
> Is it possible to coax legend() into displaying more than one simbol per
> line in legend? I have a graph like the one attached to this mail; I would
> like to reorganize the legend in such a way that the duplicate text would be
> omitted, i.e., the first line would read<square> <triangledown> "increasing
> frequency" and the second one would read<circle> <triangleup> "decreasing
> frequency". Before resorting to box() and text() I would like to check
> whether some clever method already exists that would solve my problem. :)
>
Hi Primoz,
This request has been made before on the list, so I suppose it's time to
get something together. Below is a first cut on a function to do this.
If the user sends a list as the fill= argument, each one of the legend
commands can have a few rectangles before it in different colors. The
length of the fill= argument should be the same as the length of the
legend= argument. If a list is passed as the pch= argument, the same
thing happens with points. It is probably best to pass a corresponding
list to the col= argument if the user wants different colored points.
"legendg" stands for legend(grouped).
legendg<-function(x,y=NULL,legend,fill=NULL,col=par("col"),
border="black",lty,lwd,pch=NULL,angle=45,density=NULL,
bty="o",bg=par("bg"),box.lwd=par("lwd"),box.lty=par("lty"),
box.col=par("fg"),pt.bg=NA,cex=1,pt.cex=cex,pt.lwd=lwd,
xjust=0,yjust=1,x.intersp=1,y.intersp=1,adj=c(0,0.5),
text.width=NULL,text.col=par("col"),merge=FALSE,
trace=FALSE,plot=TRUE,ncol=1,horiz=FALSE,title=NULL,
inset=0,xpd,title.col=text.col) {
if(missing(legend) && !is.null(y)) {
legend<-y
y<-NULL
}
if(is.list(x)) {
y<-x$y
x<-x$x
}
if(!missing(xpd)) {
oldxpd<-par("xpd")
par(xpd=xpd)
}
legend.info<-legend(x=x,y=y,legend=legend,col=par("bg"),lty=1,
bty=bty,bg=bg,box.lwd=box.lwd,box.lty=box.lty,
box.col=par("fg"),pt.bg=NA,cex=1,pt.cex=pt.cex,pt.lwd=pt.lwd,
xjust=xjust,yjust=yjust,x.intersp=x.intersp,y.intersp=y.intersp,
adj=adj,text.width=text.width,text.col=text.col,merge=merge,
trace=trace,plot=plot,ncol=ncol,horiz=horiz,title=title,
inset=inset,title.col=title.col)
if(!is.null(fill)) {
rectheight<-strheight("Q")
if(length(adj) > 1) yadj<-adj[2] else yadj<-0.5
for(nel in 1:length(fill)) {
nrect<-length(fill[[nel]])
rectspace<-(legend.info$text$x[nel]-legend.info$rect$left)
lefts<-cumsum(c(legend.info$rect$left+rectspace*0.1,
rep(0.8*rectspace/nrect,nrect-1)))
rights<-lefts+0.7*rectspace/nrect
bottoms<-rep(legend.info$text$y[nel]-yadj*rectheight,nrect)
rect(lefts,bottoms,rights,bottoms+rectheight,col=fill[[nel]])
}
}
if(!is.null(pch)) {
if(!is.list(col)) {
mycol<-pch
if(length(col) < length(mycol[[1]]))
col<-rep(col,length.out=length(mycol[[1]]))
for(nel in 1:length(col))
mycol[[nel]]<-rep(col,length.out=length(mycol[[nel]]))
}
else mycol<-col
for(nel in 1:length(pch)) {
midspace<-(legend.info$rect$left+legend.info$text$x[nel])/2
npch<-length(pch[[nel]])
pchwidth<-strwidth("O")
xpos<-cumsum(c(midspace-npch*0.5*pchwidth,rep(pchwidth,npch-1)))
ypos<-rep(legend.info$text$y[nel],npch)
points(xpos,ypos,pch=pch[[nel]],col=mycol[[nel]])
}
}
if(!missing(xpd)) par(xpd=oldxpd)
invisible(legend.info)
}
legendg(locator(1),c("one","two","three"),fill=list(2:3,3:5,6:7))
legendg(locator(1),c("one","two","three"),pch=list(1:2,3:5,6:7),
col=list(2:3,3:5,6:7))
Give it a whacking folks and I'll put the function into the next version
of plotrix if it survives. Also send any requests for features that I
have neglected.
Jim
More information about the R-help
mailing list