[R] lattice, latticeExtra: Adding moving averages to double y plot

Duncan Mackay dulcalma at bigpond.com
Fri Aug 1 04:03:07 CEST 2014


Hi Anna

I have gone back to doubleYScale because I started following the wrong
section that I had before so it was quicker to do doubleYScale
You need to have 2 lattice objects and components are taken from each  below
so use the function str on the three objects to see

library(lattice)
library(latticeExtra)

yleft <-
 xyplot(Value ~ Year, mydata, groups = Type,
        allow.multiple = T,
        distribute.type = TRUE,
        par.settings = list(layout.heights = list(key.top = 1.5)),
        key = list(text = list(label = c("stuff1","stuff2","stuff3")),
                   lines = list(col = 1:3),
                   cex   = 0.8,
                   title = "stuff type",
                   cex.title = 0.9,
                   space = "bottom"),
        col = c(1:3) # for points
         )

 yright <-
 xyplot(mavg ~ Year, mydata, groups = Type,
        allow.multiple = T,
        distribute.type = TRUE,
        type = "l",
        ylab = "mean",
        par.settings = list(layout.heights = list(key.top = 1.5)),  #
separate key from bottom a bit more
        col = c(1:3) )

# colours both y axes so change with next command
yboth <-
doubleYScale(yleft, yright, add.ylab2 = TRUE)
yboth

# change y axes col to suit
update(trellis.last.object(),             # left   # right
       par.settings = simpleTheme(col = c("black", "cyan")))

Duncan


-----Original Message-----
From: Anna Zakrisson Braeunlich [mailto:anna.zakrisson at su.se] 
Sent: Friday, 1 August 2014 03:11
To: Duncan Mackay
Subject: RE: [R] lattice, latticeExtra: Adding moving averages to double y
plot

Hi Duncan,

Now I have found a solution to my problem. It is complete except for one
tiny detail: I am unable to define different line types for stuff2 and
stuff3 moving averages (see plot2_3).

mydata<- data.frame(
  Year = 1980:2009,
  Type = factor(rep(c("stuff1", "stuff2", "stuff3"), each = 10*3)),
  Value = rnorm(90, mean = seq(90),
                sd = rep(c(6, 7, 3), each = 10)))

library(lattice)
library(latticeExtra)

stuff1data <- mydata[(mydata$Type) %in% c("stuff1"), ]
stuff2_3data <- mydata[(mydata$Type) %in% c("stuff2", "stuff3"), ]


# make moving averages function using zoo and rollmean:
library(zoo)
library(plyr)

f <- function(d)
{
  require(zoo)
  data.frame(Year = d$Year[5:length(d$Year)],
             mavg = rollmean(d$Value, 5))
}

# Apply the function to each group as well as both data frames:
madfStuff1 <- ddply(stuff1data, "Type", f)
madfStuff2_3 <- ddply(stuff2_3data, "Type", f)

# combine averages into mydata
mydata$mavg <-
  c(rep(NA,4), madfStuff1[,3], # what is rep(NA,4) doing?
    rep(NA,4), subset(madfStuff2_3, Type== "stuff2",3, drop = T), # is "3"
referring to the number of factors?
    rep(NA,4), subset(madfStuff2_3, Type== "stuff3",3, drop = T))

table(mydata$Type)

# split stuff1 from stuff2/3
datamystuff1 <- mydata[(mydata$Type) %in% c("stuff1"), ]
datamystuff23 <- mydata[(mydata$Type) %in% c("stuff2", "stuff3"), ]

table(datamystuff23$Type)
xyplot(Value ~ Year, datamystuff23, groups=Type)
xyplot(mavg ~ Year, datamystuff23, groups=Type)

# plot stuff2/3:
plot2_3 <- xyplot(Value ~ Year, datamystuff23, groups = Type,
                  allow.multiple = T,
                  distribute.type = TRUE,
                  par.settings = list(layout.heights = list(key.top = 1.5)),
                  col = "black", pch=c(2:3),
                  ylab="concentration",
                  subscripts = TRUE,
                  panel = panel.superpose,
                  panel.groups = function(x, y, subscripts,
...,group.number) {
                    panel.xyplot(x, y, ...)
                    panel.xyplot(x, datamystuff23[subscripts,"mavg"], col =
                                   "black", type = "l", lty=c(1:2))  ### Why
can I not define different lty?
                  })
plot2_3 # plot is incorrect!

plot1<- xyplot(Value ~ Year, datamystuff1, groups = Type,
               allow.multiple = T,
               distribute.type = TRUE,
               par.settings = list(layout.heights = list(key.top = 1.5)),
               col = "black", pch=c(2:3),
               subscripts = TRUE,
               ylab="temperature",
               panel = panel.superpose,
               panel.groups = function(x, y, subscripts, ...,group.number) {
                 panel.xyplot(x, y, ...)
                 panel.xyplot(x, mydata[subscripts,"mavg"], col =
                                c(1:3)[group.number], type = "l", lty=3)
               })
