This sounds like a job for mapply, viz: > a.list <- list(a=cbind(1:4,rnorm(4)),b=cbind(4:1,rnorm(4))) > > plot.x.main.y <- function(x,y,...) plot( x, main=y, ... ) > mapply( plot.x.main.y , a.list, names(a.list) )
Chuck On Wed, 13 Jun 2007, Stephen Tucker wrote: > Hi Professor Ripley, > > Thanks for the response. I apologize, my examples were not too real (though > your solutions are indeed clever)... I was trying to ask more generally > whether the element name or index of 'listObj' could be obtained by the > user-function 'myfunction' when used in lapply(X=listObj,FUN=myfunction); > below I illustrate two cases in which I have come across this desire: > (1) In 'Example 1' I essentially take the list element and do some > transformations (optionally some number-crunching), and then plot it with the > element name of the list for the title. > (2) In 'Example 2' I want to read in data from the list element and write the > contents to a file; writing a header line only when operating on the first > element of the list. > > ## data specification > data1 <- "var1 var2 > -0.44 0.17 > 1.03 0.93 > 0.85 0.39" > data2 <- "var1 var2 > -0.16 0.97 > 0.93 0.23 > 0.80 0.42" > L <- list(data1=data1,data2=data2) > > ##=== Example 1 (want element name) === > ## function definition > plottingfunc <- function(i,x) { > plot(read.table(textConnection(x[[i]]),header=TRUE),main=names(x)[i]) > } > ## function application > par(mfrow=c(2,1)) > lapply(seq(along=L),plottingfunc,x=L) > > ##=== Example 2 (want element index) === > ## function definition > readwritefunc <- function(i,x,fout) { > data <- read.table(textConnection(x[[i]]),header=TRUE) > if(i==1) cat(paste(colnames(data),collapse=","),"\n",file=fout) > write.table(data,file=fout,sep=",",col=FALSE, > row=FALSE,quote=FALSE,append=TRUE) > } > ## function application > fout <- file("out.dat",open="w") > lapply(seq(along=L),readwritefunc,x=L,fout=fout) > close(fout) > > Since the above code works, I suppose this is more of a question of > aesthetics since I thought the spirit of lapply() was to operate on the > elements of a list and not its indices - I thought perhaps there is a way to > get the index number and element name from within the user-function. > > Also, I recall a lesson on 'loop avoidance' from an earlier version of MASS; > this was in the days of S-PLUS dominance and perhaps less applicable now to R > as you mentioned... But old habits die hard; my amygdala still invokes a fear > response at the thought of a loop... (and as of recently, I have been > infatuated with the notion of adhering, albeit loosely, to the 'functional > programming' paradigm which makes me doubly fearful of loops) > > Thanks and best regards, > > Stephen > > --- Prof Brian Ripley <[EMAIL PROTECTED]> wrote: > >> On Tue, 12 Jun 2007, Stephen Tucker wrote: >> >>> Hello everyone, >>> >>> I wonder if there is a way to pass the index or name of a list to a >>> user-specified function in lapply(). For instance, my desired effect is >>> something like the output of >>> >>>> L <- list(jack=4098,sape=4139) >>>> lapply(seq(along=L),function(i,x) if(i==1) "jack" else "sape",x=L) >>> [[1]] >>> [1] "jack" >>> >>> [[2]] >>> [1] "sape" >> >> as.list(names(L)) >> >>>> lapply(seq(along=L),function(i,x) if(names(x)[i]=="jack") 1 else 2,x=L) >>> [[1]] >>> [1] 1 >>> >>> [[2]] >>> [1] 2 >> >> as.list(seq_along(L)) >> >> lapply() can be faster than a for-loop, but usually not by much: its main >> advantage is clarity of code. >> >> I think we need a real-life example to see what you are trying to do. >> >>> But by passing L as the first argument of lapply(). I thought there was a >>> tangentially-related post on this mailing list in the past but I don't >> recall >>> that it was ever addressed directly (and I can't seem to find it now). >> The >>> examples above are perfectly good alternatives especially if I wrap each >> of >>> the lines in "names<-"() to return lists with appropriate names assigned, >> but >> >> Try something like >> >> L[] <- lapply(seq_along(L),function(i,x) if(i==1) "jack" else "sape",x=L) >> >>> it feels like I am essentially writing a FOR-LOOP - though I was >> surprised to >>> find that speed-wise, it doesn't seem to make much of a difference >> (unless I >>> have not selected a rigorous test): >>> >>>> N <- 10000 >>>> y <- runif(N) >>> ## looping through elements of y >>>> system.time(lapply(y, >>> + function(x) { >>> + set.seed(222) >>> + mean(rnorm(1e4,x,1)) >>> + })) >>> [1] 21.00 0.17 21.29 NA NA >>> ## looping through indices >>>> system.time(lapply(1:N, >>> + function(x,y) { >>> + set.seed(222) >>> + mean(rnorm(1e4,y[x],1)) >>> + },y=y)) >>> [1] 21.09 0.14 21.26 NA NA >>> >>> In Python, there are methods for Lists and Dictionaries called >> enumerate(), >>> and iteritems(), respectively. Example applications: >>> >>> ## a list >>> L = ['a','b','c'] >>> [x for x in enumerate(L)] >>> ## returns index of list along with the list element >>> [(0, 'a'), (1, 'b'), (2, 'c')] >>> >>> ## a dictionary >>> D = {'jack': 4098, 'sape': 4139} >>> [x for x in D.iteritems()] >>> ## returns element key (name) along with element contents >>> [('sape', 4139), ('jack', 4098)] >>> >>> And this is something of the effect I was looking for... >>> >>> Thanks to all, >>> >>> Stephen >>> >>> ______________________________________________ >>> R-help@stat.math.ethz.ch 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. >>> >> >> -- >> Brian D. Ripley, [EMAIL PROTECTED] >> Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ >> University of Oxford, Tel: +44 1865 272861 (self) >> 1 South Parks Road, +44 1865 272866 (PA) >> Oxford OX1 3TG, UK Fax: +44 1865 272595 >> > > ______________________________________________ > R-help@stat.math.ethz.ch 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. > Charles C. Berry (858) 534-2098 Dept of Family/Preventive Medicine E mailto:[EMAIL PROTECTED] UC San Diego http://famprevmed.ucsd.edu/faculty/cberry/ La Jolla, San Diego 92093-0901 ______________________________________________ R-help@stat.math.ethz.ch 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.