Re: [Rd] relist, an inverse operator to unlist
Hi Gabor, Can you suggest some examples of how your proposal could be used? Reshape never returns a vector. Cheers, Andrew On Tue, May 22, 2007 at 07:36:56PM -0400, Gabor Grothendieck wrote: One additional idea. I wonder if reshape might be promoted to a generic and relist made into methods for it. The unlisted version of an object would be the long version and the original version of the list would be the wide version. This would consolidate the two concepts together and make it easier to use since the user could leverage his knowledge of how reshape works to lists where it would work analogously. Essentially reshape(myList, direction = long) would be similar to unlist but would add the attributes need to reverse the procedure and reshape(myList, direction = wide) would perform the inversion. I am not sure if the reshape package has any bearing here as well. On 5/22/07, Andrew Clausen [EMAIL PROTECTED] wrote: Hi Seth, On Mon, May 21, 2007 at 05:15:10PM -0700, Seth Falcon wrote: I will also add that the notion of a default argument on a generic function seems a bit odd to me. If an argument is available for dispatch, I just don't see what sense it makes to have a default. In those cases, the default should be handled by the method that has a signature with said argument matching the missing class. What often does make sense is to define a generic function where some argument are not available for dispatch. For example: setGeneric(foo, signature=flesh, function(flesh, skeleton=attr(flesh, skeleton) standardGeneric(foo))) That's an excellent suggestion. Thanks! However, I had to set the signature to c(numeric, missing) rather than just numeric. I have uploaded a new version here: http://www.econ.upenn.edu/~clausen/computing/relist.R Cheers, Andrew __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] relist, an inverse operator to unlist
# returns list(a1 = 1, a2 = 2, b = 3) with an attribute # reshapeLong containing skeleton (existing reshape also uses # reshapeWide and reshapeLong attributes) L - list(a = 1:2, b = 3) long - reshape(L, direction = long) # returns original list but with an attribute reshapeWide reshape(long, direction = wide) In the last case there a new optional skeleton argument would be added. On 5/23/07, Andrew Clausen [EMAIL PROTECTED] wrote: Hi Gabor, Can you suggest some examples of how your proposal could be used? Reshape never returns a vector. Cheers, Andrew On Tue, May 22, 2007 at 07:36:56PM -0400, Gabor Grothendieck wrote: One additional idea. I wonder if reshape might be promoted to a generic and relist made into methods for it. The unlisted version of an object would be the long version and the original version of the list would be the wide version. This would consolidate the two concepts together and make it easier to use since the user could leverage his knowledge of how reshape works to lists where it would work analogously. Essentially reshape(myList, direction = long) would be similar to unlist but would add the attributes need to reverse the procedure and reshape(myList, direction = wide) would perform the inversion. I am not sure if the reshape package has any bearing here as well. On 5/22/07, Andrew Clausen [EMAIL PROTECTED] wrote: Hi Seth, On Mon, May 21, 2007 at 05:15:10PM -0700, Seth Falcon wrote: I will also add that the notion of a default argument on a generic function seems a bit odd to me. If an argument is available for dispatch, I just don't see what sense it makes to have a default. In those cases, the default should be handled by the method that has a signature with said argument matching the missing class. What often does make sense is to define a generic function where some argument are not available for dispatch. For example: setGeneric(foo, signature=flesh, function(flesh, skeleton=attr(flesh, skeleton) standardGeneric(foo))) That's an excellent suggestion. Thanks! However, I had to set the signature to c(numeric, missing) rather than just numeric. I have uploaded a new version here: http://www.econ.upenn.edu/~clausen/computing/relist.R Cheers, Andrew __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] relist, an inverse operator to unlist
Andrew Clausen [EMAIL PROTECTED] writes: Hi Seth, On Mon, May 21, 2007 at 05:15:10PM -0700, Seth Falcon wrote: I will also add that the notion of a default argument on a generic function seems a bit odd to me. If an argument is available for dispatch, I just don't see what sense it makes to have a default. In those cases, the default should be handled by the method that has a signature with said argument matching the missing class. What often does make sense is to define a generic function where some argument are not available for dispatch. For example: setGeneric(foo, signature=flesh, function(flesh, skeleton=attr(flesh, skeleton) standardGeneric(foo))) That's an excellent suggestion. Thanks! However, I had to set the signature to c(numeric, missing) rather than just numeric. I have uploaded a new version here: http://www.econ.upenn.edu/~clausen/computing/relist.R I misunderstood. You aren't using S4 classes/methods at all and so I don't actually see how my comments could have been helpful in any way. relist seems like a really odd solution to me, but based on the discussion I guess it has its use cases. Best, + seth -- Seth Falcon | Computational Biology | Fred Hutchinson Cancer Research Center http://bioconductor.org __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] relist, an inverse operator to unlist
On 5/23/07, Seth Falcon [EMAIL PROTECTED] wrote: Andrew Clausen [EMAIL PROTECTED] writes: Hi Seth, On Mon, May 21, 2007 at 05:15:10PM -0700, Seth Falcon wrote: I will also add that the notion of a default argument on a generic function seems a bit odd to me. If an argument is available for dispatch, I just don't see what sense it makes to have a default. In those cases, the default should be handled by the method that has a signature with said argument matching the missing class. What often does make sense is to define a generic function where some argument are not available for dispatch. For example: setGeneric(foo, signature=flesh, function(flesh, skeleton=attr(flesh, skeleton) standardGeneric(foo))) That's an excellent suggestion. Thanks! However, I had to set the signature to c(numeric, missing) rather than just numeric. I have uploaded a new version here: http://www.econ.upenn.edu/~clausen/computing/relist.R I misunderstood. You aren't using S4 classes/methods at all and so I don't actually see how my comments could have been helpful in any way. relist seems like a really odd solution to me, but based on the discussion I guess it has its use cases. You didn't misunderstand but there was an offline discussion pointing out that one primary use is in the inner loop of an optimization so it should be made as efficient as possible and it was changed with that in mind. __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] relist, an inverse operator to unlist
GaGr == Gabor Grothendieck [EMAIL PROTECTED] on Wed, 23 May 2007 08:56:50 -0400 writes: GaGr On 5/23/07, Seth Falcon [EMAIL PROTECTED] wrote: Andrew Clausen [EMAIL PROTECTED] writes: Hi Seth, On Mon, May 21, 2007 at 05:15:10PM -0700, Seth Falcon wrote: I will also add that the notion of a default argument on a generic function seems a bit odd to me. If an argument is available for dispatch, I just don't see what sense it makes to have a default. In those cases, the default should be handled by the method that has a signature with said argument matching the missing class. What often does make sense is to define a generic function where some argument are not available for dispatch. For example: setGeneric(foo, signature=flesh, function(flesh, skeleton=attr(flesh, skeleton) standardGeneric(foo))) That's an excellent suggestion. Thanks! However, I had to set the signature to c(numeric, missing) rather than just numeric. I have uploaded a new version here: http://www.econ.upenn.edu/~clausen/computing/relist.R I misunderstood. You aren't using S4 classes/methods at all and so I don't actually see how my comments could have been helpful in any way. relist seems like a really odd solution to me, but based on the discussion I guess it has its use cases. GaGr You didn't misunderstand but there was an offline GaGr discussion pointing out that one primary use is in the GaGr inner loop of an optimization so it should be made as GaGr efficient as possible and it was changed with that in GaGr mind. Thank you Gabor for that explanation. (I had wondered, too, and was glad that Andrew had dropped S4 generics seemingly by himself ;-)) Re your proposal of mixing this into reshape(): I think it's a nice and didactly helpful idea to point out the similarity in concepts between reshape() and relist(). However, I wouldn't like to make reshape() generic in this sense: As Andrew has mentioned as well, I think the two topics of data.frame (/matrix) reshaping and list - vector transformation seem too much different... Martin __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] relist, an inverse operator to unlist
On 5/23/07, Martin Maechler [EMAIL PROTECTED] wrote: GaGr == Gabor Grothendieck [EMAIL PROTECTED] on Wed, 23 May 2007 08:56:50 -0400 writes: GaGr On 5/23/07, Seth Falcon [EMAIL PROTECTED] wrote: Andrew Clausen [EMAIL PROTECTED] writes: Hi Seth, On Mon, May 21, 2007 at 05:15:10PM -0700, Seth Falcon wrote: I will also add that the notion of a default argument on a generic function seems a bit odd to me. If an argument is available for dispatch, I just don't see what sense it makes to have a default. In those cases, the default should be handled by the method that has a signature with said argument matching the missing class. What often does make sense is to define a generic function where some argument are not available for dispatch. For example: setGeneric(foo, signature=flesh, function(flesh, skeleton=attr(flesh, skeleton) standardGeneric(foo))) That's an excellent suggestion. Thanks! However, I had to set the signature to c(numeric, missing) rather than just numeric. I have uploaded a new version here: http://www.econ.upenn.edu/~clausen/computing/relist.R I misunderstood. You aren't using S4 classes/methods at all and so I don't actually see how my comments could have been helpful in any way. relist seems like a really odd solution to me, but based on the discussion I guess it has its use cases. GaGr You didn't misunderstand but there was an offline GaGr discussion pointing out that one primary use is in the GaGr inner loop of an optimization so it should be made as GaGr efficient as possible and it was changed with that in GaGr mind. Thank you Gabor for that explanation. (I had wondered, too, and was glad that Andrew had dropped S4 generics seemingly by himself ;-)) Re your proposal of mixing this into reshape(): I think it's a nice and didactly helpful idea to point out the similarity in concepts between reshape() and relist(). However, I wouldn't like to make reshape() generic in this sense: As Andrew has mentioned as well, I think the two topics of data.frame (/matrix) reshaping and list - vector transformation seem too much different... Martin Another possibility is to call it reshapeList instead of relist or reshape and the argument list made similar to reshape to keep the analogy as to reshape as close as possible to leverage the R user's knowledge of reshape. However, I am not so sure it really is different. Both reshape and relist involve flattening of structures and then reconstructing them back to the original. This seems very similar to me. __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] relist, an inverse operator to unlist
On 5/23/07, Gabor Grothendieck [EMAIL PROTECTED] wrote: On 5/23/07, Martin Maechler [EMAIL PROTECTED] wrote: GaGr == Gabor Grothendieck [EMAIL PROTECTED] on Wed, 23 May 2007 08:56:50 -0400 writes: GaGr On 5/23/07, Seth Falcon [EMAIL PROTECTED] wrote: Andrew Clausen [EMAIL PROTECTED] writes: Hi Seth, On Mon, May 21, 2007 at 05:15:10PM -0700, Seth Falcon wrote: I will also add that the notion of a default argument on a generic function seems a bit odd to me. If an argument is available for dispatch, I just don't see what sense it makes to have a default. In those cases, the default should be handled by the method that has a signature with said argument matching the missing class. What often does make sense is to define a generic function where some argument are not available for dispatch. For example: setGeneric(foo, signature=flesh, function(flesh, skeleton=attr(flesh, skeleton) standardGeneric(foo))) That's an excellent suggestion. Thanks! However, I had to set the signature to c(numeric, missing) rather than just numeric. I have uploaded a new version here: http://www.econ.upenn.edu/~clausen/computing/relist.R I misunderstood. You aren't using S4 classes/methods at all and so I don't actually see how my comments could have been helpful in any way. relist seems like a really odd solution to me, but based on the discussion I guess it has its use cases. GaGr You didn't misunderstand but there was an offline GaGr discussion pointing out that one primary use is in the GaGr inner loop of an optimization so it should be made as GaGr efficient as possible and it was changed with that in GaGr mind. Thank you Gabor for that explanation. (I had wondered, too, and was glad that Andrew had dropped S4 generics seemingly by himself ;-)) Re your proposal of mixing this into reshape(): I think it's a nice and didactly helpful idea to point out the similarity in concepts between reshape() and relist(). However, I wouldn't like to make reshape() generic in this sense: As Andrew has mentioned as well, I think the two topics of data.frame (/matrix) reshaping and list - vector transformation seem too much different... Martin Another possibility is to call it reshapeList instead of relist or reshape and the argument list made similar to reshape to keep the analogy as to reshape as close as possible to leverage the R user's knowledge of reshape. However, I am not so sure it really is different. Both reshape and relist involve flattening of structures and then reconstructing them back to the original. This seems very similar to me. The cast and melt operators in reshape are already generic, if you wanted to hook onto those instead. Hadley __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] relist, an inverse operator to unlist
On 5/23/07, hadley wickham [EMAIL PROTECTED] wrote: On 5/23/07, Gabor Grothendieck [EMAIL PROTECTED] wrote: On 5/23/07, Martin Maechler [EMAIL PROTECTED] wrote: GaGr == Gabor Grothendieck [EMAIL PROTECTED] on Wed, 23 May 2007 08:56:50 -0400 writes: GaGr On 5/23/07, Seth Falcon [EMAIL PROTECTED] wrote: Andrew Clausen [EMAIL PROTECTED] writes: Hi Seth, On Mon, May 21, 2007 at 05:15:10PM -0700, Seth Falcon wrote: I will also add that the notion of a default argument on a generic function seems a bit odd to me. If an argument is available for dispatch, I just don't see what sense it makes to have a default. In those cases, the default should be handled by the method that has a signature with said argument matching the missing class. What often does make sense is to define a generic function where some argument are not available for dispatch. For example: setGeneric(foo, signature=flesh, function(flesh, skeleton=attr(flesh, skeleton) standardGeneric(foo))) That's an excellent suggestion. Thanks! However, I had to set the signature to c(numeric, missing) rather than just numeric. I have uploaded a new version here: http://www.econ.upenn.edu/~clausen/computing/relist.R I misunderstood. You aren't using S4 classes/methods at all and so I don't actually see how my comments could have been helpful in any way. relist seems like a really odd solution to me, but based on the discussion I guess it has its use cases. GaGr You didn't misunderstand but there was an offline GaGr discussion pointing out that one primary use is in the GaGr inner loop of an optimization so it should be made as GaGr efficient as possible and it was changed with that in GaGr mind. Thank you Gabor for that explanation. (I had wondered, too, and was glad that Andrew had dropped S4 generics seemingly by himself ;-)) Re your proposal of mixing this into reshape(): I think it's a nice and didactly helpful idea to point out the similarity in concepts between reshape() and relist(). However, I wouldn't like to make reshape() generic in this sense: As Andrew has mentioned as well, I think the two topics of data.frame (/matrix) reshaping and list - vector transformation seem too much different... Martin Another possibility is to call it reshapeList instead of relist or reshape and the argument list made similar to reshape to keep the analogy as to reshape as close as possible to leverage the R user's knowledge of reshape. However, I am not so sure it really is different. Both reshape and relist involve flattening of structures and then reconstructing them back to the original. This seems very similar to me. The cast and melt operators in reshape are already generic, if you wanted to hook onto those instead. Hadley If that were done then it would probably make more sense to add it to the reshape package rather than the core of R. __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] relist, an inverse operator to unlist
Hi Seth, On Mon, May 21, 2007 at 05:15:10PM -0700, Seth Falcon wrote: I will also add that the notion of a default argument on a generic function seems a bit odd to me. If an argument is available for dispatch, I just don't see what sense it makes to have a default. In those cases, the default should be handled by the method that has a signature with said argument matching the missing class. What often does make sense is to define a generic function where some argument are not available for dispatch. For example: setGeneric(foo, signature=flesh, function(flesh, skeleton=attr(flesh, skeleton) standardGeneric(foo))) That's an excellent suggestion. Thanks! However, I had to set the signature to c(numeric, missing) rather than just numeric. I have uploaded a new version here: http://www.econ.upenn.edu/~clausen/computing/relist.R Cheers, Andrew __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] relist, an inverse operator to unlist
AndrewC == Andrew Clausen [EMAIL PROTECTED] on Tue, 22 May 2007 07:51:54 -0400 writes: AndrewC Hi Seth, AndrewC On Mon, May 21, 2007 at 05:15:10PM -0700, Seth Falcon wrote: I will also add that the notion of a default argument on a generic function seems a bit odd to me. If an argument is available for dispatch, I just don't see what sense it makes to have a default. In those cases, the default should be handled by the method that has a signature with said argument matching the missing class. What often does make sense is to define a generic function where some argument are not available for dispatch. For example: setGeneric(foo, signature=flesh, function(flesh, skeleton=attr(flesh, skeleton) standardGeneric(foo))) AndrewC That's an excellent suggestion. Thanks! However, I had to set the signature AndrewC to c(numeric, missing) rather than just numeric. AndrewC I have uploaded a new version here: AndrewC http://www.econ.upenn.edu/~clausen/computing/relist.R This looks good from far. I won't have time to do anything more about it for the next few days. Please remind me (in private) about it if you don't hear back within one week. Martin AndrewC Cheers, AndrewC Andrew __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] relist, an inverse operator to unlist
One additional idea. I wonder if reshape might be promoted to a generic and relist made into methods for it. The unlisted version of an object would be the long version and the original version of the list would be the wide version. This would consolidate the two concepts together and make it easier to use since the user could leverage his knowledge of how reshape works to lists where it would work analogously. Essentially reshape(myList, direction = long) would be similar to unlist but would add the attributes need to reverse the procedure and reshape(myList, direction = wide) would perform the inversion. I am not sure if the reshape package has any bearing here as well. On 5/22/07, Andrew Clausen [EMAIL PROTECTED] wrote: Hi Seth, On Mon, May 21, 2007 at 05:15:10PM -0700, Seth Falcon wrote: I will also add that the notion of a default argument on a generic function seems a bit odd to me. If an argument is available for dispatch, I just don't see what sense it makes to have a default. In those cases, the default should be handled by the method that has a signature with said argument matching the missing class. What often does make sense is to define a generic function where some argument are not available for dispatch. For example: setGeneric(foo, signature=flesh, function(flesh, skeleton=attr(flesh, skeleton) standardGeneric(foo))) That's an excellent suggestion. Thanks! However, I had to set the signature to c(numeric, missing) rather than just numeric. I have uploaded a new version here: http://www.econ.upenn.edu/~clausen/computing/relist.R Cheers, Andrew __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] relist, an inverse operator to unlist
Hi Andrew, Andrew Clausen [EMAIL PROTECTED] writes: For reasons I can't explain, the code I posted worked in my session, but didn't work when I started a fresh one. standardGeneric() seems to get confused by defaults for missing arguments. It looks for a missing method with this code: relist - function(flesh, skeleton=attr(flesh, skeleton)) { standardGeneric(relist) } This looks very odd to me. If you are creating an S4 generic function, why are you not calling setGeneric? Or has that part of the code simply been omitted from your post? I will also add that the notion of a default argument on a generic function seems a bit odd to me. If an argument is available for dispatch, I just don't see what sense it makes to have a default. In those cases, the default should be handled by the method that has a signature with said argument matching the missing class. What often does make sense is to define a generic function where some argument are not available for dispatch. For example: setGeneric(foo, signature=flesh, function(flesh, skeleton=attr(flesh, skeleton) standardGeneric(foo))) + seth -- Seth Falcon | Computational Biology | Fred Hutchinson Cancer Research Center http://bioconductor.org __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] relist, an inverse operator to unlist
Hi all, I've written a new version of relist that includes the suggestions from Gabor and Martin: http://www.econ.upenn.edu/~clausen/computing/relist.R The leading example now looks like this: initial.param - list(mean=c(0, 1), vcov=cbind(c(1, 1), c(1, 0))) initial.param - as.relistable(initial.param) ll - function(param.vector) { param - relist(initial.param) -sum(dnorm(x, mean=param$mean, vcov=param$vcov, log=TRUE)) # note: dnorm doesn't do vcov... but I hope you get the point } optim(unlist(initial.param), ll) One thing that concerns me is that relist() needs to count how many items are in a structued object. In this version, it does that by repeatedly calling length(unlist(obj)) which is quite inefficient (O(n^2) time, where n is the depth of the structure). Is there a clean way of making this faster? I suppose relist() could return attach a length attribute to the object it returns. Apart from that, I suppose I should do these things before inclusion: * write some documentation (including pointers in unlist's docs) * write more relist methods (eg for character) What's the usual process? Email a patch to [EMAIL PROTECTED] Cheers, Andrew On Mon, May 14, 2007 at 09:53:31AM +0200, Martin Maechler wrote: Nice ideas, Gabor and Andrew. While I agree with Andrew that such a utility makes for nicer and considerably better maintainable code in examples like his, and I do like to provide inverse operator functions in R whenever sensible, OTOH, we have strived to keep R's base package as lean and clean as possible, so I think this had to go to utils. One further small proposal: I'd use class name relistable since that's what the object of this class are and hence as.relistable(). What do other R-develers think? Martin GaGr == Gabor Grothendieck [EMAIL PROTECTED] on Mon, 14 May 2007 02:54:22 -0400 writes: GaGr unlist would not attach a skeleton to every vector it GaGr returns, only the relist method of unlist would. GaGr That way just that method needs to be added and no GaGr changes to unlist itself are needed. GaGr Before applying unlist to an object you would coerce GaGr the object to class relist to force the relist GaGr method of unlist to be invoked. GaGr Here is an outline of the code: GaGr as.relist - function(x) { GaGr if (!inherits(x, relist)) class(x) - c(relist, class(x)) GaGr x GaGr } GaGr unlist.relist - function(x, ...) { GaGr y - x GaGr cl - class(y) GaGr class(y) - cl[- grep(relist, cl)] GaGr z - unlist(y) GaGr attr(z, relist) - y GaGr as.relist(z) GaGr } GaGr relist - function(x, skeleton = attr(x, relist)) { GaGr # simpler version of relist so test can be executed GaGr skeleton GaGr } GaGr # test GaGr x - list(a = 1:2, b = 3) GaGr class(as.relist(x)) GaGr unlist(as.relist(x)) GaGr relist(unlist(as.relist(x))) GaGr On 5/14/07, Andrew Clausen [EMAIL PROTECTED] wrote: Hi GaGr, Thanks for the interesting suggestion. I must confess I got lost -- is it something like this? * unlist() could attach skeleton to every vector it returns. * relist() could then use the skeleton attached to the vector to reconstruct the object. The interface might be relist - function(flesh, skeleton=attributes(flesh)$skeleton) For example: par - list(mean=c(0, 0), vcov(rbind(c(1, 1), c(1, 1 vector.for.optim - unlist(par) print(attributes(vector.optim)$skeleton)# the skeleton is stored! converted.back.again - relist(par) Some concerns: * the metadata might get lost in some applications -- although it seems to work fine with optim(). But, if we provide both interfaces (where skeleton=flesh$skeleton is the default), then there should be no problem. * would there be any bad side-effects of changing the existing unlist interface? I suppose an option like save.skeleton could be added to unlist. I expect there would be some objections to enabling this as default behaviour, as it would significantly increase the storage requirements of the output. Cheers, Andrew On Sun, May 13, 2007 at 07:02:37PM -0400, GaGr Grothendieck wrote: I suggest you define a relist class and then define an unlist method for it which stores the skeleton as an attribute. Then one would not have to specify skeleton in the relist command so relist(unlist(relist(x))) === x 1. relist(x) is the same as x except it gets an additional class relist. 2. unlist(relist(x)) invokes the relist method of unlist on relist(x) returning another relist object
Re: [Rd] relist, an inverse operator to unlist
Hi all, For reasons I can't explain, the code I posted worked in my session, but didn't work when I started a fresh one. standardGeneric() seems to get confused by defaults for missing arguments. It looks for a missing method with this code: relist - function(flesh, skeleton=attr(flesh, skeleton)) { standardGeneric(relist) } I uploaded yet another new version that adds a wrapper that seems to resolve standardGeneric()'s confusion like this: relist - function(flesh, skeleton=attr(flesh, skeleton)) { # need a wrapper, since standardGeneric gets confused by # default arguments. f - function(flesh, skeleton) standardGeneric(relist) f(flesh, skeleton) } Cheers, Andrew __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] relist, an inverse operator to unlist
unlist would not attach a skeleton to every vector it returns, only the relist method of unlist would. That way just that method needs to be added and no changes to unlist itself are needed. Before applying unlist to an object you would coerce the object to class relist to force the relist method of unlist to be invoked. Here is an outline of the code: as.relist - function(x) { if (!inherits(x, relist)) class(x) - c(relist, class(x)) x } unlist.relist - function(x, ...) { y - x cl - class(y) class(y) - cl[- grep(relist, cl)] z - unlist(y) attr(z, relist) - y as.relist(z) } relist - function(x, skeleton = attr(x, relist)) { # simpler version of relist so test can be executed skeleton } # test x - list(a = 1:2, b = 3) class(as.relist(x)) unlist(as.relist(x)) relist(unlist(as.relist(x))) On 5/14/07, Andrew Clausen [EMAIL PROTECTED] wrote: Hi Gabor, Thanks for the interesting suggestion. I must confess I got lost -- is it something like this? * unlist() could attach skeleton to every vector it returns. * relist() could then use the skeleton attached to the vector to reconstruct the object. The interface might be relist - function(flesh, skeleton=attributes(flesh)$skeleton) For example: par - list(mean=c(0, 0), vcov(rbind(c(1, 1), c(1, 1 vector.for.optim - unlist(par) print(attributes(vector.optim)$skeleton)# the skeleton is stored! converted.back.again - relist(par) Some concerns: * the metadata might get lost in some applications -- although it seems to work fine with optim(). But, if we provide both interfaces (where skeleton=flesh$skeleton is the default), then there should be no problem. * would there be any bad side-effects of changing the existing unlist interface? I suppose an option like save.skeleton could be added to unlist. I expect there would be some objections to enabling this as default behaviour, as it would significantly increase the storage requirements of the output. Cheers, Andrew On Sun, May 13, 2007 at 07:02:37PM -0400, Gabor Grothendieck wrote: I suggest you define a relist class and then define an unlist method for it which stores the skeleton as an attribute. Then one would not have to specify skeleton in the relist command so relist(unlist(relist(x))) === x 1. relist(x) is the same as x except it gets an additional class relist. 2. unlist(relist(x)) invokes the relist method of unlist on relist(x) returning another relist object 3. relist(unlist(relist(x))) then recreates relist(x) On 5/13/07, Andrew Clausen [EMAIL PROTECTED] wrote: Hi all, I wrote a function called relist, which is an inverse to the existing unlist function: http://www.econ.upenn.edu/~clausen/computing/relist.R Some functions need many parameters, which are most easily represented in complex structures. Unfortunately, many mathematical functions in R, including optim, nlm, and grad can only operate on functions whose domain is a vector. R has a function to convert complex objects into a vector representation. This file provides an inverse operation called unlist to convert vectors back to the convenient structural representation. Together, these functions allow structured functions to have simple mathematical interfaces. For example, a likelihood function for a multivariate normal model needs a variance-covariance matrix and a mean vector. It would be most convenient to represent it as a list containing a vector and a matrix. A typical parameter might look like list(mean=c(0, 1), vcov=cbind(c(1, 1), c(1, 0))) However, optim can't operate on functions that take lists as input; it only likes vectors. The solution is conversion: initial.param - list(mean=c(0, 1), vcov=cbind(c(1, 1), c(1, 0))) ll - function(param.vector) { param - relist(initial.param, param.vector) -sum(dnorm(x, mean=param$mean, vcov=param$vcov, log=TRUE)) # note: dnorm doesn't do vcov... but I hope you get the point } optim(unlist(initial.param), ll) relist takes two parameters: skeleton and flesh. Skeleton is a sample object that has the right shape but the wrong content. flesh is a vector with the right content but the wrong shape. Invoking relist(skeleton, flesh) will put the content of flesh on the skeleton. As long as skeleton has the right shape, it should be a precise inverse of unlist. These equalities hold: relist(skeleton, unlist(x)) == x unlist(relist(skeleton, y)) == y Is there any easy way to do this without my new relist function? Is there any interest in including this in R's base package? (Or anywhere else?) Any comments on the implementation? Cheers, Andrew
Re: [Rd] relist, an inverse operator to unlist
Nice ideas, Gabor and Andrew. While I agree with Andrew that such a utility makes for nicer and considerably better maintainable code in examples like his, and I do like to provide inverse operator functions in R whenever sensible, OTOH, we have strived to keep R's base package as lean and clean as possible, so I think this had to go to utils. One further small proposal: I'd use class name relistable since that's what the object of this class are and hence as.relistable(). What do other R-develers think? Martin GaGr == Gabor Grothendieck [EMAIL PROTECTED] on Mon, 14 May 2007 02:54:22 -0400 writes: GaGr unlist would not attach a skeleton to every vector it GaGr returns, only the relist method of unlist would. GaGr That way just that method needs to be added and no GaGr changes to unlist itself are needed. GaGr Before applying unlist to an object you would coerce GaGr the object to class relist to force the relist GaGr method of unlist to be invoked. GaGr Here is an outline of the code: GaGr as.relist - function(x) { GaGr if (!inherits(x, relist)) class(x) - c(relist, class(x)) GaGr x GaGr } GaGr unlist.relist - function(x, ...) { GaGr y - x GaGr cl - class(y) GaGr class(y) - cl[- grep(relist, cl)] GaGr z - unlist(y) GaGr attr(z, relist) - y GaGr as.relist(z) GaGr } GaGr relist - function(x, skeleton = attr(x, relist)) { GaGr # simpler version of relist so test can be executed GaGr skeleton GaGr } GaGr # test GaGr x - list(a = 1:2, b = 3) GaGr class(as.relist(x)) GaGr unlist(as.relist(x)) GaGr relist(unlist(as.relist(x))) GaGr On 5/14/07, Andrew Clausen [EMAIL PROTECTED] wrote: Hi GaGr, Thanks for the interesting suggestion. I must confess I got lost -- is it something like this? * unlist() could attach skeleton to every vector it returns. * relist() could then use the skeleton attached to the vector to reconstruct the object. The interface might be relist - function(flesh, skeleton=attributes(flesh)$skeleton) For example: par - list(mean=c(0, 0), vcov(rbind(c(1, 1), c(1, 1 vector.for.optim - unlist(par) print(attributes(vector.optim)$skeleton)# the skeleton is stored! converted.back.again - relist(par) Some concerns: * the metadata might get lost in some applications -- although it seems to work fine with optim(). But, if we provide both interfaces (where skeleton=flesh$skeleton is the default), then there should be no problem. * would there be any bad side-effects of changing the existing unlist interface? I suppose an option like save.skeleton could be added to unlist. I expect there would be some objections to enabling this as default behaviour, as it would significantly increase the storage requirements of the output. Cheers, Andrew On Sun, May 13, 2007 at 07:02:37PM -0400, GaGr Grothendieck wrote: I suggest you define a relist class and then define an unlist method for it which stores the skeleton as an attribute. Then one would not have to specify skeleton in the relist command so relist(unlist(relist(x))) === x 1. relist(x) is the same as x except it gets an additional class relist. 2. unlist(relist(x)) invokes the relist method of unlist on relist(x) returning another relist object 3. relist(unlist(relist(x))) then recreates relist(x) On 5/13/07, Andrew Clausen [EMAIL PROTECTED] wrote: Hi all, I wrote a function called relist, which is an inverse to the existing unlist function: http://www.econ.upenn.edu/~clausen/computing/relist.R Some functions need many parameters, which are most easily represented in complex structures. Unfortunately, many mathematical functions in R, including optim, nlm, and grad can only operate on functions whose domain is a vector. R has a function to convert complex objects into a vector representation. This file provides an inverse operation called unlist to convert vectors back to the convenient structural representation. Together, these functions allow structured functions to have simple mathematical interfaces. For example, a likelihood function for a multivariate normal model needs a variance-covariance matrix and a mean vector. It would be most convenient to represent it as a list containing a vector and a matrix. A typical parameter might look like list(mean=c(0, 1), vcov=cbind(c(1, 1), c(1, 0))) However, optim can't operate on functions that take lists as input; it only likes vectors. The solution is conversion: initial.param -
Re: [Rd] relist, an inverse operator to unlist
On Sun, May 13, 2007 at 01:29:11PM -0400, Andrew Clausen wrote: R has a function to convert complex objects into a vector representation. This file provides an inverse operation called unlist to convert vectors back to the convenient structural representation. Oops. I meant to say: R has a function to convert complex objects into a vector representation called unlist. This file provides an inverse operation called relist to convert vectors back to the convenient structural representation. __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] relist, an inverse operator to unlist
I suggest you define a relist class and then define an unlist method for it which stores the skeleton as an attribute. Then one would not have to specify skeleton in the relist command so relist(unlist(relist(x))) === x 1. relist(x) is the same as x except it gets an additional class relist. 2. unlist(relist(x)) invokes the relist method of unlist on relist(x) returning another relist object 3. relist(unlist(relist(x))) then recreates relist(x) On 5/13/07, Andrew Clausen [EMAIL PROTECTED] wrote: Hi all, I wrote a function called relist, which is an inverse to the existing unlist function: http://www.econ.upenn.edu/~clausen/computing/relist.R Some functions need many parameters, which are most easily represented in complex structures. Unfortunately, many mathematical functions in R, including optim, nlm, and grad can only operate on functions whose domain is a vector. R has a function to convert complex objects into a vector representation. This file provides an inverse operation called unlist to convert vectors back to the convenient structural representation. Together, these functions allow structured functions to have simple mathematical interfaces. For example, a likelihood function for a multivariate normal model needs a variance-covariance matrix and a mean vector. It would be most convenient to represent it as a list containing a vector and a matrix. A typical parameter might look like list(mean=c(0, 1), vcov=cbind(c(1, 1), c(1, 0))) However, optim can't operate on functions that take lists as input; it only likes vectors. The solution is conversion: initial.param - list(mean=c(0, 1), vcov=cbind(c(1, 1), c(1, 0))) ll - function(param.vector) { param - relist(initial.param, param.vector) -sum(dnorm(x, mean=param$mean, vcov=param$vcov, log=TRUE)) # note: dnorm doesn't do vcov... but I hope you get the point } optim(unlist(initial.param), ll) relist takes two parameters: skeleton and flesh. Skeleton is a sample object that has the right shape but the wrong content. flesh is a vector with the right content but the wrong shape. Invoking relist(skeleton, flesh) will put the content of flesh on the skeleton. As long as skeleton has the right shape, it should be a precise inverse of unlist. These equalities hold: relist(skeleton, unlist(x)) == x unlist(relist(skeleton, y)) == y Is there any easy way to do this without my new relist function? Is there any interest in including this in R's base package? (Or anywhere else?) Any comments on the implementation? Cheers, Andrew __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel