459

I know if I have a data frame with more than 1 column, then I can use

colnames(x) <- c("col1","col2")

to rename the columns. How to do this if it's just one column? Meaning a vector or data frame with only one column.

Example:

trSamp <- data.frame(sample(trainer$index, 10000))
head(trSamp )
#   sample.trainer.index..10000.
# 1                      5907862
# 2                      2181266
# 3                      7368504
# 4                      1949790
# 5                      3475174
# 6                      6062879

ncol(trSamp)
# [1] 1
class(trSamp)
# [1] "data.frame"
class(trSamp[1])
# [1] "data.frame"
class(trSamp[,1])
# [1] "numeric"
colnames(trSamp)[2] <- "newname2"
# Error in names(x) <- value : 
#   'names' attribute [2] must be the same length as the vector [1]
AndrewGB
  • 16,126
  • 5
  • 18
  • 49
screechOwl
  • 27,310
  • 61
  • 158
  • 267
  • 4
    @aix's solution will work for a 1-column data.frame. You're probably being confused by the `drop=TRUE` default argument to `[`, which causes a "1-column" object to be converted to a vector... and vectors don't have `colnames`. An example of what you tried would be very helpful. – Joshua Ulrich Sep 23 '11 at 16:31
  • 5
    it works if you use "colnames(x)[1] <- 'newname2'" – screechOwl Sep 23 '11 at 16:44

21 Answers21

767

This is a generalized way in which you do not have to remember the exact location of the variable:

# df = dataframe
# old.var.name = The name you don't like anymore
# new.var.name = The name you want to get

names(df)[names(df) == 'old.var.name'] <- 'new.var.name'

This code pretty much does the following:

  1. names(df) looks into all the names in the df
  2. [names(df) == old.var.name] extracts the variable name you want to check
  3. <- 'new.var.name' assigns the new variable name.
Blaszard
  • 30,954
  • 51
  • 153
  • 233
Side_0o_Effect
  • 7,771
  • 2
  • 12
  • 4
  • 7
    I'm also quite new with R, loved this solution! I've actually checked what it does, and I think it's worth specify that `[names(df) == old.var.name]` actually returns a vector with true/false values. So it has the potential to change multiple column names if, for example, regular expressions are used. – mikyatope Dec 11 '13 at 16:21
  • 3
    For regular expression results, use something like `names(df) = sub('pattern', 'replacement', names(df))`. Otherwise you'd be trying to set multiple columns to the same name. – We Are All Monica Sep 27 '14 at 20:09
  • 64
    Mixed feelings...in a perfect world, where perfect programming languages abound, would it really require this many keystrokes to change the name of a single column? I love R but sometimes I want to strangle it for these types of reasons. – tumultous_rooster Aug 15 '15 at 01:19
  • Other simple option in accordance to above solution is to simply refer to the column number of the file you want to change the name . That is : # 'Column#1' is the one you want to change the name in your data frame(df) so simply write : `names(df)[1] <- 'new.var.name` – Daniel Feb 06 '17 at 15:35
  • 8
    How there not a wrapper function for this in base? – ifly6 Sep 06 '18 at 17:03
  • 1
    How we all wish ! I do not know about now, but back then there was not any wrapper in base – Side_0o_Effect Sep 20 '18 at 11:07
  • Beware of the order of appearance when you are changing multiple columns at the same time (one line of code) use this solution. – Jia Gao Jul 09 '19 at 19:11
440
colnames(trSamp)[2] <- "newname2"

attempts to set the second column's name. Your object only has one column, so the command throws an error. This should be sufficient:

colnames(trSamp) <- "newname2"
Joshua Ulrich
  • 173,410
  • 32
  • 338
  • 418
  • 1
    .@JoshuaUlrich - This doesn't seem to work if the column name is something like `"A,B,C,X,Y,Z"` where I want to rename it to `Y` using `testData[379] <- "Y"`. – Chetan Arvind Patil Jan 17 '19 at 16:10
