What is the simplest way that one can swap the order of a selected subset of columns in a data frame in R. The answers I have seen (Is it possible to swap columns around in a data frame using R?) use all indices / column names for this. If one has, say, 100 columns and need either: 1) to swap column 99 with column 1, or 2) move column 99 before column 1 (but keeping column 1 now as column 2) the suggested approaches appear cumbersome. Funny there is no small package around for this (Wickham's "reshape" ?) - or can one suggest a simple code ?
Asked
Active
Viewed 309 times
-1
-
5`x <- x[, c(99, 1:98, 100)]` seems pretty simple to me. I can't think how it would be possible to instruct R as to which columns you're interested in moving without referring to them by name or index. – jbaums Oct 19 '14 at 08:53
-
Yes you are properly right, Thanks. Sure one need to instruct R somehow I just thought that a tool could be needed for more complicated cases (although I have no example at hand). – user3375672 Oct 19 '14 at 09:02
1 Answers
3
If you really want a shortcut for this, you could write a couple of simple functions, such as the following.
To swap the position of two columns:
swapcols <- function(x, col1, col2) {
if(is.character(col1)) col1 <- match(col1, colnames(x))
if(is.character(col2)) col2 <- match(col2, colnames(x))
if(any(is.na(c(col1, col2)))) stop("One or both columns don't exist.")
i <- seq_len(ncol(x))
i[col1] <- col2
i[col2] <- col1
x[, i]
}
To move a column from one position to another:
movecol <- function(x, col, to.pos) {
if(is.character(col)) col <- match(col, colnames(x))
if(is.na(col)) stop("Column doesn't exist.")
if(to.pos > ncol(x) | to.pos < 1) stop("Invalid position.")
x[, append(seq_len(ncol(x))[-col], col, to.pos - 1)]
}
And here are examples of each:
(m <- matrix(1:12, ncol=4, dimnames=list(NULL, letters[1:4])))
# a b c d
# [1,] 1 4 7 10
# [2,] 2 5 8 11
# [3,] 3 6 9 12
swapcols(m, col1=1, col2=3) # using column indices
# c b a d
# [1,] 7 4 1 10
# [2,] 8 5 2 11
# [3,] 9 6 3 12
swapcols(m, 'd', 'a') # or using column names
# d b c a
# [1,] 10 4 7 1
# [2,] 11 5 8 2
# [3,] 12 6 9 3
movecol(m, col='a', to.pos=2)
# b a c d
# [1,] 4 1 7 10
# [2,] 5 2 8 11
# [3,] 6 3 9 12

jbaums
- 27,115
- 5
- 79
- 119
-
1Doesn't handle this same user case, but still fun: http://news.mrdwab.com/2013/08/28/an-r-function-like-order-from-stata/ – A5C1D2H2I1M1N2O1R2T1 Oct 19 '14 at 10:13
-
-
-
1May be there is typo in the code. 4th line of movecol() should be: if(to > ncol(x) | to < 1) stop("Invalid position.") – KFB Oct 19 '14 at 10:26
-
@KFB sorry about that - I simplified the arg names but that one slipped through. :) – jbaums Oct 19 '14 at 10:32
-
1