4

I wrote this tiny little wrapper around order, but I fear my implementation is lame. I huddle in the corner, waiting for the gods of R commands or algorithmic efficiency to smite my ergonomic keyboard :-(

set.seed(1001)

height <- rnorm(6, mean = 1, sd = 0.2)
weight <- rnorm(6, mean = 100, sd = 15)
id     <- 1:6

dd <- data.frame(id, height, weight)

# Here's the function I came up with
ReorderDataByColumn <- function(x, column) {
  ordered.indices <- order(x[ ,paste(column)])

  return(x[ordered.indices, ])
}

#And here are its results
> ReorderDataByColumn(dd, column = "height")
  id    height    weight
4  4 0.4986928  76.09430
5  5 0.8885377 104.53967
3  3 0.9629449  86.38809
2  2 0.9644905  90.65584
6  6 0.9712881 124.51589
1  1 1.4377296 116.37253

> ReorderDataByColumn(dd, column = "weight")
  id    height    weight
4  4 0.4986928  76.09430
3  3 0.9629449  86.38809
2  2 0.9644905  90.65584
5  5 0.8885377 104.53967
1  1 1.4377296 116.37253
6  6 0.9712881 124.51589
briandk
  • 6,749
  • 8
  • 36
  • 46

2 Answers2

4

I'm not into the smiting business for well-formed questions. And I thought the code was readable and sensible. If you wanted to tighten it up a bit you can drop the paste() operation by using "[[" and creating the index inside "[":

ReorderDataByColumn2 <- function(x, column) {
    return(x[ order( x[[column]]), ])
}

EDIT: Adding Hadley's suggestion (except I think you need do.call as well):

 ReorderDataByColumn2 <- function(x, column, desc=FALSE) {
    return(
      x[ do.call( order, x[ , column, drop=FALSE ]  ), ]
      ) }

You could add some error checking if you wanted:

ReorderDataByColumn2 <- function(x, column) {
    if(column %in% names(x)){return(x[ order( x[[column]]), ]) 
     }else{ cat("Column ", column, "not in dataframe ", deparse(substitute(x))) }
}
IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • I never knew about double bracketing "[[" like that. I thought that was just the indexing notation for lists. But it's also shorthand for evaluating an argument as a string? – briandk Jul 09 '11 at 16:41
  • It's not really shorthand ... it's the original method. "[[" evaluates its argument. It does have the disadvantage that it only accepts one argument, so if you were ordering by more than one column this will fail. – IRTFM Jul 09 '11 at 18:16
  • If you wanted to index more than one column you could do `x[, column, drop = F]` – hadley Jul 09 '11 at 21:27
2

See the arrange function in plyr:

library(plyr)
arrange(mtcars, cyl)
arrange(mtcars, desc(cyl))
arrange(mtcars, vs, am)

The definition of the function is pretty simple:

arrange <- function (df, ...) {
    ord <- eval(substitute(order(...)), df, parent.frame())
    unrowname(df[ord, ])
}

And it works on a very similar process to subset in base R.

hadley
  • 102,019
  • 32
  • 183
  • 245