112
colnames(df)[colnames(df) == 'oldName'] <- 'newName'
zongshiwujie
  • 1,169
  • 1
  • 8
  • 8
  • 5
    I like this solution as you can reference the column name by name, as opposed to requiring to know which number column it is. Better for larger number features. – Cybernetic Aug 22 '14 at 17:18
  • 1
    I've got a small extension to the question and this answer. I have a dataframe with a column which has the letters _'snp'_ in it. I want to rename it to _'Marker'_. But I want to use a _regular expression_ to do so. Apparently the code I have is flawed: `colnames(GWASDATA_RAWSELECTION)[colnames(GWASDATA_RAWSELECTION)=="^snp$"] <- "Marker"`, because the column is not renamed. If I do `names(GWASDATA_RAWSELECTION)[names(GWASDATA_RAWSELECTION)=="snp"] <- "Marker"` it _is_ renamed. What am I missing? – Sander W. van der Laan Nov 29 '16 at 22:13
94

This is an old question, but it is worth noting that you can now use setnames from the data.table package.

library(data.table)

setnames(DF, "oldName", "newName")

# or since the data.frame in question is just one column: 
setnames(DF, "newName")

# And for reference's sake, in general (more than once column)
nms <- c("col1.name", "col2.name", etc...)
setnames(DF, nms)
Ricardo Saporta
  • 54,400
  • 17
  • 144
  • 178
64

This can also be done using Hadley's plyr package, and the rename function.

library(plyr) 
df <- data.frame(foo=rnorm(1000)) 
df <- rename(df,c('foo'='samples'))

You can rename by the name (without knowing the position) and perform multiple renames at once. After doing a merge, for example, you might end up with:

  letterid id.x id.y
1       70    2    1
2      116    6    5
3      116    6    4
4      116    6    3
5      766   14    9
6      766   14   13

Which you can then rename in one step using:

letters <- rename(letters,c("id.x" = "source", "id.y" = "target"))

  letterid source target
1       70      2      1
2      116      6      5
3      116      6      4
4      116      6      3
5      766     14      9
6      766     14     13
alexplanation
  • 1,468
  • 14
  • 18
56

I think the best way of renaming columns is by using the dplyr package like this:

require(dplyr)
df = rename(df, new_col01 = old_col01, new_col02 = old_col02, ...)

It works the same for renaming one or many columns in any dataset.

Rich Scriven
  • 97,041
  • 11
  • 181
  • 245
Luis Vazquez
  • 756
  • 6
  • 5
21

We might use dplyr::rename_at (though it's superseded) :

library(dplyr)
cars %>% rename_at("speed",~"new") %>% head     
cars %>% rename_at(vars(speed),~"new") %>% head
cars %>% rename_at(1,~"new") %>% head

#   new dist
# 1   4    2
# 2   4   10
# 3   7    4
# 4   7   22
# 5   8   16
# 6   9   10
  • works well in pipe chaines
  • convenient when names are stored in variables
  • works with a name or an column index
  • clear and compact
moodymudskipper
  • 46,417
  • 11
  • 121
  • 167
14

I like the next style for rename dataframe column names one by one.

colnames(df)[which(colnames(df) == 'old_colname')] <- 'new_colname'

where

which(colnames(df) == 'old_colname')

returns by the index of the specific column.

jshepherd
  • 900
  • 1
  • 9
  • 22
11

Let df be the dataframe you have with col names myDays and temp. If you want to rename "myDays" to "Date",

library(plyr)
rename(df,c("myDays" = "Date"))

or with pipe, you can

dfNew      <- df %>% 
  plyr::rename(c("myDays" = "Date"))
Ebby
  • 141
  • 1
  • 4
8

This is likely already out there, but I was playing with renaming fields while searching out a solution and tried this on a whim. Worked for my purposes.

Table1$FieldNewName <- Table1$FieldOldName
Table1$FieldOldName <- NULL

Edit begins here....

This works as well.

library(dplyr)
df <- dplyr::rename(df, c("oldColName" = "newColName"))
Scottieie
  • 304
  • 8
  • 14
  • To whoever marked me down, that is fine, but since I am obviously new to doing this, perhaps you could enlighten as to what was wrong with the answer. – Scottieie Feb 02 '17 at 02:56
  • There's nothing wrong with your answer, besides it not being a oneliner.. that was just a hostile SO user not having the courage to justify his tantrum. – count0 Mar 10 '17 at 19:12
  • Thanks @count0. It actually is meaningful to have some mana points or whatever to comment on a question, something I have been yet to be able to do. Follow up questions in some cases would be nice as I learn a new skillset. Again. TY. – Scottieie Mar 11 '17 at 21:12
  • 1
    we need to give all columns name to use this. – Arpit Sisodia Apr 02 '17 at 08:47
  • which package does the `rename` function come from? – Diego Mar 19 '20 at 00:40
  • @Diego - library is dplyr – Scottieie May 24 '23 at 19:54
7

You can use the rename.vars in the gdata package.

library(gdata)
df <- rename.vars(df, from = "oldname", to = "newname")

This is particularly useful where you have more than one variable name to change or you want to append or pre-pend some text to the variable names, then you can do something like:

df <- rename.vars(df, from = c("old1", "old2", "old3", 
         to = c("new1", "new2", "new3"))

For an example of appending text to a subset of variables names see: https://stackoverflow.com/a/28870000/180892

Community
  • 1
  • 1
Jeromy Anglim
  • 33,939
  • 30
  • 115
  • 173
7

Try:

colnames(x)[2] <- 'newname2'
NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • 8
    This is what threw the error that OP asked about (in his edit). It won't work, as the dataframe only has one column. –  Sep 23 '11 at 22:05
  • .@NPE - This doesn't seem to work if the column name is something like `"A,B,C,X,Y,Z"` where I want to rename it to `Y` using `testData[379] <- "Y"`. – Chetan Arvind Patil Jan 17 '19 at 16:10
4

You could also try 'upData' from 'Hmisc' package.

library(Hmisc)

trSamp = upData(trSamp, rename=c(sample.trainer.index..10000. = 'newname2'))

ansek
  • 443
  • 3
  • 17
  • Very nice! It's is also possible to rename more columns at once: trSamp = upData(trSamp, rename=c(sample.trainer.index..10000. = 'newname2, AnotherColumnName = 'RenameThisColumn')) – FraNut Jul 07 '16 at 13:11
