4

I have the following code,

z <- data.frame(a=sample.int(10),b=sample.int(10),c=sample.int(10))
letter <- c("a","c","b") # this will be used as the argument to a function
vec <- unlist(lapply(1:length(letter), 
              function(x) cat(paste("z[[letter[",x,"]]],",sep=""))))
vec[length(vec)] <- paste("z[[letter[",length(vec),"]]]",sep="")

Consequently:

> vec    
[1] "z[[letter[1]]]," "z[[letter[2]]]," "z[[letter[3]]]" 

I want to use vec to order the rows of dataframe z, using the code below,

z.sort <- z[with(z, order(???)),]

How can I get the character vector vec to be evaluated as the arguments to order? Is there a better way of doing this bearing in mind that letter, which is used to form vec will be an argument to a function?

Desired output would be:

    a  b  c
5   1  1  9
10  2 10  2
1   3  7  1
9   4  2  5
8   5  8  6
2   6  4  3
4   7  9 10
3   8  3  8
6   9  5  7
7  10  6  4

or as dput output:

structure(list(a = 1:10, b = c(1L, 10L, 7L, 2L, 8L, 4L, 9L, 3L, 5L, 6L), c = c(9L, 2L, 1L, 5L, 6L, 3L, 10L, 8L, 7L, 4L)), .Names = c("a", "b", "c"), row.names = c(5L, 10L, 1L, 9L, 8L, 2L, 4L, 3L, 6L, 7L), class = "data.frame")
Kaleb
  • 1,022
  • 1
  • 15
  • 26
  • It may be helpful if you provide a what the output should look like. – Tyler Rinker Apr 19 '12 at 16:17
  • You should probably be moving that ??? argument to the right side of the comma, at least if you _are_ interested in re-ordering columns. – IRTFM Apr 19 '12 at 16:18

2 Answers2

4

Here's what you want (with different random data):

> z[do.call(order, z[,letter]),]
    a  b  c
5   1  2  1
4   2  4  8
1   3  3  9
6   4  6  3
8   5  8  5
10  6  1  4
2   7  5  7
3   8 10  2
9   9  7  6
7  10  9 10

do.call lets us send a list to a function as its arguments, so we can just reorder the columns of z and send them to order using do.call, as a data.frame is just a special kind of list.

Works with no problem in a function:

my.reorder <- function(dat, cols) { dat[do.call(order, dat[,cols]),] }
Aaron left Stack Overflow
  • 36,704
  • 7
  • 77
  • 142
0

A little more clarification about what your doing would help a lot, but a few thoughts...

in your sapply call you can simplify dramatically by using:

vec <- sapply(letter, function(x) paste('z[["',x,'"]]',sep=''))

the cat step is unnecessary unless you're trying to see the output as well as assign it... but you'd be better served there with a two line function that uses print. you can get the sorting you're talking about by using eval(parse(text=...))

z[order(eval(parse(text=vec[1])),]

and getting each sorting out as a list:

lapply(vec, function(x) z[order(eval(parse(text=x))),])

But... if sorting your data.frame by the each column specified in letter is the goal:

lapply(letter, function(x) z[order(z[[x]]),])

gives you the same output as all the fiddly steps above. Using something like eval(parse(text=...)) often means you're doing something silly and should rethink your steps since there very well could be a more straightforward solution.

Justin
  • 42,475
  • 9
  • 93
  • 111