My appologies for reposting the final message in this thread. The previous e-mail sent from a Yahoo mailbox got completely scrubbed ... ----- Forwarded Message ----- From: Boris Vasiliev <bvasil...@yahoo.com> To: Duncan Mackay <mac...@northnet.com.au>; "gunter.ber...@gene.com" <gunter.ber...@gene.com>; r-help-r-project.org <r-help@r-project.org> Sent: Tuesday, February 19, 2013 9:05:17 PM Subject: Re: [R] lattice 3x3 plot: force common y-limits accross rows and align x-axes
Duncan and Bert, Thank you very much for your help with my question. It's very much appreciated. I used your suggestions to get the plot I needed: * 3x3 lattice of dotplots, * x-limits are the same for all panels, * y-limits and y-ticks in each row are the same, * y-limits and y-ticks are different between rows, * within each row subjects are ordered by sum(count) in the row. My code is below just in case somebody in the r-help list finds it useful. Regards, Boris. # raw data df <- data.frame( subject=c('A','A','A', 'BB','BB', 'CCC','CCC','CCC', 'DD','DD', 'A','A','A', 'FFFF','FFFF', 'A','A', 'B','B'), risk=c('high','high','high', 'high','high', 'high','high','high', 'med','med', 'med','med','med', 'med','med', 'low','low', 'low','low'), treatment=c('none','optX','optZ', 'none','optZ', 'none','optX','optZ', 'none','optZ', 'none','optX','optZ', 'none','optZ', 'none','optX', 'none','optZ'), count=c(5,10,2, 3,5, 8,1,2, 3,7, 10,2,5, 15,2, 7,7, 10,8)) # re-level factors df$risk <- factor(df$risk,levels=c('low','med','high')) df$treatment <- factor(df$treatment,levels=c('none','optX','optZ')) # create unique subjects ordered by sum(count) and risk df$sbj.byrisk <- paste(df$risk,df$subject,sep="_") df$sbj <- reorder(reorder(df$sbj.byrisk,df$count,sum),as.numeric(df$risk)) df$sbj.ix <- as.numeric(df$sbj) # for each row (i.e. risk), find limits, ticks, labels, and # maximum number of points per panel df.byrisk <- split(df,df['risk']) ylim <- lapply(df.byrisk,function(idf) return(range(idf$sbj.ix))) ytck <- lapply(df.byrisk,function(idf) return(sort(unique(idf$sbj.ix)))) ylbl <- lapply(df.byrisk,function(idf) { ytck <- sort(unique(idf$sbj.ix)) jdnx <- pmatch(ytck,idf$sbj.ix) ylbl <- sub(".*_","",idf$sbj[jdnx]) return(ylbl) }) yhei <- unlist(lapply(ytck,length)) # set up lists for limits, ticks, labels, panel heights ylims <- rep(ylim,c(3,3,3)) ytcks <- rep(list(NULL,NULL,NULL),c(3,3,3)) ytcks[seq(1,7,by=3)] <- ytck ylbls <- rep(list(NULL,NULL,NULL),c(3,3,3)) ylbls[seq(1,7,by=3)] <- ylbl # set up plot layout laywid <- list(axis.panel=c(1,0.1,0.1)) layhei <- list(panel=yhei/sum(yhei)) # plot oltc <- dotplot(sbj~count|treatment+risk,data=df, type=c("p","h"),origin=0, scales=list(x=list(limits=c(-1,16), alternating=FALSE), y=list(relation="free", alternating=FALSE, limits=ylims, at=ytcks, labels=ylbls)), par.settings=list(layout.widths=laywid, layout.heights=layhei), between=list(y=0.2)) useOuterStrips(oltc) ________________________________ From: Duncan Mackay <mac...@northnet.com.au> To: Boris Vasiliev <bvasil...@yahoo.com>; r-help-r-project.org <r-help@r-project.org> Sent: Monday, February 18, 2013 10:29:23 PM Subject: Re: [R] lattice 3x3 plot: force common y-limits accross rows and align x-axes Hi Boris Just a different take on it, quick glimpse of it library(lattice) library(latticeExtra) z= unique(df$subject) df$nsub <- sapply(df$subject, pmatch, z) useOuterStrips(xyplot(count ~ nsub|treatment*risk, df, type = "h", lwd = 2, scales = list(x = list(at = 1:6, labels = z)))) The order can be changed by changing the order in z by making subject a factor in the correct order see http://finzi.psych.upenn.edu/R/Rhelp02/archive/43626.html on how to change the yaxis limits. An example of mine (cut and paste) for an 8x3 panel xyplot (it could be streamlined - i needed to change things as I went along to get everything in) par.settings = layout.heights = list(panel = c(1,1,0.6,0.6,0.6,0.6,1,0.5)/sum(c(1,1,0.6,0.6,1,0.6,1,0.5)) ) ), scales = list(x = list(alternating = FALSE, relation = "same", rot = 0), y = list(alternating = FALSE, relation = "free", limits = list(c(-1500,30000),c(-1500,30000),c(-1500,30000), # BZ c(-1500,30000),c(-1500,30000),c(-1500,30000), # LV c(-2000,20000),c(-2000,20000),c(-2000,20000), # L2 c( -500, 4000),c( -500, 4000),c( -500, 4000), # CL c(-2000,20000),c(-2000,20000),c(-2000,20000), # OP c(-2000,20000),c(-2000,20000),c(-2000,20000), # AB c(-1500,30000),c(-1500,30000),c(-1500,30000), # MO c(-500, 4000),c(-500, 4000),c(-500, 4000)), # MX at = rep(list(seq(0,30000,10000), NULL, seq(0,30000,10000), NULL, seq(0,20000,10000), NULL, seq(0, 4000, 2000), NULL, seq(0,20000,10000), NULL, seq(0,20000,10000), NULL, seq(0,30000,10000), NULL, seq(0, 4000, 2000), NULL ), c(1,2, 1,2, 1,2, 1,2, 1,2, 1,2, 1,2, 1,2) ), labels = rep(list(as.character(seq(0,30,10)), NULL, as.character(seq(0,30,10)), NULL, as.character(seq(0,20,10)), NULL, as.character(seq(0, 4, 2)), NULL, as.character(seq(0,20,10)), NULL, as.character(seq(0,20,10)), NULL, as.character(seq(0,30,10)), NULL, as.character(seq(0, 4, 2)), NULL ), c(1,2, 1,2, 1,2, 1,2, 1,2, 1,2, 1,2, 1,2) ), rot = 0) ), I had different panel heights for each row so if they were all the same it would be panel = rep(1,n)/n the trick is to get the rep of the lists to match what would normally happen for each of the all the panels ie whether an axis/label is required str(plot object) can help if problems HTH Duncan Duncan Mackay Department of Agronomy and Soil Science University of New England Armidale NSW 2351 Email: home: mac...@northnet.com.au <mailto:mac...@northnet.com.au> At 12:22 19/02/2013, you wrote: > Content-Type: text/plain > Content-Disposition: inline > Content-length: 14523 > > Bert, > > Thank you very much for your reply.à Your suggestions to set manually > y-limits of panels in lattice plot certainly puts me on the right track. > > It works really well with xyplot(): > > hf <- data.frame( > à à x=seq(1,20,by=1), > à à y=seq(0.1,2,by=0.1), > à à risk=gl(2,10,labels=c("low","high")), > à à treatment=rep(gl(2,5,labels=c("oXX","oYY")),2))à à à à à à à à > à à à à à > à > xyplot(y~x|treatment+risk,data=hf,type="b", > à à à à à à scales=list(y=list(limits=list(c(-0.1,1.1),c(-0.1,1.1), > à à à à à à à à à à à à à à à à à à à à à à à à à à > à à à à à à à à à à à c(1.0,2.1),c(1.0,2.1)), > à à à à à à à à à à à à à à à à à à > at=list(seq(0,1,0.2),NULL, > à à à à à à à à à à à à à à à à à à à à à à à à à à > seq(1,2,0.2),NULL), > à à à à à à à à à à à à à à à à à à relation="free"))) > > With the xyplot() above, I get 2x2 lattice where panels in the same row have > the same y-limits: > > Panel 1,2 (row 1): -0.1, 1.1 > Panel 3,4 (row 2): 1.0, 2.1 > > Unfortunately, it does not work so well with dot plots: > > > kf <- data.frame(subject=c("A","BB","A","C","DDD","DDD"), > à à à à à à à à à à à à à à à à > risk=c("low","low","low","high","high","high"), > à à à à à à à à à à à à à à à à > treatment=c("oXX","oXX","oYY","oXX","oXX","oYY"), > à à à à à à à à à à à à à à à à count=c(5,7,10,4,13,8)) > kf$risk <- factor(kf$risk,levels=c("low","high")) > kf$treatment <- factor(kf$treatment,levels=c("oXX","oYY")) > > lims.low <- factor(c("A","BB")) > lims.high <- factor(c("C","DDD")) > dotplot(subject~count|treatment+risk,data=kf,type=c("p","h"), > à à à à à à à scales=c(y=list(limits=list(lims.low,lims.low, > à à à à à à à à à à à à à à à à à à à à à à à à à à > à à à à lims.high,lims.high), > à à à à à à à à à à à à à à à à à à à à à à à > relation="free"))) > > > With the dotplot() above I get 2x2 lattice plot where all panels haveà the > same y-limits; y-ticks on all panels are 'A','BB','C','DDD'. > > > This behaviour is probably fixed by design.à According to documentation for > prepanel functions: "... to make this information consistent between panels, > the ââ¬Ëxlimââ¬â¢ or ââ¬Ëylimââ¬â¢ values should represent all > the levels of the corresponding factor, even if some are not used within that > particular panel." > > A way to trick lattice would be to use xyplot() with a custom panel > function.à I'll give a try today or tomorrow. > > Regards, > Boris. > > > > > ________________________________ > From: Bert Gunter <gunter.ber...@gene.com <mailto:gunter.ber...@gene.com> > > > Cc: "mac...@northnet.com.au <mailto:mac...@northnet.com.au> " > <mac...@northnet.com.au <mailto:mac...@northnet.com.au> >; > "r-help@r-project.org <mailto:r-help@r-project.org> " <r-help@r-project.org > <mailto:r-help@r-project.org> > > Sent: Monday, February 18, 2013 1:09:10 PM > Subject: Re: [R] lattice 3x3 plot: force common y-limits accross rows and > align x-axes > > Boris: > > If I understand you correctly, you wish to set panel limits by row. I > know of no "slick" way of doing this (others may), as what is in a row > can change depending on layout and how you determine the scale for the > rows' contents may depend on the application context. > > So I would do it manually: First, outside of trellis, compute your > xlim and ylim values for each row as you desire. Then issue the > trellis call, with the relation="free" component in the scales = list, > Then just use the list form of the xlim and ylim argument to xyplot > with your precomputed limits. > > -- Bert > > > > Hi Duncan, > > > > Thank you for quick reply. > > > > I am not sure that your solution solves the problem.à If I use > > useOuterStrips(dotplot(count ~ subject|risk*treatment,df)) > > the order of subjects and panel y-limits in each panel are > > > > A, B, BB, CCC, DD, FFFF. > > > > However, the order of subjects and y-limits which I would > > like to get are > > > > Panels 1,2,3 (row 1): A, B > > > > Panels 4,5,6 (row 2): DD, A, FFFF > > > > Panels 7,8,9 (row 3): BB, CCC, A. > > > > I can re-index subjects so that they have correct order in each row. > > However, I am not sure how to specify per-panel y-limits in lattice > > so that all panels in the same row have the same y-limits irrespective > > of what data is in these panels. > > > > With relation "same", the limits are the same for all plots; with > > relation "free" the limits depend on the data in the panel.à I thought > > that relation "free" and specification of y-limits via prepanel > > function (my previous trys) or as a list would do the trick: > > scales=list(y=list(limits=list(panel-1-limits, panel-2-limits, ...)) > > but I cannot get it to work. > > > > I guess I am missing something basic ... any ideas or advice to give > > up are greatly appreciated. > > > > Regards, > > Boris. > > > > > > > > Hi Boris > > > > Not sure what you mean exactly > > try > > > > library(latticeExtra) > > useOuterStrips(dotplot(count ~ subject|risk*treatment,df)) > > > > if you want to change the order of the subjects in each panel and an > > index column and plot the index column instead of subject and change > > the scales to suit. > > > > HTH > > > > Duncan > > > > Duncan Mackay > > Department of Agronomy and Soil Science > > University of New England > > Armidale NSW 2351 > > Email: home: mackay at northnet.com.au At 07:54 16/02/2013, you wrote: > >>Good afternoon, >>I would like to ask for help in controlling y-axis limits > >>and labels in >lattice doplots.à Unfortunately, the problem is somewhat > >>convoluted, >please bear with the long explanation. >>I would like to > >>create a 3x3 lattice of dotplots, say subject ~ count. >The plot is > >>conditioned on variables treatment and risk: subject ~ count >|treatment + > >>risk.à In the experiment,à not all subjects were exposed >to all > >>combinations of treatment and risk.à For each risk, I would like >to show > >>subject ~ count | treatment and order the subjects by the total >count.à > >>At the same time, I would like the x-axes to be the same in all >panels and > >>aligned by columns. >>Here is a sample data set: >># raw data >df <- > >>data.frame(subject=c('A','A','A','BB','BB','CCC','CCC','CCC', > >>>'DD','DD','A','A','A','FFFF','FFFF', >'A','A', 'B','B'), > >>>>risk=c('high','high','high','high',' high','high','high','high', > >>>'med','med','med','med','med','med','med', > >à >'low','low','low','low'), >>treatment=c('none > >','optX','optZ','none','optZ','none','optX','optZ', > >>>'none','optZ','none','optX','optZ','none','optZ', > >>'none','optX','none','optZ'), >count=c(5,10,2, 3,5,8,1,2, >3,7,10,2,5,15,2, > >>7,7,10,8)) ># re-level factors >df$risk <- > >factor(df$risk,levels=c('low','med','high')) >df $treatment <- > >factor(df$treatment,levels=c('none','optX','optZ')) >>>## > df >##à à > >subject risk treatment count >## 1à à à à A highà à à noneà > >à 5 >## 2à à à à A highà à à optXà à 10 >## 3à à à > >à A highà à à optZà à 2 >## 4à à à BB highà à à > >noneà à 3 >## 5à à à BB highà à à optZà à 5 >## 6à à > >à CCC highà à à noneà à 8 >## 7à à à CCC highà à à > >optXà à 1 >## 8à à à CCC highà à à optZà à 2 >## 9à à > > à DDà medà à à noneà à 3 >## 10à à à DDà medà à > >à optZà à 7 >## 11à à à Aà medà à à noneà à 10 >## > >12à à à Aà medà à à optXà à > 2 >## 13à à à Aà medà à à optZà à 5 >## 14à à FFFFà > medà à à noneà à 15 >## 15à à FFFFà medà à à optZ > >à 2 >## 16à à à Aà lowà à à noneà à 7 >## 17à à à > >Aà lowà à à optXà à 7 >## 18à à à Bà lowà à à > >noneà à 10 >## 19à à à Bà lowà à à optZà à 8 >>One way > >to plot the data is to break-up the data into sub-frames, one >frame for > >each risk, order subjects by total counts, create dotplots, >and merge with > >trellis.c().à This almost works but in the merged plot I >cannot decrease > >column spacing to be small enough.à Also, the output of >trellis.c() would > >not work with useOuterStrips() which I really like. >My code is in TRY ONE > >below. >>Another way to create the plot is specify y-limits for each panel > >with >custom prepanel and panel functions.à For each panel, the data-frame > >for >the panel row is isolated, subjects in the data-frame for the current > >>row are ordered by counts, panel y-limits are set to the re-ordered > >>levels, y-data for each panel is releveled, and data plotted with >standard > >panel.dotplot().à This > somewhat works but lattice does not >honour > >à the user-defined y-limits and labels are not correct.à I suspect >that > >it is not correct to useà y-relation="same" in this case but "free" >and > >"sliced" do not give correct results too. My code in in TRY TWO >below. >>If > >anybody can offer any assistance with this problem, it would be much > >>appreciated, >Sincerely, >Boris. >>>#### BEGIN TRY ONE - MERGE LATTICE > >PLOTS #### >library(lattice) >library(latticeExtra) >l ibrary(grid) >>for > >(irisk in levels(df$risk)) { ># subset data frame >df.irisk <- > >subset(df,risk==irisk) >># order subjects by total count; store levels of > >subjectx variables ># for later re-use in panel labels >df.irisk$subjectx <- > >df.irisk$subject[,drop=TRUE] >df.irisk$subjectx <- > >reorder(df.irisk$subjectx,df.irisk$count,sum) >a > >ssign(paste('sbjx.',irisk,sep=''),levels(df.irisk$subjectx)) >># create > >dotplot and store it in oltc.{irisk} variable >oltc.irisk <- > >dotplot(subjectx~count|treatment,data=df.irisk, > >>layout=c(3,1),type=c('p','h'), > >à >xlim=c(-1,16),origin=0, >xlab="",ylab="") >as > >sign(paste('oltc.',irisk,sep=''),oltc.irisk) >} >># combine everthing in > >one plot >oltc <- c(low=oltc.low,med=oltc.med,high=oltc.high) >pri nt(oltc) > >>># get rid of variable labels in middle and right column; decrease ># > >distance between columns.à But can't make inter-column spaces ># small > >enought and get rid of the panels in all but top rows. >laywid <- > >trellis.par.get('layout.widths') >laywid$between <- -5 >laywid$axis.panel > ><- 0.7 >yscales <- list(labels=list(sbjx.low,NULL,NULL, >sbjx.med,N > >ULL,NULL, >sbjx.high,NULL,NULL)) >oltd <- > >update(oltc,scales=list(y=yscales), >par.setting > >s=list(layout.widths=laywid)) >print(oltd) >>### # END TRY ONE - MERGE > >LATTICE PLOTS #### >>#### BEGIN TRY TWO - CUSTOM PREPANEL AND PANEL > >FUNCTIONS #### >>prepanel.dotplot.x <- > >function(x,y,type,subscripts,...,data=NULL) { ># find data-frame that > >corresponds to the entire row of the plot >irisk <- > >à levels(data$risk[subscripts,drop=TRUE]) >idata <- > >subset(data,risk==irisk) >># in the sub-frame, order subjects by total > >counts >idata$subjectx <- reorder(idata$subject[,drop=TRUE],idata$count,sum) > > >># set y-limits >ylim <- levels(idata$subjectx) >># increment packet > >counter and print new panel limits >pcknum = > >lattice.options()$packet.counter >lattice.option s(packet.counter=pcknum+1) > >>cat(paste(pcknum,":" ,paste(ylim,collapse=", ")),sep="\n") > >>return(list(ylim=ylim)) >} >>pane l.dotplot.x <- > >function(x,y,type,subscripts,...,data=NULL) { ># get the sub-frame for the > >row >irisk <- levels(data$risk[subscripts,drop=TRUE]) >idata <- > >subset(data,risk==irisk) >># in the sub-frame, order subjects by total > >counts >idata$subjectx <- reorder(idata$subject[,drop=TRUE],idata$count,sum) > > >># re-order y-variable to "correct levels" >y <- > >factor(as.character(y),levels(idata$subjectx)) > ># print levels of the > >releveled subjects - should be the same ># as the output of > >à prepanel.dotplot.x >pnlnum <- panel.number() > >>cat(paste(pnlnum,':',paste(level s(y),collapse=", ")),sep="\n") >># call > >standard dotplot >panel.dotplot(x,y,...) >} >># the data is plotted > >correctly but the labels and limits are not >correct > >>lattice.options(packet.counter=1) >oltc <- > >dotplot(subject~count|treatment+risk,data=df, >l > >ayout=c(3,3),subscripts=TRUE, >prepanel=function (...) > >>{prepanel.dotplot.x(...,data=df)}, >panel > >=function(...){panel.dotplot.x(...,data=df)}, >s > >cales=list(y=list(relation='same')), >drop.unuse d.levels=FALSE, > >>xlim=c(0,16)) >print(oltc) >>## ## END TRY TWO - CUSTOM PANEL AND PREPANEL > >FUNCTIONS #### >>_________________________________________ _____ >R-help at > >r-project.org mailing list >https://stat.ethz.ch/mailman/listinfo/r-he lp > >>PLEASE do read the posting guide > >http://www.R-project.org/posting-guide.html >and provide commented, > >minimal, self-contained, reproducible code. > >à à à à [[alternative HTML version deleted]] > > > > ______________________________________________ > > R-help@r-project.org <mailto:R-help@r-project.org> mailing list > > https://stat.ethz.ch/mailman/listinfo/r-help > > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > > and provide commented, minimal, self-contained, reproducible code. > > > > -- > > Bert Gunter > Genentech Nonclinical Biostatistics > > Internal Contact Info: > Phone: 467-7374 > Website: > http://pharmadevelopment.roche.com/index/pdb/pdb-functional-groups/pdb-biostatistics/pdb-ncb-home.htm > [[alternative HTML version deleted]] > > > ______________________________________________ > R-help@r-project.org <mailto:R-help@r-project.org> mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. [[alternative HTML version deleted]]
______________________________________________ R-help@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.