1

I am trying to replicate a lattice graph using ggplot2 for a mixed model. My ggplot graph looks very similar but I am not sure about about loess line model fitted.

My goal is to add a loess line from the mixed model using ggplot2. Below is an example of my commands :

library(nlme)
library(ggplot2)
library(lattice)
library(lme4)

data(MathAchieve)
attach(MathAchieve)
mses <- tapply(SES, School, mean) 
mses[as.character(MathAchSchool$School[1:10])] 

Bryk <- as.data.frame(MathAchieve[, c("School", "SES", "MathAch")])

names(Bryk) <- c("school", "ses", "mathach")
sample20 <- sort(sample(7185, 20)) # 20 randomly sampled students

Bryk$meanses <- mses[as.character(Bryk$school)]

Bryk$cses <- Bryk$ses - Bryk$meanses
sector <- MathAchSchool$Sector
names(sector) <- row.names(MathAchSchool)
Bryk$sector <- sector[as.character(Bryk$school)]

attach(Bryk)

cat <- sample(unique(school[sector=="Catholic"]), 20)
Cat.20 <- groupedData(mathach ~ ses | school,  data=Bryk[is.element(school, cat),])

Graph with Lattice:

Graph with Lattice

trellis.device(color=T)
xyplot(mathach ~ ses | school, data=Cat.20, main="Catholic", 
       panel=function(x, y) {
         panel.loess(x, y, span=1) 
         panel.xyplot(x, y)
         panel.lmline(x, y, lty=2)
       })

Graph with ggplot:

Graph with ggplot

ggplot(Cat.20, aes(x = ses, y =mathach )) + 
  geom_point(size=1, shape=1) + 
  stat_smooth(method="lm",se=F)+
  stat_smooth(, colour="Red",se=F)+
  facet_wrap(school~., scale = "free_y")  

Please any advice will be appreciated.

Z.Lin
  • 28,055
  • 6
  • 54
  • 94
Rodrigo
  • 121
  • 8

1 Answers1

1

Preamble

Before going into the explanation, allow me to refer you to this question: Why is it not advisable to use attach() in R, and what should I use instead?

While it's recommendable that you made your question reproducible, the code you used can do with some clean-up. For example:

  1. Don't include packages that aren't used in the code (I didn't see a need for the lme4 package);
  2. There's no need to use data(...) to load MathAchieve. See the "Good Practices" section from ?data for more details.
  3. As mentioned above, don't use attach().
  4. For complete reproducibility, use set.seed() before any random sampling.
  5. For a minimal example, don't plot 20 schools when a smaller number would do.

Since you are using one of the tidyverse packages for plotting, I recommend another from its collection for data manipulation:

library(nlme)
library(ggplot2)
library(lattice)
library(dplyr)

Bryk <- MathAchieve %>%
  select(School, SES, MathAch) %>%
  group_by(School) %>%
  mutate(meanses = mean(SES),
         cses = SES - meanses) %>%
  ungroup() %>%
  left_join(MathAchSchool %>% select(School, Sector),
            by = "School")
colnames(Bryk) <- tolower(colnames(Bryk))

set.seed(123)
cat <- sample(unique(Bryk$school[Bryk$sector == "Catholic"]), 2)
Cat.2 <- groupedData(mathach ~ ses | school,
                     data = Bryk %>% filter(school %in% cat))

Explanation

Now that that's out of the way, let's look at the relevant functions for loess:

from ?panel.loess:

panel.loess(x, y, span = 2/3, degree = 1,
            family = c("symmetric", "gaussian"),
            ... # omitted for space
            )

from ?stat_smooth:

stat_smooth(mapping = NULL, data = NULL, geom = "smooth",
  method = "auto", formula = y ~ x, span = 0.75, method.args = list(), 
  ... # omitted for space
  )

where method = "auto" defaults to loess from the stats package for <1000 observations.

from ?loess:

loess(formula, data, span = 0.75, degree = 2,
      family = c("gaussian", "symmetric"),
      ... #omitted for space
      )

In short, a loess plot's default parameters are span = 2/3, degree = 1, family = "symmetric" for the lattice package, and span = 0.75, degree = 2, family = "gaussian" for the ggplot2 package. You have to specify matching parameters if you want the resulting plots to match:

xyplot(mathach ~ ses | school, data = Cat.2, main = "Catholic", 
       panel=function(x, y) {
         panel.loess(x, y, span=1, col = "red")  # match ggplot's colours
         panel.xyplot(x, y, col = "black")       # to facilitate comparison
         panel.lmline(x, y, lty=2, col = "blue")
       })

ggplot(Cat.2, aes(x = ses, y = mathach)) + 
  geom_point(size = 2, shape = 1) +
  stat_smooth(method = "lm", se = F)+
  stat_smooth(span = 1,
              method.args = list(degree = 1, family = "symmetric"),
              colour = "red", se = F)+
  facet_wrap(school ~ .) +
  theme_classic() # less cluttered background to facilitate comparison

lattice result

ggplot2 result

Z.Lin
  • 28,055
  • 6
  • 54
  • 94