Dear R community, I am using function 'within' in R.2.9.1 to add variables to an existing data.frame. This works wonderful, except for one minor point: The new variables are added to the data in reverse order. For example: x <- data.frame(a = 1:3, b = 4:6) y <- within(x, { c = a^2 d = b^2 e = c+d } ) gives a b e d c 1 1 4 17 16 1 2 2 5 29 25 4 3 3 6 45 36 9 Just what I want; except that I would prefer the columns to be in order a,b,c,d,e instead. I could use transform ("transform(x, c=a^2, d=b^2, e=c+d)"), which preserves the specified order of variables, but that won't work here because unfortunately it doesn't find object 'd' (same with "within(x, {e = c+d; d = b^2; c = a^2})", by the way). Of course in my toy example I can easily do something like y[, c(1:2,5:3)] afterwards, but I'd like to ask if maybe there is a simple way to make 'within' preserve the order of specified variables (or maybe someone can shed light on why this is not possible?). Thanks, Heinrich.
Try this: transform(transform(x, c = a ^ 2, d = b ^2), e = c + d) On Wed, Sep 2, 2009 at 10:27 AM, RINNER Heinrich < HEINRICH.RINNER@tirol.gv.at> wrote:> Dear R community, > > I am using function 'within' in R.2.9.1 to add variables to an existing > data.frame. This works wonderful, except for one minor point: The new > variables are added to the data in reverse order. > > For example: > x <- data.frame(a = 1:3, b = 4:6) > y <- within(x, { > c = a^2 > d = b^2 > e = c+d > } > ) > gives > a b e d c > 1 1 4 17 16 1 > 2 2 5 29 25 4 > 3 3 6 45 36 9 > > Just what I want; except that I would prefer the columns to be in order > a,b,c,d,e instead. > > I could use transform ("transform(x, c=a^2, d=b^2, e=c+d)"), which > preserves the specified order of variables, but that won't work here because > unfortunately it doesn't find object 'd' (same with "within(x, {e = c+d; d > b^2; c = a^2})", by the way). > > Of course in my toy example I can easily do something like y[, c(1:2,5:3)] > afterwards, but I'd like to ask if maybe there is a simple way to make > 'within' preserve the order of specified variables (or maybe someone can > shed light on why this is not possible?). > > Thanks, > Heinrich. > > ______________________________________________ > R-help@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. >-- Henrique Dallazuanna Curitiba-Paraná-Brasil 25° 25' 40" S 49° 16' 22" O [[alternative HTML version deleted]]
On 9/2/2009 9:27 AM, RINNER Heinrich wrote:> Dear R community, > > I am using function 'within' in R.2.9.1 to add variables to an existing data.frame. This works wonderful, except for one minor point: The new variables are added to the data in reverse order. > > For example: > x <- data.frame(a = 1:3, b = 4:6) > y <- within(x, { > c = a^2 > d = b^2 > e = c+d > } > ) > gives > a b e d c > 1 1 4 17 16 1 > 2 2 5 29 25 4 > 3 3 6 45 36 9 > > Just what I want; except that I would prefer the columns to be in order a,b,c,d,e instead. > > I could use transform ("transform(x, c=a^2, d=b^2, e=c+d)"), which preserves the specified order of variables, but that won't work here because unfortunately it doesn't find object 'd' (same with "within(x, {e = c+d; d = b^2; c = a^2})", by the way). > > Of course in my toy example I can easily do something like y[, c(1:2,5:3)] afterwards, but I'd like to ask if maybe there is a simple way to make 'within' preserve the order of specified variables (or maybe someone can shed light on why this is not possible?).Environments have no defined order, so you should not expect the order of evaluations which create new variables to produce them in a reproducible order. To get the order you want, declare it from the beginning when you create the data.frame. Or if x came from somewhere else, you could do this by adding the new columns first, then modifying them: x <- data.frame(a = 1:3, b = 4:6) # original creation x <- data.frame(x, c=1,d=1,e=1) # add some new columns y <- within(x, { # modify them c = a^2 d = b^2 e = c+d } ) Duncan Murdoch
Heinrich, You could create your own function mywithin() by inserting a couple of rev()'s in within.data.frame(). In within.data.frame(), replace the two commented lines with those immediately following: mywithin <- function (data, expr, ...) { parent <- parent.frame() # e <- evalq(environment(), data, parent) e <- evalq(environment(), rev(data), parent) eval(substitute(expr), e) # l <- as.list(e) l <- rev(as.list(e)) l <- l[!sapply(l, is.null)] nD <- length(del <- setdiff(names(data), (nl <- names(l)))) data[nl] <- l if (nD) data[del] <- if (nD == 1) NULL else vector("list", nD) data } Peter Ehlers RINNER Heinrich wrote:> Dear R community, > > I am using function 'within' in R.2.9.1 to add variables to an existing data.frame. This works wonderful, except for one minor point: The new variables are added to the data in reverse order. > > For example: > x <- data.frame(a = 1:3, b = 4:6) > y <- within(x, { > c = a^2 > d = b^2 > e = c+d > } > ) > gives > a b e d c > 1 1 4 17 16 1 > 2 2 5 29 25 4 > 3 3 6 45 36 9 > > Just what I want; except that I would prefer the columns to be in order a,b,c,d,e instead. > > I could use transform ("transform(x, c=a^2, d=b^2, e=c+d)"), which preserves the specified order of variables, but that won't work here because unfortunately it doesn't find object 'd' (same with "within(x, {e = c+d; d = b^2; c = a^2})", by the way). > > Of course in my toy example I can easily do something like y[, c(1:2,5:3)] afterwards, but I'd like to ask if maybe there is a simple way to make 'within' preserve the order of specified variables (or maybe someone can shed light on why this is not possible?). > > Thanks, > Heinrich. > > ______________________________________________ > 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. > >
On Wed, Sep 2, 2009 at 9:27 AM, RINNER Heinrich<HEINRICH.RINNER at tirol.gv.at> wrote:> Dear R community, > > I am using function 'within' in R.2.9.1 to add variables to an existing data.frame. This works wonderful, except for one minor point: The new variables are added to the data in reverse order. > > For example: > x <- data.frame(a = 1:3, b = 4:6) > y <- within(x, { > ? ? c = a^2 > ? ? d = b^2 > ? ? e = c+d > ? ? } > ) > gives > ?a b ?e ?d c > 1 1 4 17 16 1 > 2 2 5 29 25 4 > 3 3 6 45 36 9 > > Just what I want; except that I would prefer the columns to be in order a,b,c,d,e instead. > > I could use transform ("transform(x, c=a^2, d=b^2, e=c+d)"), which preserves the specified order of variables, but that won't work here because unfortunately it doesn't find object 'd' (same with "within(x, {e = c+d; d = b^2; c = a^2})", by the way).Such a constract is supported by my.transform posted here: http://tolstoy.newcastle.edu.au/R/e2/help/07/09/24707.html x <- data.frame(a = 1:3, b = 4:6) my.transform(x, c=a^2, d=b^2, e=c+d)