Question

Hi everybody I am working in a lattice graph and all works fine but I have some trouble with legend. I am using xyplot() and it works awesome. My dataframe is NM (I add dput() version in the final part):

        AMes     A2009     A2010   A2011   A2012   A2013   A2014
1       enero  710004.3 1458624.4 6229245 4407423 3006568 1749746
2     febrero  889398.1  942099.6 5553163 4248144 2615730 1902865
3       marzo 1114883.1 1210951.2 6372920 3537103 2833299 1605746
4       abril 1419242.1 1151423.9 6755055 3500596 3438797 2116088
5        mayo 1585857.2 1598355.1 7119008 4049074 3224926      NA
6       junio 1010455.6 1370856.8 7585412 3279869 2794030      NA
7       julio 1292333.4 1420547.4 7258676 3420974 3003458      NA
8      agosto 1032443.3 2048291.1 7250944 2602310 2486932      NA
9  septiembre 1133260.1 3043637.6 6227707 2225635 2515076      NA
10    octubre 1229593.8 3669634.1 5795989 2853467 2674568      NA
11  noviembre 1074569.6 3641665.2 4015226 2830482 1731063      NA
12  diciembre 1370905.6 6780879.4 5391953 2823591 2054560      NA

I used the next code to produce the next plot:

library(lattice)
library(latticeExtra)
parSettings <- list(layout.widths=list(left.padding=8,rigth.padding=20))
comma_formatter <- function (lim, logsc = FALSE, at = NULL, ...)  {
  ans <- yscale.components.default(lim = lim, logsc = logsc, at = at, ...)
  xxPrime <- as.numeric(ans$left$labels$labels)
  ans$left$labels$labels <- formatC(xxPrime, format = "fg", big.mark = ",")
  ans
}

D <- xyplot(A2009+A2010+A2011+A2012+A2013+A2014 ~ factor(NM$AMes,unique(NM$AMes)), NM, type = c("p","l"), yscale.components = comma_formatter,auto.key=list(space="right",lines=TRUE,points=T), par.settings = parSettings,layout=c(1,1),aspect=0.6,main = "Delta Index",lwd=2,pch=16,cex.axis=4,scales=list(x=list(rot=90,font=2,cex=0.8),y=list(font=2),tick.number=9))
D

The result is the next graph: enter image description here

I would like to get in the legend of this plot points in the middle of the lines, but not separated as yiu can see. Also I would like to get the same style that I used in the graph for lines and points in the legend. Also I don't know if it is possible to remove top x axis and right y axis or at least remove the breaks in this axis. The dput() version of my dataframe is the next:

structure(list(AMes = c("enero", "febrero", "marzo", "abril", 
"mayo", "junio", "julio", "agosto", "septiembre", "octubre", 
"noviembre", "diciembre"), A2009 = c(710004.35, 889398.08, 1114883.11, 
1419242.11, 1585857.22, 1010455.56, 1292333.35, 1032443.35, 1133260.11, 
1229593.84, 1074569.64, 1370905.58), A2010 = c(1458624.41, 942099.6, 
1210951.2, 1151423.89, 1598355.1, 1370856.78, 1420547.36, 2048291.06, 
3043637.6, 3669634.09, 3641665.16, 6780879.37), A2011 = c(6229245.09, 
5553163.01, 6372919.9, 6755054.64, 7119008.27, 7585411.87, 7258675.63, 
7250944.21, 6227706.73, 5795989.01, 4015226.43, 5391952.87), 
    A2012 = c(4407422.89, 4248144.11, 3537103.4, 3500595.75, 
    4049074.18, 3279868.96, 3420974.23, 2602310.3, 2225635.25, 
    2853467.41, 2830482.27, 2823590.65), A2013 = c(3006568.05, 
    2615730, 2833299.1, 3438797.32, 3224926.48, 2794029.57, 3003458.16, 
    2486931.57, 2515076.46, 2674568.38, 1731063.04, 2054559.54
    ), A2014 = c(1749745.71, 1902865, 1605746.41, 2116087.84, 
    NA, NA, NA, NA, NA, NA, NA, NA)), .Names = c("AMes", "A2009", 
"A2010", "A2011", "A2012", "A2013", "A2014"), row.names = c(NA, 
-12L), class = "data.frame")

Many thanks for your help.

EDIT

I don't know if it is possible to get in lattice a legend with this style, where points are inside lines in the legend:

enter image description here

Was it helpful?

Solution 3

I've been thinking about this problem for a while but i've been very busy so I didn't have much time to work on it till now. I understand better what your original question was. By default Lattice does not like to stack the points on top of the lines in the legend. That's simply not an easily accessible option. However, If you're willing do dig into grid (the package Lattice is built on) you can pretty much do anything. So i've hacked together a solution I think may work for you. This should work when

  • You only have one column of values in the legend
  • You set auto.key=(..., points=T, lines=T)

The strategy here is to supply a customized legend drawing function to the plot. I try to reuse as much of the calculations as I can from Lattice. I intercept the grid viewport and make a few changes to merge the lines and points. Here's the customized legend drawing function:

