Sumitrajit Dhar
2015-Aug-28 04:11 UTC
[R] Piecewise regression using segmented package plotted in xyplot
Hi, xyplot(threshold ~ age |frequency.a, data=rage, groups=HL, cex=0.5, layout=c(7,4), par.strip.tex=list(cex=0.8), xlab="Age (years)", ylab="Threshold (dB SPL)", na.rm="TRUE", panel=function(x,y,groups,...) { panel.superpose(x,y,groups=HL,...) # panel.abline(segmented(lm(threshold~age),seg.Z = ~age, psi = NA, control = seg.control(K=1))) panel.abline(lm(threshold~age)) }, ) Is there anyway to make the commented line work in lattice? I need to fit my data in each panel using piecewise regression. Being able to use segmented would make it easy. The code above works to give me a linear fit. Thanks for your help in advance. Regards, Sumit [[alternative HTML version deleted]]
S Ellison
2015-Aug-28 11:04 UTC
[R] Piecewise regression using segmented package plotted in xyplot
There isn't an abline method for segmented, and even if there were you'd need segments() for a segmented line plot. You're going to have to roll your own. That will need a function to extract the break locations and predicted values at those points I don't have your data, so I can't do one specifically for you. But here's a version that works on the data in the first example in ?segmented. I've deliberately separated segmented model fitting and line segment extraction (get.segments) from the panel function that plots them, as that would then work with the base graphics segments function #Construct the data set (from ?segmented, though the z covariate is not used here) set.seed(12) xx<-1:100 zz<-runif(100) yy<-2+1.5*pmax(xx-35,0)-1.5*pmax(xx-70,0)+15*pmax(zz-.5,0)+rnorm(100,0,2) dati<-data.frame(x=xx,y=yy,z=zz) # Function to fit a simple model using segmented # and then get line segment data from the model # For the latter, I've used code from plot. segmented to locate extremes # and break points (in psi) and then just used # predict() rather crudely to get the corresponding ordinate values # you would have to do something more clever # if your model is not just y~x get.segments <- function(x, y, term, ...) { #Returns a data frame of line segment coordinates #from a simple segmented() model S <- segmented(lm(y~x), seg.Z=~x,psi=list(x=c(30,60)), control=seg.control(display=FALSE)) if(missing(term)) term <- S$nameUV$Z[1] x<-with(S, sort(c(psi[,'Est.'], rangeZ[,term]))) #Then cheat a bit new <- data.frame(x=unname(x)) names(new) <- term y <- predict(S, new=new) L <- length(x) -1 #return the line segment data in an easy-to-use format data.frame(x0=x[1:L], y0=y[1:L], x1=x[1:L + 1], y1=y[1:L + 1]) } #Write a panel function using that... panel.segmented <- function(x, y, ...) { ## Fit the simple model m <- get.segments( x, y ) #Plot the segments with(m, panel.segments(x0, y0, x1, y1, ... )) } library(lattice) xyplot(y~x, data=dati, panel = function(x, y, ...) { panel.xyplot(x, y, ...) panel.segmented(x, y, ...) } ) #And just to see if it works for panel-grouped data: set.seed(1023) dati$parts <- sample(gl(2, 50)) xyplot(y~x|parts, data=dati, panel = function(x, y, ...) { panel.xyplot(x, y, ...) panel.segmented(x, y, ...) } ) S Ellison ******************************************************************* This email and any attachments are confidential. Any use...{{dropped:8}}
S Ellison
2015-Aug-28 11:25 UTC
[R] Piecewise regression using segmented package plotted in xyplot
I perhaps should have added a stronger warning here; note that the model fitting in my previous post (below) uses explicit initial breakpoints for segmented (specifically, c(30,60) at line 1 of the get.segments() ). if you know where yours are, substitute them there. Otherwise, you'd need to use the automated breakpoint routines documented in ?segmented, typically adjusting the control list. To be general, you'd need a way to get a choice of at least number of breakpoints into the model. xyplot doesn't (I think) pass extra parameters to its panel function, but it will pick up environment parameters so you _could_ just rely on that, or perhaps on setting something in options(), as a quick and dirty work-round. S Ellisaon -------------------------- There isn't an abline method for segmented, and even if there were you'd need segments() for a segmented line plot. You're going to have to roll your own. That will need a function to extract the break locations and predicted values at those points I don't have your data, so I can't do one specifically for you. But here's a version that works on the data in the first example in ?segmented. I've deliberately separated segmented model fitting and line segment extraction (get.segments) from the panel function that plots them, as that would then work with the base graphics segments function #Construct the data set (from ?segmented, though the z covariate is not used here) set.seed(12) xx<-1:100 zz<-runif(100) yy<-2+1.5*pmax(xx-35,0)-1.5*pmax(xx-70,0)+15*pmax(zz-.5,0)+rnorm(100,0,2) dati<-data.frame(x=xx,y=yy,z=zz) # Function to fit a simple model using segmented # and then get line segment data from the model # For the latter, I've used code from plot. segmented to locate extremes # and break points (in psi) and then just used # predict() rather crudely to get the corresponding ordinate values # you would have to do something more clever # if your model is not just y~x get.segments <- function(x, y, term, ...) { #Returns a data frame of line segment coordinates #from a simple segmented() model S <- segmented(lm(y~x), seg.Z=~x,psi=list(x=c(30,60)), control=seg.control(display=FALSE)) if(missing(term)) term <- S$nameUV$Z[1] x<-with(S, sort(c(psi[,'Est.'], rangeZ[,term]))) #Then cheat a bit new <- data.frame(x=unname(x)) names(new) <- term y <- predict(S, new=new) L <- length(x) -1 #return the line segment data in an easy-to-use format data.frame(x0=x[1:L], y0=y[1:L], x1=x[1:L + 1], y1=y[1:L + 1]) } #Write a panel function using that... panel.segmented <- function(x, y, ...) { ## Fit the simple model m <- get.segments( x, y ) #Plot the segments with(m, panel.segments(x0, y0, x1, y1, ... )) } library(lattice) xyplot(y~x, data=dati, panel = function(x, y, ...) { panel.xyplot(x, y, ...) panel.segmented(x, y, ...) } ) #And just to see if it works for panel-grouped data: set.seed(1023) dati$parts <- sample(gl(2, 50)) xyplot(y~x|parts, data=dati, panel = function(x, y, ...) { panel.xyplot(x, y, ...) panel.segmented(x, y, ...) } ) S Ellison ******************************************************************* This email and any attachments are confidential. Any use...{{dropped:8}}
Duncan Mackay
2015-Aug-28 14:31 UTC
[R] Piecewise regression using segmented package plotted in xyplot
Hi Without a reproducible example I am only guessing Try this xyplot(threshold ~ age |frequency.a, data=subset(rage !is.na(threshold} & !is.na(age)), groups = HL, cex=0.5, layout=c(7,4), par.strip.tex=list(cex=0.8), xlab="Age (years)", ylab="Threshold (dB SPL)", # na.rm="TRUE", # see above type = c("p","l"), # re-read ?xyplot: from the panel section: panel.abline(lm(threshold~age)) panel = panel.superpose, panel.groups =function(x,y,groups,...) { panel.xyplot(x,y,...) # panel.abline(segmented(lm(threshold~age),seg.Z ~age, psi = NA, control = seg.control(K=1))) }, ) I do not know what the commented line means-- you may need to look at the subscripts section as well as panel.groups of ?xyplot and ?panel.xyplot Regards Duncan Duncan Duncan Mackay Department of Agronomy and Soil Science University of New England Armidale NSW 2351 Email: home: mackay at northnet.com.au -----Original Message----- From: R-help [mailto:r-help-bounces at r-project.org] On Behalf Of Sumitrajit Dhar Sent: Friday, 28 August 2015 14:12 To: r-help at r-project.org Subject: [R] Piecewise regression using segmented package plotted in xyplot Hi, xyplot(threshold ~ age |frequency.a, data=rage, groups=HL, cex=0.5, layout=c(7,4), par.strip.tex=list(cex=0.8), xlab="Age (years)", ylab="Threshold (dB SPL)", na.rm="TRUE", panel=function(x,y,groups,...) { panel.superpose(x,y,groups=HL,...) # panel.abline(segmented(lm(threshold~age),seg.Z = ~age, psi = NA, control seg.control(K=1))) panel.abline(lm(threshold~age)) }, ) Is there anyway to make the commented line work in lattice? I need to fit my data in each panel using piecewise regression. Being able to use segmented would make it easy. The code above works to give me a linear fit. Thanks for your help in advance. Regards, Sumit [[alternative HTML version deleted]] ______________________________________________ R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see 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.