Moving columns within a data.frame() without retyping
Is there a method for moving a column from one position in a data.frame to the next - without typing an entirely new data.frame()
For example:
a <- b <- c <- d <- e <- f <- g <- 1:100
df <- data.frame(a,b,c,d,e,f,g)
Now let's say I wanted "g" in front of "a"
I could retype it, as
df <- data.frame(g,a,b,c,d,e,f)
But is there not a quicker way? (Imagine 1500+ columns)
The subset
function has a nice select
argument that gives a convenient way to select ranges of columns by name:
df <- subset(df, select=c(g,a:f))
I wrote this function recently called moveme
. It's designed to work on vectors, with the intent of shuffling column orders around.
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)
}
myVec
}
Usage is simple. Try these out:
moveme(names(df), "g first")
moveme(names(df), "g first; a last; e before c")
Of course, using it to reorder the columns in your data.frame
is straightforward:
df[moveme(names(df), "g first")]
And for data.table
s (moves by reference, no copy) :
setcolorder(dt, moveme(names(dt), "g first"))
The basic options are:
- first
- last
- before
- after
Compounded moves are separated by a semicolon.
Here is one way to do it:
> col_idx <- grep("g", names(df))
> df <- df[, c(col_idx, (1:ncol(df))[-col_idx])]
> names(df)
[1] "g" "a" "b" "c" "d" "e" "f"