3

The OP's question has been well and truly answered. However, here's a trick that may be useful in some situations: partial matching of the column name, irrespective of its position in a dataframe:

Partial matching on the name:

d <- data.frame(name1 = NA, Reported.Cases..WHO..2011. = NA, name3 = NA)
##   name1 Reported.Cases..WHO..2011. name3
## 1    NA                         NA    NA
names(d)[grepl("Reported", names(d))] <- "name2"
##   name1 name2 name3
## 1    NA    NA    NA

Another example: partial matching on the presence of "punctuation":

d <- data.frame(name1 = NA, Reported.Cases..WHO..2011. = NA, name3 = NA)
##   name1 Reported.Cases..WHO..2011. name3
## 1    NA                         NA    NA
names(d)[grepl("[[:punct:]]", names(d))] <- "name2"
##   name1 name2 name3
## 1    NA    NA    NA

These were examples I had to deal with today, I thought might be worth sharing.

PatrickT
  • 10,037
  • 9
  • 76
  • 111
3

If you know that your dataframe has only one column, you can use: names(trSamp) <- "newname2"

2

I would simply change a column name to the dataset with the new name I want with the following code: names(dataset)[index_value] <- "new_col_name"

1

I would simply add a new column to the data frame with the name I want and get the data for it from the existing column. like this:

dataf$value=dataf$Article1Order

then I remove the old column! like this:

dataf$Article1Order<-NULL

This code might seem silly! But it works perfectly...

Niloufar
  • 21
  • 3
1

I found colnames() argument easier https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/row%2Bcolnames

select some column from the data frame

df <- data.frame(df[, c( "hhid","b1005", "b1012_imp", "b3004a")])

and rename the selected column in order,

colnames(df) <- c("hhid", "income", "cost", "credit")

check the names and the values to be sure

names(df);head(df)
Johannes Konings
  • 188
  • 2
  • 10
Seyma Kalay
  • 2,037
  • 10
  • 22
0

We can use rename_with to rename columns with a function (stringr functions, for example).

Consider the following data df_1:

df_1 <- data.frame(
  x = replicate(n = 3, expr = rnorm(n = 3, mean = 10, sd = 1)), 
  y = sample(x = 1:2, size = 10, replace = TRUE)
)

names(df_1)

#[1] "x.1" "x.2" "x.3" "y" 

Rename all variables with dplyr::everything():

library(tidyverse)

