[R] Preserving lists in a function
baptiste auguie
baptiste.auguie at googlemail.com
Sat Feb 27 11:22:10 CET 2010
Hi,
I think I would follow this approach too, using updatelist() from the
reshape package,
updatelist <- function (x, y)
{
common <- intersect(names(x), names(y))
x[common] <- y[common]
x
}
myfunction=function(list1=NULL, list2=NULL, list3=NULL){
list1=updatelist(list(variable1=1,
variable2=2,
variable3=3), list1)
list2=updatelist(list(variable1="variable1",
variable2="variable2",
variable3="variable3"), list2)
list3=updatelist(list(variable1="character",
variable2=24,
variable3=c(0.1,0.1,0.1,0.1),
variable4=TRUE), list3)
return(list(list1=list1,list2=list2,list3=list3))
}
Best regards,
baptiste
On 27 February 2010 01:51, Don MacQueen <macq at llnl.gov> wrote:
> Barry explained your first puzzle, but let me add some explanation and
> examples.
>
>
>> tmpfun <- function( a =3 ) {a}
>> tmpfun()
>
> [1] 3
>>
>> tmpfun(a='x')
>
> [1] "x"
>
> Inside the function, the value of the argument is whatever the user
> supplied. The default is replaced by what the user supplies. There is no
> mechanism for retaining the default structure and filling in any missing
> parts. R never preserves the defaults when the user supplies something other
> than the default.
>
> For example, and using your function,
>
>> myfunction(list1='x')
>
> $list1
> [1] "x"
>
> $list2
> $list2$variable1
> [1] "variable1"
>
> $list2$variable2
> [1] "variable2"
>
> $list2$variable3
> [1] "variable3"
>
>
> $list3
> $list3$variable1
> [1] "character"
>
> $list3$variable2
> [1] 24
>
> $list3$variable3
> [1] 0.1 0.1 0.1 0.1
>
> $list3$variable4
> [1] TRUE
>
>
>> myfunction(list1=data.frame(a=1:2, b=c('x','y')))
>
> $list1
> a b
> 1 1 x
> 2 2 y
>
> $list2
> $list2$variable1
> [1] "variable1"
>
> $list2$variable2
> [1] "variable2"
>
> $list2$variable3
> [1] "variable3"
>
>
> $list3
> $list3$variable1
> [1] "character"
>
> $list3$variable2
> [1] 24
>
> $list3$variable3
> [1] 0.1 0.1 0.1 0.1
>
> $list3$variable4
> [1] TRUE
>
> What you put in is what you get out.
>
> I don't know that I would deal with this the way Barry did. I would probably
> write code to examine the structure of what the user supplies, compare it to
> the required structure, and then fill in.
>
> myf <- function(l1, l2, l3) {
> if (missing(l1)) {
> ## user did not supply l1, so set it = to the default
> l1 <- list(v1=1, v2=2, v3=3)
> } else if (!is.list(l1)) {
> ## user must supply a list, if not, it's an error
> stop('l1 must be a list')
> } else {
> ## user has at least supplied a list
> ## now write code to check the names of the list that the user supplied
> ## make sure the names that the user supplied are valid, if not, stop()
> ## if the user supplied too few elements, fill in the missing ones
> ## if the user supplied too many elements stop()
> ## if the user supplied all the correct elements, with all the correct
> names, use what the user supplied
> }
>
> Looks complicated; maybe Barry's way is better...
>
> -Don
>
> At 5:56 PM -0500 2/26/10, Shang Gao wrote:
>>
>> Dear R users,
>>
>> A co-worker and I are writing a function to facilitate graph plotting in
>> R. The function makes use of a lot of lists in its defaults.
>>
>> However, we discovered that R does not necessarily preserve the defaults
>> if we were to input them in the form of list() when initializing the
>> function. For example, if you feed the function codes below into R:
>>
>> myfunction=function(
>> list1=list (variable1=1,
>> variable2=2,
>> variable3=3),
>>
>> list2=list (variable1="variable1",
>> variable2="variable2",
>> variable3="variable3"),
>>
>> list3=list (variable1="character",
>> variable2=24,
>> variable3=c(0.1,0.1,0.1,0.1),
>> variable4=TRUE))
>>
>> {return(list(list1=list1,list2=list2,list3=list3))}
>>
>> By definition, the values associated with each variable in the lists would
>> be the default unless the user impute a different value while executing the
>> function. But a problem arises when a variable in the list is left out
>> completely (not imputed at all). An example is shown below:
>>
>> myfunction( list1=list (variable1=1,
>> variable2=2), #variable 3 deliberately left out
>>
>> list2=list (variable1="variable1",
>> variable3="position changed",
>> variable2="variable2"),
>>
>> list3=list (variable1="character",
>> variable2=24,
>> variable4=FALSE)) #variable 3 deliberately left out
>>
>> #The outcome of the above execution is shown below:
>>
>> $list1
>> $list1$variable1
>> [1] 1
>>
>> $list1$variable2
>> [1] 2
>> #list1$variable3 is missing. Defaults in function not assigned in this
>> execution
>>
>> $list2
>> $list2$variable1
>> [1] "variable1"
>>
>> $list2$variable3
>> [1] "position changed"
>>
>> $list2$variable2
>> [1] "variable2"
>>
>>
>> $list3
>> $list3$variable1
>> [1] "character"
>>
>> $list3$variable2
>> [1] 24
>>
>> $list3$variable4
>> [1] FALSE
>> #list3$variable3 is missing. Defaults in function not assigned in this
>> execution
>>
>> We later realized that the problem lies in list() commands. Hence, we
>> tried to enforce the defaults on the list using these codes in the function
>> definition:
>>
>> myfunction.alternative=function(
>> list1=list (variable1=1,
>> variable2=2,
>> variable3=3),
>>
>> list2=list (variable1="variable1",
>> variable2="variable2",
>> variable3="variable3"),
>>
>> list3=list (variable1="character",
>> variable2=24,
>> variable3=c(0.1,0.1,0.1,0.1),
>> variable4=TRUE))
>> {
>> defaults=vector("list", 3)
>> names(defaults)=c("list1","list2","list3")
>> defaults$list1=list(variable1=1,
>> variable2=2,
>> variable3=3)
>> defaults$list2=list(variable1="variable1",
>> variable2="variable2",
>> variable3="variable3")
>> defaults$list3=list (variable1="character",
>> variable2=24,
>> variable3=c(0.1,0.1,0.1,0.1),
>> variable4=TRUE)
>> if(length(list1$variable1)==0){list1$variable1=defaults$list1$variable1}
>> if(length(list1$variable2)==0){list1$variable2=defaults$list1$variable2}
>> if(length(list1$variable3)==0){list1$variable3=defaults$list1$variable3}
>>
>> if(length(list2$variable1)==0){list2$variable1=defaults$list2$variable1}
>> if(length(list2$variable2)==0){list2$variable2=defaults$list2$variable2}
>> if(length(list2$variable3)==0){list2$variable3=defaults$list2$variable3}
>>
>> if(length(list3$variable1)==0){list3$variable1=defaults$list3$variable1}
>> if(length(list3$variable2)==0){list3$variable2=defaults$list3$variable2}
>> if(length(list3$variable3)==0){list3$variable3=defaults$list3$variable3}
>> if(length(list3$variable4)==0){list3$variable4=defaults$list3$variable4}
>>
>> return(list(list1=list1,list2=list2,list3=list3))}
>>
>> The outcome of execution the above function with the same commands
>> produces the results that we wanted:
>>>
>>> myfunction.alternative( list1=list (variable1=1,
>>
>> + variable2=2), #variable 3 deliberately left out
>> +
>> + list2=list (variable1="variable1",
>> + variable3="position changed",
>> + variable2="variable2"),
>> +
>> + list3=list (variable1="character",
>> + variable2=24,
>> + variable4=FALSE)) #variable 3 deliberately left
>> out
>> $list1
>> $list1$variable1
>> [1] 1
>>
>> $list1$variable2
>> [1] 2
>>
>> $list1$variable3
>> [1] 3
>> #list1$variable3 is assigned default despite being left out in the
>> execution command
>>
>>
>> $list2
>> $list2$variable1
>> [1] "variable1"
>>
>> $list2$variable3
>> [1] "position changed"
>>
>> $list2$variable2
>> [1] "variable2"
>>
>>
>> $list3
>> $list3$variable1
>> [1] "character"
>>
>> $list3$variable2
>> [1] 24
>>
>> $list3$variable4
>> [1] FALSE
>>
>> $list3$variable3
>> [1] 0.1 0.1 0.1 0.1
>> #list3$variable3 is assigned default despite being left out in the
>> execution command
>>
>> Even though the function works, as you can see, the codes that enforce the
>> defaults are very long and bulky. Such lengthy codes won't be efficient if
>> we have a write a function containing a large number of lists. We tried to
>> come up with ideas to try to shorten the codes, but so far none of them
>> prove to be effective.
>>
>> What would be your recommendation to deal with such situation? It would be
>> great if you would be able to help us our with this problem. We appreciate
>> your help tremendously.
>>
>> Thank you.
>>
>> Sincerely,
>> Shang
>>
>>
>> [[alternative HTML version deleted]]
>>
>> ______________________________________________
>> 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.
>
>
> --
> --------------------------------------
> Don MacQueen
> Environmental Protection Department
> Lawrence Livermore National Laboratory
> Livermore, CA, USA
> 925-423-1062
>
> ______________________________________________
> 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.
>
More information about the R-help
mailing list