[R] Preserving lists in a function
Gabor Grothendieck
ggrothendieck at gmail.com
Sat Feb 27 12:29:11 CET 2010
Or use modifyList which is in the core of R.
On Sat, Feb 27, 2010 at 5:22 AM, baptiste auguie
<baptiste.auguie at googlemail.com> wrote:
> 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.
>>
>
> ______________________________________________
> 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