Dear colleagues, I have a problem which has bitten me occasionally. I often need to prepare graphs for many variables in a data set, but seldom for all. or for any large number of sequential or sequentially named variables. Often I need several graphs for different subsets of the dataset for a given variable. I run into similar problems with other needs besides graphing. What I would like to do is something like "write a function which takes the *name* of a variable, presumably a s a character string, from a dataframe, as one argument, and the dataframe, as a second argument". For example, where y is to be the the name of a variable in a given dataframe d, and the other variables needed, T, M and so on, are to be found in the same dataframe :- pf <- function (y,data,...) { p1 <- xyplot(y~x|T,data) p2 <- xyplot(y~x|T,subset(data,M == 2)) p3 <- xyplot(y~x|T,subset(data,M == 4)) #print(p1,p2,p3....) } pf(Score1,data) pf(Score2,data) This fails, because, of course, Score 1, Score 2 etc.. are not defined, or if you pass them as pf(data$Score2,data), then when you subset the data, data$Score2 is now the wrong shape. I've come up with various inelegant hacks, (often with for loops), for getting around this over the last few years, but I can't help feeling that I'm missing something obvious, which I've been too dim to spot. Please note the answer to my requirements is *not* a clever use of lattice. This question goes beyond graphs. All suggestions gratefully received! Best wishes, Anthony Staines -- Anthony Staines,? Professor of Health Systems Research, School? of Nursing, Dublin City University, Dublin 9, Ireland. Tel:- +353 1 7007807. Mobile:- +353 86 606 9713
Hello,> I have a problem which has bitten me occasionally. I often need to > prepare graphs for many variables in a data set, but seldom for all. > or for any large number of sequential or sequentially named variables. > Often I need several graphs for different subsets of the dataset > for a given variable. I run into similar problems with other needs > besides graphing. > > What I would like to do is something like "write a function which > takes the *name* of a variable, presumably a s a character string, > from a dataframe, as one argument, and the dataframe, as a second argument". > > For example, where y is to be the the name of a variable in a given > dataframe d, and the other variables needed, T, M and so on, are > to be found in the same dataframe :- > > pf <- function (y,data,...) { > p1 <- xyplot(y~x|T,data) > p2 <- xyplot(y~x|T,subset(data,M == 2)) > p3 <- xyplot(y~x|T,subset(data,M == 4)) > #print(p1,p2,p3....) > } > pf(Score1,data) > pf(Score2,data) > > > This fails, because, of course, Score 1, Score 2 etc.. are not > defined, or if you pass them as pf(data$Score2,data), then when you > subset the > data, data$Score2 is now the wrong shape. > I've come up with various > inelegant hacks, (often with for loops), for getting around this over > the > last few years, but I can't help feeling that I'm missing something > obvious, which I've been too dim to spot.Depending on your needs (e.g., you use formulas, which can be trickier), I think I often do something like: # I prefer this, I quote the variable name... df1 <- data.frame(x = rnorm(100), score1 = rnorm(100), M = sample(c(2, 4), 100, replace = TRUE)) pf <- function (y,data,...) { data$y <- data[[y]] xyplot(y~x, subset(data, M == 2)) } pf("score1", df1) # as an alternative, use eval/substitute, don't have to quote pf2 <- function (y,data,...) { data$y <- eval(substitute(y), data) xyplot(y~x, subset(data, M == 2)) } pf2(score1, df1)
Hi Anthony, I don't know if this will help you. A similar method should work for any function that accepts a formula, which is your main issue I think. Outside of formulae, you should just be able to pass the arguments directly (as with the data argument of xyplot). The only other thought that comes to mind involves a combination of eval() and parse(), but its obvious messiness and fortune(106), suggest that that is not worth sharing. #Some data to work with mydata <- data.frame(x = 1:10, Score1 = 1:10, T = rep(c(1,2), 5), M = rep(c(2,4), each = 5)) #Function pf <- function (y, data, ...) { #Save the old par() settings, and restore at the end old.par <- par(no.readonly = TRUE) on.exit(par(old.par)) #Set it so it asks before changing graphs par(ask = TRUE) #Create a text string of your formula my.f <- paste(y, " ~ x|T", sep = "") #Initialize a list and calculate plots p <- vector("list", length = 3) p[[1]] <- xyplot(x = formula(my.f), data = data) p[[2]] <- xyplot(x = formula(my.f), data = subset(x = data, subset = M == 2)) p[[3]] <- xyplot(x = formula(my.f), data = subset(x = data, subset = M == 4)) #Graph the plots for(i in 1:length(p)) { print(p[[i]]) } } #Graphs! pf(y = "Score1", data = mydata) HTH, Josh On Wed, Aug 4, 2010 at 6:56 AM, Anthony Staines <anthony.staines at gmail.com> wrote:> Dear colleagues, > > I have a problem which has bitten me occasionally. I often need to > prepare graphs for many variables in a data set, but seldom for all. > or for any large number of sequential or sequentially named variables. > Often I need several graphs for different subsets of the dataset > for a given variable. ?I run into similar problems with other needs > besides graphing. > > ?What I would like to do is something like "write a function which > takes the *name* of a variable, presumably a s a character string, > from a dataframe, as one argument, and the dataframe, as a second argument". > > For example, where y is to be the the name of a variable in a given > dataframe d, and the other variables needed, T, M and so on, are > to be found in the same dataframe :- > > pf <- function (y,data,...) { > p1 <- xyplot(y~x|T,data) > p2 <- xyplot(y~x|T,subset(data,M == 2)) > p3 <- xyplot(y~x|T,subset(data,M == 4)) > #print(p1,p2,p3....) > } > ?pf(Score1,data) > pf(Score2,data) > > > This fails, because, of course, Score 1, Score 2 etc.. are ?not > defined, or if you pass them as pf(data$Score2,data), then when you > subset the > data, data$Score2 is now the wrong shape. ?I've come up with various > inelegant hacks, (often with for loops), for getting around this over > the > last few years, but I can't help feeling that I'm missing something > obvious, which I've been too dim to spot. > > Please note the answer to my requirements is *not* a clever use of > lattice. This question goes beyond graphs. > All suggestions gratefully received! > > Best wishes, > Anthony Staines > -- > Anthony Staines,? Professor of Health Systems Research, > School? of Nursing, Dublin City University, Dublin 9, Ireland. > Tel:- +353 1 7007807. Mobile:- +353 86 606 9713 > > ______________________________________________ > 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. >-- Joshua Wiley Ph.D. Student, Health Psychology University of California, Los Angeles http://www.joshuawiley.com/
Thanks to Joshua and Erik for very helpful suggestions. This clarifies what I had found to be a tricky area of the documentation! Best wishes, Anthony Staines -- Anthony Staines,? Professor of Health Systems Research, School? of Nursing, Dublin City University, Dublin 9, Ireland. Tel:- +353 1 7007807. Mobile:- +353 86 606 9713
Dear Anthony On Wed, 4 Aug 2010 14:56:58 +0100 Anthony Staines <anthony.staines at gmail.com> wrote:> What I would like to do is something like "write a function which > takes the *name* of a variable, presumably a s a character string, > from a dataframe, as one argument, and the dataframe, as a second > argument". >I am not sure that this is what you're looking for, but I was working on this all day and am pretty happy with the result. The following code takes a list of character variable names x.vars, apply-ies the function to each variable .var in data frame .data (with optional subset .subs) and stores the results in a list names-ed after the original variables list. Best regards Liviu my.fun <- function(.var, .data, .subs) { require(lattice) res <- list() x <- .data[[.var]][.subs] res <- bwplot(x, main=.var) return(res) } x.vars <- as.list(names(mtcars)[2:5]) names(x.vars) <- names(mtcars)[2:5] x.vars ##there's probably a nicer way of doing this x <- lapply(x.vars, my.fun, .data=mtcars) x ##if you use Sweave, don't forget to print(x)