andrewH
2011-Sep-15 21:11 UTC
[R] Returning the name of an object passed directly or from a list by lapply
Dear folks: Let?s suppose I want a function to print return the name of the object passed to it.> myname <- function(object) {out<-deparse(substitute(object)); out}This works fine on a single object:> O1 <-c(1:4) > myname(O1)[1] "O1" However it does not work if you use lapply to pass it the same object from a list:> O2 <-c(1:4) > object.list <- list(O1,O2) > lapply(object.list, myname)[[1]] [1] "X[[1L]]" [[2]] [1] "X[[2L]]" Is there any way to write myname() so that it returns the same objects name regardless of whether it is handed the name directly or by lapply as an element of a list? Any help you can offer would be greatly appreciated. Warmly, andrewH -- View this message in context: http://r.789695.n4.nabble.com/Returning-the-name-of-an-object-passed-directly-or-from-a-list-by-lapply-tp3816798p3816798.html Sent from the R help mailing list archive at Nabble.com.
William Dunlap
2011-Sep-15 21:53 UTC
[R] Returning the name of an object passed directly or from a list by lapply
> -----Original Message----- > From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] On Behalf Of andrewH > Sent: Thursday, September 15, 2011 2:11 PM > To: r-help at r-project.org > Subject: [R] Returning the name of an object passed directly or from a list by lapply > > Dear folks: > > Let?s suppose I want a function to print return the name of the object > passed to it. > > > myname <- function(object) {out<-deparse(substitute(object)); out} > > This works fine on a single object: > > O1 <-c(1:4) > > myname(O1) > [1] "O1" > > However it does not work if you use lapply to pass it the same object from a > list: > > O2 <-c(1:4) > > object.list <- list(O1,O2) > > lapply(object.list, myname) > [[1]] > [1] "X[[1L]]" > > [[2]] > [1] "X[[2L]]" > > Is there any way to write myname() so that it returns the same objects name > regardless of whether it is handed the name directly or by lapply as an > element of a list?The short answer is "no", because object.list does not contain the names I think you are looking for ("O1" and "O2"). Notice that list(O1, O2) and list(1:4, 1:4) are identical. I suggest abandoning the myname() function and instead attach names to your lists. These names stay attached to the object, unlike the name you call a dataset in a particular evaluation frame. > O1 <- 1:4 > object.list <- list(O1=O1, O2=5:8) > lapply(seq_along(object.list), function(i) names(object.list)[i]) [[1]] [1] "O1" [[2]] [1] "O2" Bill Dunlap Spotfire, TIBCO Software wdunlap tibco.com> > Any help you can offer would be greatly appreciated. > > Warmly, andrewH > > > -- > View this message in context: http://r.789695.n4.nabble.com/Returning-the-name-of-an-object-passed- > directly-or-from-a-list-by-lapply-tp3816798p3816798.html > Sent from the R help mailing list archive at Nabble.com. > > ______________________________________________ > 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.
andrewH
2011-Sep-16 23:27 UTC
[R] Returning the name of an object passed directly or from a list by lapply
Dear Bill-- Wow. This is very clever and I learned a lot from it. I've never seen the ...() trick before, and on a Google code search, I could not find anyone else who had used it. And I've never used the "..." feature, which, BTW, though mentioned in every intro to R text, has no help page I can find. <grrr> Your function is still not doing what I am trying to do, doubtless because I was not clear enough in the question I pose At the bottom of this message I have posted a copy of my testing function, and a few objects to test it on. Its details are unimportant and not very interesting, but note that all of its important outputs are in the form of side effects. What I would like to be able to do is this: f(fun, <n variable names>) and get back this: fun(variable#1) fun(variable#2) ... fun(variable#n) Attempting to copy some of your techniques, I came up with this: evaluate <- function(fun, ...){ unevaluatedArgs <- substitute(...) for (i in 1:length(deparse(unevaluatedArgs))) fun(deparse(unevaluatedArgs)[i]) invisible(TRUE) } As applied to my test data, it works on the first variable (but gets the variable name wrong) and ignores the remainder of the list, e.g.:> evaluate(testX, H.char, H.vec, H.df, H.mat)################### testX( deparse(unevaluatedArgs)[i] ): Class= character Type= character Mode= character Summary: Length Class Mode 1 character character Structure: chr "H.char" On the other hand, this almost works: evaluate <- function(fun, ...){ evaluatedArgs <- list(...) for (i in 1:length(evaluatedArgs)) fun(evaluatedArgs[i]) invisible(TRUE) } The only thing it does not do is get the name of the passed object right. That seems like it ought to be a small problem, but as you pointed out, the names are not in the list. (BTW, I don't understand dropping the names as a design choice for the list() function. If you use list() to make a list out of four symbols for objects, wouldn't it be better to make the text of the symbols the default names for those objects? That would solve this problem nicely.) [s]ubstitute seems to drop all but the first variable passed by "...". Thanks so much for your thoughtful help. andrewH testX <- function(objectX, bar=TRUE) { # A useful diagnostic function object.name <- deparse(substitute(objectX)) if(bar) cat("##################################\n"); cat("testX(", object.name, "): "); cat(" Class=", class(objectX)); cat(" Type=", typeof(objectX)); cat(" Mode=", mode(objectX), "\n"); cat("Summary:\n"); print(summary(objectX)) cat("Structure:\n"); str(objectX); if (is.factor(objectX)) {cat("Levels: ", levels(objectX), "\n"); cat("Length: ", length(objectX), "\n")} invisible(object.name) } ## Define 4 test variables: H.char, H.vec, H.df, H.mat H.char <- letters[1:10] H.vec <- c(1:10) H.df <- { # Makes a test data set A.df with 2-, 3-, & 4-factor sorting variables, making 24 # combinations, & a 4th variable with a unique data value for each combination. # No random component. year.2 <- factor( rep(1:2, each=12) ) cohort.3 <- factor( rep(rep(1:3,each=4),2) ) race.4 <- factor( rep(1:4, 6) ) D1 <- as.numeric(as.character(year.2))*1.1 + as.numeric(as.character(cohort.3))*1.01+ as.numeric(as.character(race.4))*1.001 data.frame(year.2,cohort.3,race.4,D1) } H.mat <-matrix(1:16, 4, 4) ## End of test variables -- View this message in context: http://r.789695.n4.nabble.com/Returning-the-name-of-an-object-passed-directly-or-from-a-list-by-lapply-tp3816798p3819378.html Sent from the R help mailing list archive at Nabble.com.
Possibly Parallel Threads
- Using str() in a function.
- Consistently printing the name of an object passed to a function; & a data-auditing question
- Replacing slot of S4 class in method of S4 class?
- help with smbmount and permissions
- function input as variable name (deparse/quote/paste) ??