Select the last n columns of data frame in R
Solution 1
You could use something like this:
move_to_start <- function(x, to_move) {
x[, c(to_move, setdiff(colnames(x), to_move))]
}
move_to_start(mydata2, c('A', 'B'))
# A B num1 num2
# 1 A B 1 36
# 2 A B 2 37
# 3 A B 3 38
# 4 A B 4 39
# 5 A B 5 40
Alternatively, if you want to move the last n
columns to the start:
move_to_start <- function(x, n) {
x[, c(tail(seq_len(ncol(x)), n), seq_len(ncol(x) - n))]
}
move_to_start(mydata2, 2)
# A B num1 num2
# 1 A B 1 36
# 2 A B 2 37
# 3 A B 3 38
# 4 A B 4 39
# 5 A B 5 40
Solution 2
The problem described doesn't match the title, and existing answers address the moving columns part, doesn't really explain how to select last N columns.
If you wanted to just select the last column in a matrix/data frame without knowing the column name:
mydata2[,ncol(mydata2)]
and if you want last n columns, try
mydata[,(ncol(mydata2)-n-1):ncol(mydata2)]
A little cumbersome, but works. Could write wrapper function if you plan to use it regularly.
Solution 3
Using the offset
argument in the last_col
function, inside select
, you can do that.
Below is an example considering the last two columns, and it in a more generic approach.
library(dplyr)
mydata <- mydata %>% select(last_col(offset=c(0,1)), everything())
n <- 2
mydata <- mydata %>% select(last_col(offset=0:(n-1), everything())
Solution 4
You can do a similar thing using the SOfun
package, available on GitHub.
library(SOfun)
foo <- moveMe(colnames(mydata2), "A, B before num1")
mydata2[, foo]
# A B num1 num2
#1 A B 1 36
#2 A B 2 37
#3 A B 3 38
#4 A B 4 39
#5 A B 5 40
You can move column names like this example from R Help.
x <- names(mtcars)
x
#[1] "mpg" "cyl" "disp" "hp" "drat" "wt" "qsec" "vs" "am" "gear" "carb"
moveMe(x, "hp first; cyl after drat; vs, am, gear before mpg; wt last")
#[1] "hp" "vs" "am" "gear" "mpg" "disp" "drat" "cyl" "qsec" "carb" "wt"
Solution 5
data frames are just lists, so you can rearrange them as you would any list:
newdata <- c(mydata[colNamesToStart],
mydata[-which(names(mydata) %in% colNamesToStart)])
Nancy
Updated on February 20, 2022Comments
-
Nancy about 2 years
Is there a way to systematically select the last columns of a data frame? I would like to be able to move the last columns to be the first columns, but maintain the order of the columns when they are moved. I need a way to do this that does not list all the columns using subset(data, select = c(all the columns listed in the new order)) because I will be using many different data frames.
Here's an example where I would like to move the last 2 columns to the front of the data frame. It works, but it's ugly.
A = rep("A", 5) B = rep("B", 5) num1 = c(1:5) num2 = c(36:40) mydata2 = data.frame(num1, num2, A, B) # Move A and B to the front of mydata2 mydata2_move = data.frame(A = mydata2$A, B = mydata2$B, mydata2[,1: (ncol(mydata2)-2)]) # A B num1 num2 #1 A B 1 36 #2 A B 2 37 #3 A B 3 38 #4 A B 4 39 #5 A B 5 40
Changing the number of columns in the original data frame causes issues. This works (see below), but the naming gets thrown off. Why do these two examples behave differently? Is there a better way to do this, and to generalize it?
mydata1_move = data.frame(A = mydata1$A, B = mydata1$B, mydata1[,1: (ncol(mydata1)-2)]) # A B mydata1...1..ncol.mydata1....2.. #1 A B 1 #2 A B 2 #3 A B 3 #4 A B 4 #5 A B 5
-
A5C1D2H2I1M1N2O1R2T1 over 9 yearsI'd say this is the most flexible approach :-) (I mean, I'm not biased or anything....)
-
jazzurro over 9 years@AnandaMahto Well, you have seen many SO posts and realised that there is need for this kind of flexible operation. I like the name of the function. :) Thanks for editing, by the way.
-
Adrien Joly almost 9 yearsnice, but that does not return a data.frame.
-
Leonardo over 4 yearsThat didn't work here. But the following did:
n <- ncol(mydata) ## find how many cols are in mydata
mydata2 <- select(mydata, last_col(offset=0:(n-1), everything()))
-
Charles Yan about 2 yearsI might be wrong, but I reckon it should be (ncol(mydata2)-n+1):ncol(mydata2)
-
PatrickT about 2 yearsBoth the answer here and Leonardo's suggestion work for me. But note that the columns are displayed in reverse order with the use of
offset=
-
Dave Gruenewald about 2 yearsLooks like
last_col
was introduced to the tidyselect package just 3 months after I initially answered. Updated above to useseq
withinlast_col
- which preserves original order of the lastn
columns