1

This is a data.frame whose third "column" is in fact a matrix:

pred.Alb <- structure(list(Age = 
   c(20, 30, 40, 50, 60, 70, 80, 20, 30, 40, 
   50, 60, 70, 80), Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
   2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("Male", "Female"), 
   class = "factor"), 
pred = structure(c(4.34976914720261, 4.3165897157342, 4.2834102842658, 
4.23952109360855, 4.15279286619591, 4.05535487959442, 3.95791689299294, 
4.02417706540447, 4.05661037005163, 4.08904367469879, 4.0942071858864, 
3.9902915232358, 3.85910606712565, 3.72792061101549, 4.37709246711838, 
4.38914906337186, 4.40120565962535, 4.3964228776405, 4.32428258270227, 
4.23530290952571, 4.14632323634915, 4.3, 4.3, 4.3, 4.28809523809524, 
4.22857142857143, 4.15714285714286, 4.08571428571429, 4.59781730640631, 
4.59910124381436, 4.60038518122242, 4.58132673532165, 4.48089875618564, 
4.36012839374081, 4.23935803129598, 4.39298701298701, 4.39711229946524, 
4.40123758594347, 4.39484310896076, 4.34636957813428, 4.28737628384687, 
4.22838298955946), .Dim = c(14L, 3L), .Dimnames = list(c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", 
"13", "14"), c("tau= 0.10", "tau= 0.25", "tau= 0.50")))), 
  .Names = c("Age", "Sex", "pred"), out.attrs =
  structure(list(dim = structure(c(7L, 2L), .Names = c("Age", "Sex")), 
  dimnames = structure(list(Age = c("Age=20", 
        "Age=30", "Age=40", "Age=50", "Age=60", "Age=70", "Age=80"), 
Sex = c("Sex=Male", "Sex=Female")),
.Names = c("Age", "Sex"))), 
.Names = c("dim", "dimnames")), row.names = c(NA, -14L), 
 class = "data.frame")

It was created with this code:

require(rms) # also loads Hmisc
require(quantreg) # might also get loaded by rms
rqAlb10fit2 <- rq(BL_ALBUMIN ~ rcs(Age,3) *Sex , data=redBan, 
                                    tau= c(0.1, 0.25, 0.5) )
pred.Alb <- expand.grid(Age=seq(20,80,by=10), Sex=c("Male", "Female") ) 
pred.Alb$pred <- predict(rqAlb10fit2, 
  newdata=expand.grid(Age=seq(20,80,by=10), Sex=c("Male", "Female") ) )

I would like to have a line plot of the predictions by Sex and tau level. I can get a points plot with:

xyplot(pred~Age|Sex, data=pred.Alb, type="p")

When I add type="l", the lines slew back and forth connecting the various levels of tau.

I doubt that it matters, but running on Mac 10.7.5 with quantreg_4.96/rms_3.6-3/Hmisc_3.10-1. If you want to show me a ggplot solution with classic theme, I'm OK with that too, it's just that I am not very good with ggplot2 and Harrell's rms package is mated to lattice.

2 Answers 2

5

The problem appears to be that y loses its dimension attribute when it's passed into the panel function, becoming a simple vector. It still goes ahead and plots, recycling x to match y's length, which you can't see type="p", but can when type="l".

Here is a custom panel function that accomplishes what you want by first converting y back to a matrix and then calling panel.xyplot separately on each of its columns:

panel.matplot <- function(x,y,...) {
    y <- matrix(y, nrow=length(x))
    apply(y, 2, function(Y) panel.xyplot(x,Y, ...))
}

xyplot(pred~Age|Sex, data=pred.Alb, type="l", panel=panel.matplot)

enter image description here


BTW: In cases like this, I often find it useful to poke around 'inside' the panel function call. A simple way to do this is to construct a dummy panel function containing a browser() call. Here, for example, is how I discovered the problem in this case:

xyplot(pred~Age|Sex, data=pred.Alb, type="l",
       panel = function(x,y,...) browser())
Browse[2]> x
# [1] 20 30 40 50 60 70 80
Browse[2]> y
#  [1] 4.349769 4.316590 4.283410 4.239521 4.152793 4.055355 3.957917 4.377092
#  [9] 4.389149 4.401206 4.396423 4.324283 4.235303 4.146323 4.597817 4.599101
# [17] 4.600385 4.581327 4.480899 4.360128 4.239358

... at which point the required fix is both (a) pretty obvious and (b) can be tested out from within the existing browser call.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the investigatory hints. I was reading old r-help postings from Deepayan Sarkar, but this answer is better than what I found (so far) from the master.
Glad to help, and please let me know if you do find anything better. Cheers!
2

You can do this by reshaping to long and using the groups argument to xyplot:

pred2 <- as.data.frame(pred.Alb$pred)
varying=names(pred2)
pred2$Age <- pred.Alb$Age
pred2$Sex <- pred.Alb$Sex
pred2.long <- reshape(pred2, direction='long', varying=varying, sep='= ')

xyplot(tau~Age|Sex, data=pred2.long, type="l", groups=time)

enter image description here

1 Comment

Good work. I had tried reshaping with much less success than you have achieved. I like the fact that the lines are differently colored and it suggests I could get a good looking legend.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.