df_1 %>% 
  rename_with(.data = ., .cols = everything(.), 
              .fn = str_replace, pattern = '.*', 
              replacement = str_c('var', seq_along(.), sep = '_')) %>% 
  names()

#[1] "var_1" "var_2" "var_3" "var_4"

Rename by name particle with some dplyr verbs (starts_with, ends_with, contains, matches, ...).

Example with . (x variables):

df_1 %>% 
  rename_with(.data = ., .cols = contains('.'), 
              .fn = str_replace, pattern = '.*', 
              replacement = str_c('var', seq_along(.), sep = '_')) %>% 
  names()

#[1] "var_1" "var_2" "var_3" "y"

Rename by class with many functions of class test, like is.integer, is.numeric, is.factor...

Example with is.integer (y):

df_1 %>% 
  rename_with(.data = ., .cols = is.integer, 
              .fn = str_replace, pattern = '.*', 
              replacement = str_c('var', seq_along(.), sep = '_')) %>% 
  names()

#[1] "x.1"   "x.2"   "x.3"   "var_1"

The warning:

Warning messages: 1: In stri_replace_first_regex(string, pattern, fix_replacement(replacement), : longer object length is not a multiple of shorter object length 2: In names[cols] <- .fn(names[cols], ...) : number of items to replace is not a multiple of replacement length

It is not relevant, as it is just an inconsistency of seq_along(.) with the replace function.

neves
  • 796
  • 2
  • 10
  • 36
0

I kept thinking about this and came up with the following function

renamecols <- function(df, oldnames, newnames) {

  #   _______________________________________
  #   Defenses                               ####
  stopifnot( exprs = {
    is.data.frame(df)
    length(oldnames) == length(newnames)
    # all(oldnames %in% names(df))
  }
  )

  #   ___________________________________________
  #   Computations                              ####
  df_names <- names(df)

  old_position <- which(oldnames %in% df_names)
  old_available <- oldnames[old_position]
  new_available <- newnames[old_position]

  tochange <- vector(length = length(old_available))

  for (i in seq_along(old_available)) {
    tochange[i] <- which(df_names %in% old_available[i])
  }

  names(df)[tochange] <- new_available

  return(df)

}

You can test it in big datasets and it is relatively fast. Of course, it won't be as fast as data.table::setnames(), but this is a useful solution for base R work.

The nice thing about this approach is that the new and old names can be in any order and the old names do not even need to be present in the data, they are just ignored. The only requirement is that there is direct correspondence between the old and the new names.

n        <- 3
l        <- as.list(1:(length(letters)*n))
nn       <- expand.grid(l = letters, n = 1:n)
names(l) <- paste0(nn$l, nn$n)
df       <- as.data.frame(l)

oldnames <- sample(names(df), floor(length(names(df))/3))
newnames <- paste0("new_", oldnames)

renamecols(df, oldnames, newnames) |> 
  names()
#>  [1] "new_a1" "b1"     "new_c1" "d1"     "new_e1" "f1"     "new_g1" "h1"    
#>  [9] "i1"     "j1"     "k1"     "new_l1" "new_m1" "n1"     "o1"     "p1"    
#> [17] "new_q1" "r1"     "s1"     "t1"     "u1"     "new_v1" "new_w1" "new_x1"
#> [25] "y1"     "z1"     "new_a2" "b2"     "c2"     "d2"     "e2"     "f2"    
#> [33] "new_g2" "h2"     "new_i2" "new_j2" "k2"     "l2"     "m2"     "n2"    
#> [41] "new_o2" "p2"     "q2"     "new_r2" "s2"     "t2"     "u2"     "new_v2"
#> [49] "w2"     "x2"     "y2"     "z2"     "a3"     "new_b3" "new_c3" "d3"    
#> [57] "new_e3" "f3"     "g3"     "h3"     "new_i3" "j3"     "k3"     "l3"    
#> [65] "m3"     "n3"     "o3"     "p3"     "new_q3" "r3"     "s3"     "new_t3"
#> [73] "new_u3" "new_v3" "new_w3" "x3"     "y3"     "z3"

Created on 2023-05-04 with reprex v2.0.2

-3
library(dplyr)
rename(data, de=de.y)
ABCD
  • 7,914
  • 9
  • 54
  • 90