drawComboKey <- function(...) {
    key = simpleKey(...)
    key = draw.key(key, draw = FALSE)

    ngroups <- (length(key$children)-1)/3
    #remove points column
    key$framevp$layout$ncol <- 
        key$framevp$layout$ncol-3L
    key$framevp$layout$respect.mat <- 
        key$framevp$layout$respect.mat[,-(3:5)]
    key$framevp$layout$widths <- 
        key$framevp$layout$widths[-(3:5)]

    #adjust background
    key$children[[1]]$col[2] <- 
        key$children[[1]]$col[2]-3L
    key$children[[1]]$cellvp$layout.pos.col[2] <-
        key$children[[1]]$cellvp$layout.pos.col[2]-3L
    key$children[[1]]$cellvp$valid.pos.col[2] <- 
        key$children[[1]]$cellvp$valid.pos.col[2]-3L

    #combine lines/points
    mylines<-(2+ngroups*2):(1+ngroups*3)
    for(i in mylines) {
        key$children[[i]]$children <- 
            gList(key$children[[i-ngroups]]$children, key$children[[i]]$children)
        key$children[[i]]$childrenOrder <- 
            names(key$children[[i]]$children)
        key$children[[i]]$col <- key$children[[i]]$col-3L
        key$children[[i]]$cellvp$layout.pos.col <- 
            key$children[[i]]$cellvp$layout.pos.col-3L
        key$children[[i]]$cellvp$valid.pos.col <- 
            key$children[[i]]$cellvp$valid.pos.col-3L
    }

    key$childrenOrder<-names(key$children)
    key
}

To use this function, you must intercept the trellis object and set this as the drawing function for the legend. So, starting with the code from last time

library(lattice)
library(latticeExtra)
parSettings <- list(
    layout.widths=list(left.padding=8,rigth.padding=20),
    superpose.line=list(lwd=2),
    superpose.symbol=list(pch=16)
)
comma_formatter <- function (lim, logsc = FALSE, at = NULL, ...)  {
  ans <- yscale.components.default(lim = lim, logsc = logsc, at = at, ...)
  xxPrime <- as.numeric(ans$left$labels$labels)
  ans$left$labels$labels <- formatC(xxPrime, format = "fg", big.mark = ",")
  ans
}

D <- xyplot(A2009+A2010+A2011+A2012+A2013+A2014 ~ factor(NM$AMes,unique(NM$AMes)), NM, 
    type = c("p","l"), 
    yscale.components = comma_formatter,
    auto.key=list(space="right", lines=TRUE,points=TRUE), 
    par.settings = parSettings,layout=c(1,1),aspect=0.6,
    main = "Delta Index",
    cex.axis=4,
    scales=list(x=list(rot=90,font=2,cex=0.8),y=list(font=2),tick.number=9))
D$legend$right$fun = "drawComboKey"
D;

So you can see in the second to the last line I specified our new drawing function. And that's pretty much it. This function is quite fragile and basically a hack. I cannot guarantee that it will always work if Lattice decides to change how it builds legends or anything like that so use at your own risk. Nevertheless, it's a pretty good example of the kinds of things you can do with trellis objects to customize them.

And here's the result:

legend with overplotted points and lines

OTHER TIPS

To put the legend in the middle, you need to set the x= and y= elements of the auto.key list rather than using space=. The coordinates you pass are on the 0-1 scale with 0,0 being the lower left. You kind of have to try out numbers till you get it in the right place.

And if you want the legend to match the plot (which is really the point after all), you should be changing the properties in the par.settings parameter and not using lwd= and pch= directly in the call to xyplot

I believe this should do the trick

library(lattice)
library(latticeExtra)
parSettings <- list(
    layout.widths=list(left.padding=8,rigth.padding=20),
    superpose.line=list(lwd=2),
    superpose.symbol=list(pch=16)
)
comma_formatter <- function (lim, logsc = FALSE, at = NULL, ...)  {
  ans <- yscale.components.default(lim = lim, logsc = logsc, at = at, ...)
  xxPrime <- as.numeric(ans$left$labels$labels)
  ans$left$labels$labels <- formatC(xxPrime, format = "fg", big.mark = ",")
  ans
}

D <- xyplot(A2009+A2010+A2011+A2012+A2013+A2014 ~ factor(NM$AMes,unique(NM$AMes)), NM, 
    type = c("p","l"), 
    yscale.components = comma_formatter,
    auto.key=list(x=.35,y=.82, lines=TRUE,points=T), 
    par.settings = parSettings,layout=c(1,1),aspect=0.6,
    main = "Delta Index",
    cex.axis=4,
    scales=list(x=list(rot=90,font=2,cex=0.8),y=list(font=2),tick.number=9))
D;

updated plot

Alternatively you can just adjust some setting in key.

Basically by setting type="b" in the lines argument in key, you can easily add points inside the lines

# Your code from above
parSettings <- list(layout.widths=list(left.padding=8,rigth.padding=20))
comma_formatter <- function (lim, logsc = FALSE, at = NULL, ...)  {
ans <- yscale.components.default(lim = lim, logsc = logsc, at = at, ...)
xxPrime <- as.numeric(ans$left$labels$labels)
ans$left$labels$labels <- formatC(xxPrime, format = "fg", big.mark = ",")
ans
}


# create your lattice plot
xyplot(A2009+A2010+A2011+A2012+A2013+A2014 ~ factor(NM$AMes,unique(NM$AMes)), NM, 
   type = "b",par.settings = parSettings,layout=c(1,1),
   aspect=0.6,main = "Delta Index",lwd=2,
   pch=16,cex.axis=4,
   scales=list(x=list(rot=90,font=2,cex=0.8),
               y=list(font=2),tick.number=9,tck=c(1,0)),

   # add a legend using key

   key=list(space="right",
            text=list(paste("A",2009:2014,sep="")),
            lines=list(pch=19,type="b",
                       col=trellis.par.get()$superpose.symbol$col[1:6])))

I haven't tried to figure out how to only get a single point on the lines in the key instead of 3, but it does the job. The annoying part is specifying the colours manually, but I'm sure there is a way to import the number of levels for your colours directly from the trellis settings.

Hope this Helps.

Example of lattice key with superposed lines and points

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top