An R function like "order" from Stata

A while ago, there was a question on Stackoverflow, Is there an equivalent R function to Stata ‘order’ command?. There isn’t really, and for the most part, you don’t really need one, but I decided that, for fun, I would write one anyway.

Instead of operating directly on the data.frames, I decided to just work on an input vector, which can be, for example, names(mydf). This makes the function more flexible—the output can be used with setcolorder() from the “data.table” package, for instance, for more memory efficient shuffling of columns.

Here’s the function:

moveme <- function(invec, movecommand) {
  movecommand <- lapply(strsplit(strsplit(movecommand, ";")[[1]], ",|\\s+"),
                        function(x) x[x != ""])
  movelist <- lapply(movecommand, function(x) {
    Where <- x[which(x %in% c("before", "after", "first", "last")):length(x)]
    ToMove <- setdiff(x, Where)
    list(ToMove, Where)

  myVec <- invec

  for (i in seq_along(movelist)) {
    temp <- setdiff(myVec, movelist[[i]][[1]])
    A <- movelist[[i]][[2]][1]
    if (A %in% c("before", "after")) {
      ba <- movelist[[i]][[2]][2]
      if (A == "before") {
        after <- match(ba, temp)-1
      } else if (A == "after") {
        after <- match(ba, temp)
    } else if (A == "first") {
      after <- 0
    } else if (A == "last") {
      after <- length(myVec)
    myVec <- append(temp, values = movelist[[i]][[1]], after = after)

Usage is simple:

myvec <- letters[1:10]
moveme(myvec, "a last; b, e, g before d; c first; h after j")
#  [1] "c" "b" "e" "g" "d" "f" "i" "j" "h" "a"

Thus, assuming that you wanted to reorder the columns of a data.frame named “mydf”, you would use:

mydf[moveme(names(mydf), "your move command")]

Similarly, if you wanted to reorder the columns of a data.table named “DT”, you would use:

setcolorder(DT, moveme(names(mydf), "your move command"))

All in all, it was pretty fun to implement the function in a “natural language” way. Looking at the order command from Stata, there are a couple of features that I have not addressed in this function. Perhaps I’ll add them some other day.

For now, it is a part of the “mrdwabmisc” package, until it finds a more appropriate home.

comments powered by Disqus