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)