Daniel Myall
2007-Nov-15 21:00 UTC
[R] Writing a helper function that takes in the dataframe and variable names and then does a subset and plot
Hi, I have a large dataframe than I'm writing functions to explore, and to reduce cut and paste I'm trying to write a function that does a subset and then a plot. Firstly, I can write a wrapper around a plot: plotwithfits <- function(formula, data, xylabels=c('','')) { xyplot(formula, data, panel function(x,y, ...) { panel.xyplot(x,y, ...) panel.abline(lm(y~x),lwd=2, ...) panel.loess(x,y,lwd=2,col.line='red', ...) }, xlab = xylabels[1], ylab= xylabels[2]) } plotwithfits(Latency ~ Stimulus.number | Subject.ID,eye_subsetted_data) # Works However, I can't get it working if I try the same for a subset and plot: explorebysubject <- function(xvar,yvar,data,condition=TRUE,xlim=c(-Inf,Inf),ylim=c(-Inf,Inf)) { temp_subset <- subset(data, subset=condition&xvar>xlim[1]&xvar<xlim[2]&yvar>ylim[1]&yvar<ylim[2], select=c(Group,Subject.ID,xvar,yvar) ) plotwithfits(xvar~yvar | Subject.ID,temp_subset) } explorebysubject(Latency,Primary.gain,eye,Analysis.type == 'reflexive') # Doesn't work as can't find 'Analysis.type', 'Latency', etc I can see why it doesn't work, however, I've looked at substitute, deparse, etc, without much luck. Is there a something simple I could do to fix this up? Is there any material I should be reading? Using the arguments eye$Latency, eye$Primary.gain, etc would partially solve this problem, however I would prefer to avoid this if possible. One unclean way that does work is constructing strings and then evaluating them. However, as I am planning to write several similar functions I would prefer to avoid this: explorebysubject <- function(xvar,yvar,dataset,condition,xlim=c(-Inf,Inf),ylim=c(-Inf,Inf)) { # xvar - variable to plot along x-axis # yvar - variable to plot along y-axis # the dataset to use # condition - used to provide extra conditions on the data selected # xlim, ylim - optional limits of data to select. i.e. xlim=c(0,1) # Generate command to select appropriate data cmd <- paste("subset(",dataset,",",condition,"&",xvar,">",xlim[1],"&",xvar,"<",xlim[2],"&",yvar,">",ylim[1],"&",yvar,"<",ylim[2],",select=c(",xvar,",",yvar,",Group,Subject.ID))") temp_subset <- eval(parse(text=cmd)) #generate plot command cmd <- paste("plotwithfits(",xvar,"~",yvar,"|Subject.ID,temp_subset)") eval(parse(text=cmd)) } explorebysubject('Latency','Primary.gain','eye',"Analysis.type == 'reflexive'",xlim=c(90,500),ylim=c(0.5,1.5)) # Works Thanks. Cheers, Daniel
Emmanuel Charpentier
2007-Nov-15 22:25 UTC
[R] Writing a helper function that takes in the dataframe and variable names and then does a subset and plot
Dear Daniel, May I point you to Thomas Lumley's paper in R News 2001-3 ("Programmer?s Niche: Macros in R\n Overcoming R?s virtues) and to the defmacro utility of the gtools package ? HTH Emmanuel Charpentier Daniel Myall a ?crit :> Hi, > > I have a large dataframe than I'm writing functions to explore, and to > reduce cut and paste I'm trying to write a function that does a subset > and then a plot. > > Firstly, I can write a wrapper around a plot: > > plotwithfits <- function(formula, data, xylabels=c('','')) { > xyplot(formula, data, panel > function(x,y, ...) { > panel.xyplot(x,y, ...) > panel.abline(lm(y~x),lwd=2, ...) > panel.loess(x,y,lwd=2,col.line='red', ...) > }, > xlab = xylabels[1], ylab= xylabels[2]) > } > > plotwithfits(Latency ~ Stimulus.number | Subject.ID,eye_subsetted_data) > # Works > > > > However, I can't get it working if I try the same for a subset and plot: > > explorebysubject <- > function(xvar,yvar,data,condition=TRUE,xlim=c(-Inf,Inf),ylim=c(-Inf,Inf)) { > > temp_subset <- subset(data, > > subset=condition&xvar>xlim[1]&xvar<xlim[2]&yvar>ylim[1]&yvar<ylim[2], > select=c(Group,Subject.ID,xvar,yvar) > ) > > plotwithfits(xvar~yvar | Subject.ID,temp_subset) > } > > explorebysubject(Latency,Primary.gain,eye,Analysis.type == 'reflexive') > # Doesn't work as can't find 'Analysis.type', 'Latency', etc > > I can see why it doesn't work, however, I've looked at substitute, > deparse, etc, without much luck. > > Is there a something simple I could do to fix this up? Is there any > material I should be reading? > > Using the arguments eye$Latency, eye$Primary.gain, etc would partially > solve this problem, however I would prefer to avoid this if possible. > > One unclean way that does work is constructing strings and then > evaluating them. However, as I am planning to write several similar > functions I would prefer to avoid this: > > explorebysubject <- > function(xvar,yvar,dataset,condition,xlim=c(-Inf,Inf),ylim=c(-Inf,Inf)) { > # xvar - variable to plot along x-axis > # yvar - variable to plot along y-axis > # the dataset to use > # condition - used to provide extra conditions on the data selected > # xlim, ylim - optional limits of data to select. i.e. xlim=c(0,1) > > # Generate command to select appropriate data > cmd <- > paste("subset(",dataset,",",condition,"&",xvar,">",xlim[1],"&",xvar,"<",xlim[2],"&",yvar,">",ylim[1],"&",yvar,"<",ylim[2],",select=c(",xvar,",",yvar,",Group,Subject.ID))") > > temp_subset <- eval(parse(text=cmd)) > > #generate plot command > cmd <- > paste("plotwithfits(",xvar,"~",yvar,"|Subject.ID,temp_subset)") > eval(parse(text=cmd)) > > } > > explorebysubject('Latency','Primary.gain','eye',"Analysis.type == > 'reflexive'",xlim=c(90,500),ylim=c(0.5,1.5)) # Works > > Thanks. > > Cheers, > Daniel > > ______________________________________________ > R-help at 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. >