113

I would like to have the last column of the data frame moved to the start (as first column). How can I do it in R?

My data.frame has about a thousand columns to changing the order wont to. I just want to pick one column and "move it to the start".

Henrik
  • 65,555
  • 14
  • 143
  • 159
ECII
  • 10,297
  • 18
  • 80
  • 121

10 Answers10

239

Dplyr's select() approach

Moving the last column to the start:

new_df <- df %>%
  select(last_column_name, everything())

This is also valid for any column and any quantity:

new_df <- df %>%
  select(col_5, col_8, everything())

Example using mtcars data frame:

head(mtcars, n = 2)
#                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
# Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
# Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4

# Last column is 'carb'
new_df <- mtcars %>% select(carb, everything())

head(new_df, n = 2)
#                   carb  mpg cyl disp  hp drat    wt  qsec vs am gear
# Mazda RX4            4 21.0   6  160 110 3.90 2.620 16.46  0  1    4
# Mazda RX4 Wag        4 21.0   6  160 110 3.90 2.875 17.02  0  1    4
marc_aragones
  • 4,344
  • 4
  • 26
  • 38
48

dplyr 1.0.0 now includes the relocate() function to reorder columns. The default behaviour is to move the named column(s) to the first position.

library(dplyr) # from version 1.0.0 

mtcars %>%
  relocate(carb) %>%
  head()

                  carb  mpg cyl disp  hp drat    wt  qsec vs am gear
Mazda RX4            4 21.0   6  160 110 3.90 2.620 16.46  0  1    4
Mazda RX4 Wag        4 21.0   6  160 110 3.90 2.875 17.02  0  1    4
Datsun 710           1 22.8   4  108  93 3.85 2.320 18.61  1  1    4
Hornet 4 Drive       1 21.4   6  258 110 3.08 3.215 19.44  1  0    3
Hornet Sportabout    2 18.7   8  360 175 3.15 3.440 17.02  0  0    3
Valiant              1 18.1   6  225 105 2.76 3.460 20.22  1  0    3

But other locations can be specifed with the .before or .after arguments:

mtcars %>%
  relocate(gear, carb, .before = cyl) %>%
  head()

                   mpg gear carb cyl disp  hp drat    wt  qsec vs am
Mazda RX4         21.0    4    4   6  160 110 3.90 2.620 16.46  0  1
Mazda RX4 Wag     21.0    4    4   6  160 110 3.90 2.875 17.02  0  1
Datsun 710        22.8    4    1   4  108  93 3.85 2.320 18.61  1  1
Hornet 4 Drive    21.4    3    1   6  258 110 3.08 3.215 19.44  1  0
Hornet Sportabout 18.7    3    2   8  360 175 3.15 3.440 17.02  0  0
Valiant           18.1    3    1   6  225 105 2.76 3.460 20.22  1  0
Ritchie Sacramento
  • 29,890
  • 4
  • 48
  • 56
42

You can change the order of columns by adressing them in the new order by choosing them explicitly with data[,c(ORDER YOU WANT THEM TO BE IN)]

If you just want the last column to be first use: data[,c(ncol(data),1:(ncol(data)-1))]

> head(cars)
  speed dist
1     4    2
2     4   10
3     7    4
4     7   22
5     8   16
6     9   10

> head(cars[,c(2,1)])
  dist speed
1    2     4
2   10     4
3    4     7
4   22     7
5   16     8
6   10     9
Rentrop
  • 20,979
  • 10
  • 72
  • 100
33
dataframe<-dataframe[,c(1000, 1:999)]

this will move your last column i.e. 1000th column to the first column.

Newbie
  • 389
  • 3
  • 9
28

I don't know if it's worth adding this as an answer or if a comment would be fine, but I wrote a function called moveme that lets you do what you want to do with the language you describe. You can find the function at this answer: https://stackoverflow.com/a/18540144/1270695

It works on the names of your data.frame and produces a character vector that you can use to reorder your columns:

mydf <- data.frame(matrix(1:12, ncol = 4))
mydf
moveme(names(mydf), "X4 first")
# [1] "X4" "X1" "X2" "X3"
moveme(names(mydf), "X4 first; X1 last")
# [1] "X4" "X2" "X3" "X1"

mydf[moveme(names(mydf), "X4 first")]
#   X4 X1 X2 X3
# 1 10  1  4  7
# 2 11  2  5  8
# 3 12  3  6  9