plot1 # this plot looks correct!


doubleYScale(plot2_3, plot1, style1 = 0, style2=0, add.ylab2 = TRUE,
             text = c("nitrogen", "winter temperature", "summer
tempareture"), lty=c(1:3),columns = 2, 
             col=c("black", "black", "black"))
             
update(trellis.last.object(),
                    par.settings = simpleTheme(col = c("black", "black"),
lty=c(1:3), 
                                               pch=c(1:3)))




Anna Zakrisson Braeunlich
PhD student

Department of Ecology, Environment and Plant Sciences
Stockholm University
Svante Arrheniusv. 21A
SE-106 91 Stockholm
Sweden/Sverige

Lives in Berlin.
For paper mail:
Katzbachstr. 21
D-10965, Berlin
Germany/Deutschland

E-mail: anna.zakrisson at su.se
Tel work: +49-(0)3091541281
Mobile: +49-(0)15777374888
LinkedIn: http://se.linkedin.com/pub/anna-zakrisson-braeunlich/33/5a2/51b

><((((º>`•. . • `•. .• `•. . ><((((º>`•. . • `•. .• `•. .><((((º>`•. . • `•.
.• `•. .><((((º>

________________________________________
From: Duncan Mackay [dulcalma at bigpond.com]
Sent: 31 July 2014 06:17
To: R; Anna Zakrisson Braeunlich
Subject: RE: [R] lattice, latticeExtra: Adding moving averages to double y
plot

Hi Anna

I am still unsure what you want

1 do you want 1 panel or 3?
2 do you want 1 y axis on the left and 1 on the right
or 1 y axis on the left and 2 on the right
                                         or 1 on the right varying with
groups in a multipanel plot

For starters try

xyplot(Value ~ Year, mydata, groups = Type,
        allow.multiple = T,
        distribute.type = TRUE,
        par.settings = list(layout.heights = list(key.top = 1.5)),  #
separate key from bottom a bit more
        col = c("black","black","black"), # for points
        key = list(text = list(label = c("stuff1","stuff2","stuff3")),
                   lines = list(col = 1:3),
                   cex   = 0.8,
                   title = "stuff type",
                   cex.title = 0.9,
                   space = "bottom"),
        subscripts = TRUE,
        panel = panel.superpose,
        panel.groups = function(x, y, subscripts, ...,group.number) {
          panel.xyplot(x, y, ...)
          panel.xyplot(x, mydata[subscripts,"mavg"], col =
c(1:3)[group.number], type = "l")
 })

OR

  xyplot(Value ~ Year|Type, mydata,
        allow.multiple = T,
        aspect = 0.75,
        layout = c(1,3),
        groups = Type,
        distribute.type = TRUE,
        par.settings = list(layout.heights = list(key.top = 1.5)),  #
separate key from bottom a bit more
        scales = list(alternating = F),
        col = c("black","black","black"),
        subscripts = TRUE,
        key = list(text = list(label = c("stuff1","stuff2","stuff3")),
                   lines = list(col = 1:3),
                   cex   = 0.8,
                   title = "stuff type",
                   cex.title = 0.9,
                   space = "bottom"),
        panel = panel.superpose,
        panel.groups = function(x, y, subscripts, ...,group.number) {
          panel.xyplot(x, y, ...)
          panel.xyplot(x, mydata[subscripts,"mavg"], col =
c(1:3)[group.number], type = "l")
 })

have a look at

 ?lattice::axis.default
for yscale.components

This means that you only need 1 xyplot object

if you use doubleYScale you need to xyplot objects
1 for the points and another for the averages

These are then superimposed with the doubleYScale

Also read and re read ?xyplot
names(trellis.par.get()) give you a list of the names in trellis.par.get()
and trellis.par.get() gives you all the settings used by  argument
par.settings in xyplot and those in the lattice series
par.settings may help you with themes.

http://lmdvr.r-forge.r-project.org/figures/figures.html
may be instructive

Duncan

-----Original Message-----
From: Anna Zakrisson Braeunlich [mailto:anna.zakrisson at su.se]
Sent: Wednesday, 30 July 2014 23:59
To: Duncan Mackay
Subject: RE: [R] lattice, latticeExtra: Adding moving averages to double y
plot

Hi Duncan and many thank's for your help!
I could see your first message perfectly.

You solved my problem to some extent. What my problem is, is that I need a
double y plot with two of these moving averages belonging to one axis (both
are temperature measurements, say Stuff 2 and 3, measured in degrees C) the
other one reading off the second axis (a nutrient measurement in mM (say
Stuff1)).

How can I plot Stuff2 and stuff3 moving averages in one plot and stuff1 in
another and then combine them using doubleYscale?

I also have some other annotated questions regarding linetypes. I could
change symbols using pch, but not the line type. Why? See code below:

Many many thank's once again.

mydata<- data.frame(
  Year = 1980:2009,
  Type = factor(rep(c("stuff1", "stuff2", "stuff3"), each = 10*3)),
  Value = rnorm(90, mean = seq(90),
                sd = rep(c(6, 7, 3), each = 10)))

library(lattice)
library(latticeExtra)

stuff1data <- mydata[(mydata$Type) %in% c("stuff1"), ]
stuff2_3data <- mydata[(mydata$Type) %in% c("stuff2", "stuff3"), ]


# make moving averages function using zoo and rollmean:
library(zoo)
library(plyr)

f <- function(d)
{
  require(zoo)
  data.frame(Year = d$Year[5:length(d$Year)],
             mavg = rollmean(d$Value, 5))
}

# Apply the function to each group as well as both data frames:
madfStuff1 <- ddply(stuff1data, "Type", f)
madfStuff2_3 <- ddply(stuff2_3data, "Type", f)

# Some styles:
myStripStyle <- function(which.panel, factor.levels, ...) {
  panel.rect(0, 0, 1, 1,
             col = bgColors[which.panel],
             border = 1)
  panel.text(x = 0.5, y = 0.5,
             font=2,
             lab = factor.levels[which.panel],
             col = txtColors[which.panel])
}

mydata$mavg <-
  c(rep(NA,4), madfStuff1[,3], # what is rep(NA,4) doing?
    rep(NA,4), subset(madfStuff2_3, Type== "stuff2",3, drop = T), # is "3"
referring to the number of factors?
    rep(NA,4), subset(madfStuff2_3, Type== "stuff3",3, drop = T))

xyplot(Value ~ Year, mydata, groups = Type,
       allow.multiple = T,
       distribute.type = TRUE,
       col = c("black","black","black"),
       subscripts = TRUE,
       par.settings = simpleTheme(lty=c(1:3), pch=c(1:3)), #why can I change
symbol (pch), but not line type (lty)?
       panel = panel.superpose,
       panel.groups = function(x, y, subscripts, ...,group.number) {
         panel.xyplot(x, y, ...)
         panel.xyplot(x, mydata[subscripts,"mavg"], col =
                        c("black","black","black")[group.number], type =
"l") # tried to change lty here too lty=c(1:3), but # without success
       })

# how can I add a legend specifying the linetype AS WELL AS symbol?
# I tried using:   text = c("stuff1", "stuff2", "stuff3"), columns = 2  but
could not make it work.




Anna Zakrisson Braeunlich
PhD student

Department of Ecology, Environment and Plant Sciences
Stockholm University
Svante Arrheniusv. 21A
SE-106 91 Stockholm
Sweden/Sverige

Lives in Berlin.
For paper mail:
Katzbachstr. 21
D-10965, Berlin
Germany/Deutschland

E-mail: anna.zakrisson at su.se
Tel work: +49-(0)3091541281
Mobile: +49-(0)15777374888
LinkedIn: http://se.linkedin.com/pub/anna-zakrisson-braeunlich/33/5a2/51b

><((((º>`•. . • `•. .• `•. . ><((((º>`•. . • `•. .• `•. .><((((º>`•. . • `•.
.• `•. .><((((º>

________________________________________
From: Duncan Mackay [dulcalma at bigpond.com]
Sent: 29 July 2014 01:45
To: R; Anna Zakrisson Braeunlich
Subject: RE: [R] lattice, latticeExtra: Adding moving averages to double y
plot

I do not know what happened to my last email as this are set up as plain
text so I am sending the code again so I hope this works

I am not sure what you wanted exactly but this will plot the points and
lines of the average.

I have not worried about the 2nd axis

Here is one way of doing things  by combining the averages into the
dataframe.
It makes it easier that way as you do not have to match up the x values

# combine averages into mydata
 mydata$mavg <-
 c(rep(NA,4), madfStuff1[,3],
   rep(NA,4), subset(madfStuff2_3, Type== "stuff2",3, drop = T),
   rep(NA,4), subset(madfStuff2_3, Type== "stuff3",3, drop = T))

 xyplot(Value ~ Year, mydata, groups = Type,
        allow.multiple = T,
        distribute.type = TRUE,
        col = c("red","blue","cyan"),
         subscripts = TRUE,
        panel = panel.superpose,
        panel.groups = function(x, y, subscripts, ...,group.number) {
                  panel.xyplot(x, y, ...)
                   panel.xyplot(x, mydata[subscripts,"mavg"], col =
c("red","blue","cyan")[group.number], type = "l")
            })

Duncan

BTW libraries are case sensitive as well. Is it you editor putting capitals?

Duncan Mackay
Department of Agronomy and Soil Science
University of New England
Armidale NSW 2351
Email: home: mackay at northnet.com.au

-----Original Message-----
From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] On
Behalf Of Anna Zakrisson Braeunlich
Sent: Monday, 28 July 2014 16:38
To: r-help at r-project.org
Subject: [R] lattice, latticeExtra: Adding moving averages to double y plot

Hi lattice users,

I would like to add 5-year moving averages to my double y-plot. I have three
factors needs to be plotted with moving averages in the same plot. One of
these reads off y-axis 1 and two from y-axis 2. I have tried to use the
rollmean function from the zoo-packages, but I fail in insering this into
lattice (I am not an experienced lattice user). I want to keep the data
points in the plot.
Find below dummy data and the script as well as annotations further
describing my question.

thank you in advance!
Anna Zakrisson

mydata<- data.frame(
  Year = 1980:2009,
  Type = factor(rep(c("stuff1", "stuff2", "stuff3"), each = 10*3)),
  Value = rnorm(90, mean = seq(90),
                sd = rep(c(6, 7, 3), each = 10)))

library(Lattice)
library(LatticeExtra)

stuff1data <- mydata[(mydata$Type) %in% c("stuff1"), ]
stuff12_3data <- mydata[(mydata$Type) %in% c("stuff2", "stuff3"), ]


# make moving averages function using zoo and rollmean:
library(zoo)
library(plyr)

f <- function(d)
{
  require(zoo)
  data.frame(Year = d$Year[5:length(d$Year)],
             mavg = rollmean(d$Value, 5))
}

# Apply the function to each group as well as both data frames:
madfStuff1 <- ddply(stuff1data, "Type", f)
madfStuff2_3 <- ddply(stuff12_3data, "Type", f)

# Some styles:
myStripStyle <- function(which.panel, factor.levels, ...) {
  panel.rect(0, 0, 1, 1,
             col = bgColors[which.panel],
             border = 1)
  panel.text(x = 0.5, y = 0.5,
             font=2,
             lab = factor.levels[which.panel],
             col = txtColors[which.panel])
}


myplot1 <- xyplot(Value ~ Year, data = stuff1data, col="black",
                   lty=1, pch=1,
                   ylab = "sweets", strip.left = F,
                   strip=myStripStyle,
                   xlab = ("Year"),
                  panel = function(x,y,...,subscripts){
                    panel.xyplot(x, y, pch = 1,col = "black")
                    panel.lmline(x,y,col = "black", data=madfStuff1) # here
I presume that panel.lmline is wrong.
                    # I would like to have my 5 year moving average here,
not a straight line.
                  })
myplot1


myplot2 <- xyplot(Value ~ Year, data = stuff12_3data, col="black",
                  lty=1, pch=1,
                  ylab = "hours", strip.left = F,
                  strip=myStripStyle,
                  xlab = ("Year"),
                  panel = function(x,y,...,subscripts){
                    panel.xyplot(x, y, pch = c(2:3),col = "black") ## what
is this "pch" defining? Types?
                    #I would like to have different symbols and line types
for stuff2 and stuff3
                    panel.lmline(x,y,col = "black", data=madfStuff2_3) #
wrong! Need my moving averages here!
                  })
myplot2

doubleYScale(myplot1, myplot2, style1 = 0, style2=0, add.ylab2 = TRUE,
             text = c("stuff1", "stuff2", "stuff3"), columns = 2,
col="black")

# problem here is that I end up with two lines. I need a double y-plot with
one moving average plots that are read off y-axis 1
# and two that reads off y-axis 2. I need to keep the data points in the
plot.

update(trellis.last.object(),
       par.settings = simpleTheme(col = c("black", "black"), lty=c(1:3),
pch=c(1:3))) # how come that I only get
# lines in my legend text and not the symbols too. I thought "pch" would add
symbols?!?


Anna Zakrisson Braeunlich
PhD student

Department of Ecology, Environment and Plant Sciences
Stockholm University
Svante Arrheniusv. 21A
SE-106 91 Stockholm
Sweden/Sverige

Lives in Berlin.
For paper mail:
Katzbachstr. 21
D-10965, Berlin
Germany/Deutschland

E-mail: anna.zakrisson at su.se
Tel work: +49-(0)3091541281
Mobile: +49-(0)15777374888
LinkedIn: http://se.linkedin.com/pub/anna-zakrisson-braeunlich/33/5a2/51b

><((((:>`?. . ? `?. .? `?. . ><((((:>`?. . ? `?. .? `?. .><((((:>`?. . ? `?.
.? `?. .><((((:>

        [[alternative HTML version deleted]]



More information about the R-help mailing list