[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