If you're shuffling things around like this, I suggest converting your data.frame to a data.table and using setcolorder (with my moveme function, if you wish) to make the change by reference.


In your question, you also mentioned "I just want to pick one column and move it to the start". If it's an arbitrary column, and not specifically the last one, you could also look at using setdiff.

Imagine you're working with the "mtcars" dataset and want to move the "am" column to the start.

x <- "am"
mtcars[c(x, setdiff(names(mtcars), x))]
Community
  • 1
  • 1
A5C1D2H2I1M1N2O1R2T1
  • 190,393
  • 28
  • 405
  • 485
27

If you want to move any named column to the first position, simply use:

df[,c(which(colnames(df)=="desired_colname"),which(colnames(df)!="desired_colname"))]
HT_079
  • 370
  • 3
  • 5
  • 5
    This is easily the best answer here – Neal Barsch Jan 31 '18 at 00:42
  • 1
    This doesn't seem to work when the named column is an ordered factor. – DLyons Aug 11 '19 at 19:48
  • This worked great for me. With a data.table it did not work directly, but could be used with `neworder <- c(which(colnames(df)=="id"),which(colnames(df)!="id"))` and then `setcolorder(df, neworder)` – Mark E. Jan 31 '21 at 23:49
5

A native R approach that works with any number of rows or columns to move the last column of a dataframe to the first column position:

df <- df[,c(ncol(df),1:ncol(df)-1)]

It can be used to move any column to the first column by replacing:

df <- df[,c(your_column_number_here,1:ncol(df)-1)]

If you don't know the column number, but know the column label name, do the following replacing "your_column_name_here":

columnNumber <- which(colnames(df)=="your_column_name_here")
df <- df[,c(columnNumber,1:ncol(df)-1)]
brapplecache
  • 51
  • 1
  • 1
  • For the any column scenario, I needed to change `1:ncol(df)-1)` to `which(colnames(df) != "your_column_name_here")` to get the remaining columns rather than always removing the last column, as suggested by @HT_079 below. – yodavid Feb 15 '21 at 11:57
5

There is also the data.table option with setcolorder():

library(data.table)
mtcars_copy <- copy(mtcars)
setDT(mtcars_copy)

# Move column "gear" in the first position
setcolorder(mtcars_copy, neworder = "gear")

head(mtcars_copy)

#    gear  mpg cyl disp  hp drat    wt  qsec vs am carb
# 1:    4 21.0   6  160 110 3.90 2.620 16.46  0  1    4
# 2:    4 21.0   6  160 110 3.90 2.875 17.02  0  1    4
# 3:    4 22.8   4  108  93 3.85 2.320 18.61  1  1    1
# 4:    3 21.4   6  258 110 3.08 3.215 19.44  1  0    1
# 5:    3 18.7   8  360 175 3.15 3.440 17.02  0  0    2
# 6:    3 18.1   6  225 105 2.76 3.460 20.22  1  0    1

If multiple columns, then mention the order in a vector:

setcolorder(mtcars_copy, neworder = c("vs", "carb"))

head(mtcars_copy)
#    vs carb gear  mpg cyl disp  hp drat    wt  qsec am
# 1:  0    4    4 21.0   6  160 110 3.90 2.620 16.46  1
# 2:  0    4    4 21.0   6  160 110 3.90 2.875 17.02  1
# 3:  1    1    4 22.8   4  108  93 3.85 2.320 18.61  1
# 4:  1    1    3 21.4   6  258 110 3.08 3.215 19.44  0
# 5:  0    2    3 18.7   8  360 175 3.15 3.440 17.02  0
# 6:  1    1    3 18.1   6  225 105 2.76 3.460 20.22  0
Valentin_Ștefan
  • 6,130
  • 2
  • 45
  • 68
3

Move any column from any position for the first position in your data

n <- which(colnames(df)=="column_need_move")
column_need_move <- df$column_need_to_move
df <- cbind(column_need_move, df[,-n])
Irina Max
  • 101
  • 1
  • 1
  • 5
3

If you want to create a new column and have it be the first column, use the .before=1 argument:

my_data <- my_data %>% mutate(newcol = a*b, .before=1)
DanY
  • 5,920
  • 1
  • 13
  • 33