Re: [R] lattice 3x3 plot: force common y-limits accross rows and align x-axes
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', '','', '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
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',                  '','',                  '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 oject.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
[R] lattice 3x3 plot: force common y-limits accross rows and align x-axes
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, . 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, 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','','', '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 ## 1A high none 5 ## 2A high optX10 ## 3A 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 none10 ## 12 A med optX 2 ## 13 A med optZ 5 ## 14 med none15 ## 15 med optZ 2 ## 16 A low none 7 ## 17 A low optX 7 ## 18 B low none10 ## 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) library(grid) for (irisk in levels(df$risk)) { # subset data frame df.irisk - subset(df,risk==irisk) # order subjects by
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 On Mon, Feb 18, 2013 at 8:40 AM, Boris Vasiliev bvasil...@yahoo.com wrote: 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, . 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, 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','','', '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 ## 1A high none 5 ## 2A high optX10 ## 3A 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 none10 ## 12 A med optX 2 ## 13 A med optZ 5 ## 14 med none15 ## 15 med optZ 2 ## 16 A low none 7 ## 17 A low optX 7 ## 18 B low none10 ## 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
Re: [R] lattice 3x3 plot: force common y-limits accross rows and align x-axes
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 Cc: mac...@northnet.com.au mac...@northnet.com.au; r-help@r-project.org 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, . 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, 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
Re: [R] lattice 3x3 plot: force common y-limits accross rows and align x-axes
, 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 Cc: mac...@northnet.com.au mac...@northnet.com.au; r-help@r-project.org 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, . 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, 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','','', '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
[R] lattice 3x3 plot: force common y-limits accross rows and align x-axes
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','','', '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 ## 1A high none 5 ## 2A high optX10 ## 3A 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 none10 ## 12 A med optX 2 ## 13 A med optZ 5 ## 14 med none15 ## 15 med optZ 2 ## 16 A low none 7 ## 17 A low optX 7 ## 18 B low none10 ## 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) library(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) assign(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=) assign(paste('oltc.',irisk,sep=''),oltc.irisk) } # combine everthing in one plot oltc - c(low=oltc.low,med=oltc.med,high=oltc.high) print(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,NULL,NULL, sbjx.high,NULL,NULL)) oltd - update(oltc,scales=list(y=yscales), par.settings=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
Re: [R] lattice 3x3 plot: force common y-limits accross rows and align x-axes
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: mac...@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','','', '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 ## 1A high none 5 ## 2A high optX10 ## 3A 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 none10 ## 12 A med optX 2 ## 13 A med optZ 5 ## 14 med none15 ## 15 med optZ 2 ## 16 A low none 7 ## 17 A low optX 7 ## 18 B low none10 ## 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) library(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) assign(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=) assign(paste('oltc.',irisk,sep=''),oltc.irisk) } # combine everthing in one plot oltc - c(low=oltc.low,med=oltc.med,high=oltc.high) print(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 -