3

Using lattice in R, I have plotted an xyplot using the factors option. Now I want to add a horizontal abline to every plot, however out of another dataframe. How can I get these lines in their correspondent panel?

EDIT - example:

MyData <- data.frame(
  v1 = 1:50,
  v2 = rnorm(50,20,5),
  v3 = c(rep("one", 10), rep("two", 10),  rep("three", 10), rep("four", 10), rep("five", 10)))


require(latticeExtra)

xyplot(
  v1 ~ v2 | v3,
  data = MyData,
  layout = c(5, 1),
  scales = list(
    x = list(relation="free"),
    y = list(relation="same")
  )
)

# Now the horizontal lines I want to draw
lineData <- c(30,30,20,20,40) 
# each for one column, from left to right; another option would be
lineData <- data.frame(
  v3 = c("one","two","three","four","five"),
  height = c(30,30,20,20,40)
)

# I know this will not work for each correspondent panel, separately...
abline(h = lineData)
Arne
  • 167
  • 7
  • 2
    You should provide a [reproducible example](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) with sample input data and the code you are currently using to make your plot. Make it as simple as possible to clearly show where you are getting stuck. – MrFlick Aug 11 '16 at 17:16
  • We're still missing `MyData` and some way to connect the values in `lineData` to the values of `v3` – MrFlick Aug 11 '16 at 17:29
  • I added sample data. The way to connect the `lineData` is what I am looking for. They could share the variable `v3` with `MyData` – Arne Aug 11 '16 at 17:46
  • Try adding `panel = function(...) { panel.xyplot(...) panel.abline(h=lineData[panel.number()]) }`. [from here](http://stackoverflow.com/questions/21175945/adding-different-vertical-lines-for-each-panel-in-xyplot-using-lattice-in-r) – user20650 Aug 11 '16 at 18:00

2 Answers2

2

I think you have to use a custom panel function.

library(lattice)

MyData <- data.frame(
  v1 = 1:50,
  v2 = rnorm(50,20,5),
  v3 = c(rep("one", 10), rep("two", 10),  rep("three", 10), rep("four", 10), rep("five", 10)))

lineData <- c(30,30,20,20,40) 
# define custom panel plot function
customPanel = function(x, y, lineData) {
  panel.xyplot(x, y)
  panel.abline(h = lineData[panel.number()]) # instead of using a global variable
}

xyplot(
  v1 ~ v2 | v3,
  data = MyData,
  layout = c(5, 1),
  scales = list(
    x = list(relation="free"),
    y = list(relation="same")
  ),
  panel = customPanel,
  lineData = lineData)
MrFlick
  • 195,160
  • 17
  • 277
  • 295
Vandenman
  • 3,046
  • 20
  • 33
  • 2
    rather than a global variable, you could use `lineData[panel.number()]` but then you would need to make sure the values are in the order of the levels of your conditioning factor. – MrFlick Aug 11 '16 at 18:01
  • Thanks, didn't know that. – Vandenman Aug 11 '16 at 18:08
2

Here's how i'd do it to make sure the values match up

lineData <- data.frame(
  v3 = c("one","two","three","four","five"),
  height = c(30,30,20,20,40)
)

xyplot(
  v1 ~ v2 | v3,
  data = MyData,
  layout = c(5, 1),
  scales = list(
    x = list(relation="free"),
    y = list(relation="same")
  ),
  panel = function(x, ...) {
      level <- dimnames(trellis.last.object())[["v3"]][packet.number()]
      panel.xyplot(x, ...);
      panel.abline(h = lineData$height[lineData$v3==level])
  }
)

This produces

enter image description here

MrFlick
  • 195,160
  • 17
  • 277
  • 295