2

Say I have the following data frame:

df <- data.frame(x1 = c(2, 2, 2, 1),
                 x2 = c(3, 3, 2, 1),
                 let = c("B", "A", "A", "A"))
df
  x1 x2 let
1  2  3   B
2  2  3   A
3  2  2   A
4  1  1   A

If I want to order df by x1, then x2 then let, I do this:

df2 <- df[with(df, order(x1, x2, let)), ]
df2
  x1 x2 let
4  1  1   A
3  2  2   A
2  2  3   A
1  2  3   B

However, x1 and x2 have actually been saved as an id <- c("x1", "x2") vector earlier in the code, which I use for other purposes.

So my problem is that I want to reference id instead of x1 and x2 in my order function, but unfortunately anything like df[order(df[id], df$let), ] will result in a argument lengths differ error.

From what I can tell (and this has been addressed at another SO thread), the problem is that length(df[id]) == 2 and length(df$let) == 4.

I have been able to make it through this workaround:

df3 <- df[order(df[, id[1]], df[, id[2]], df[, "let"]), ]
df3
  x1 x2 let
4  1  1   A
3  2  2   A
2  2  3   A
1  2  3   B

But it looks ugly and depends on knowing the size of id.

Is there a more elegant solution to sorting my data frame by id then let?

Community
  • 1
  • 1
Waldir Leoncio
  • 10,853
  • 19
  • 77
  • 107
  • That works for `id`, but what about for `id` then `let` (I'll make the bottom of my post clearer)? – Waldir Leoncio Aug 13 '14 at 19:47
  • I'm still checking if it did the trick in my real case, but as far as the mock data goes, Works like a charm. Thanks a lot, Ananda, you're a job saver! – Waldir Leoncio Aug 13 '14 at 19:49

1 Answers1

3

I would suggest using do.call(order, ...) and combining id and "let" with c():

id <- c("x1", "x2")

df[do.call(order, df[c(id, "let")]), ]
#   x1 x2 let
# 4  1  1   A
# 3  2  2   A
# 2  2  3   A
# 1  2  3   B
A5C1D2H2I1M1N2O1R2T1
  • 190,393
  • 28
  • 405
  • 485