How to rename specific variable of a data frame with setNames()?

Viewed 8568

To rename a specific variable I can do for instance

names(df1)[which(names(df1)  == "C")] <- "X"
> df1
  A B X
1 1 2 3

I wonder if this is also possible with setNames(), but without repeating the names I don't want to rename as in

df1 <- setNames(df1, c("A", "B", "X"))`

I've tried setNames(df1, c(rep(NA, 2), "X")) and setNames(df1[3], "X") but this won't work. The advantage I see in setNames() is that I can set names while doing other stuff in one step.

Data

df1 <- setNames(data.frame(matrix(1:3, 1)), LETTERS[1:3])
> df1
  A B C
1 1 2 3    
6 Answers

You can use replace,

setNames(df1, replace(names(df1), names(df1) == 'B', 'X'))
#  A X C
#1 1 2 3
setNames(df1, replace(names(df1), names(df1) == 'A', 'X'))
#  X B C
#1 1 2 3
setNames(df1, replace(names(df1), names(df1) == 'C', 'X'))
#  A B X
#1 1 2 3

You can do it using setnames from library(data.table)

library(data.table)

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

dplyr also has a special function for this:

dplyr::rename(df1, X = C)
#   A B X
# 1 1 2 3

Best I can do is this one, which doesn't seem any easier than using other methods. You could also write a function that would fit your needs..

df2 <- setNames(df1, c(colnames(df1)[1:2],"test"))
> df2
  A B test
1 1 2    3

Edit: to change other names (for example column B), we can define a custom function:

dfrename <- function(mydf, mycolumns=1:ncol(mydf), mynewnames=c(letters[1:mycolumns])) {
  if(!is.numeric(mycolumns)) {
    toreplace <- colnames(mydf) %in% mycolumns
  } else { 
    toreplace <- 1:ncol(mydf) %in% mycolumns
  }
  mycols <- colnames(mydf)
  mycols[toreplace] <- mynewnames
  res <- setNames(mydf, mycols)
  return(res)
}

You can either use the indexes of the columns to replace or their names.

> dfrename(df1, 2, "test")
  A test C
1 1    2 3

Because names of data is a vector, I try to use ifelse() to identify elements logically.

setNames(df1, ifelse(names(df1) == "A", "X", names(df1)))
  X B C
1 1 2 3
setNames(df1, ifelse(names(df1) == "B", "X", names(df1)))
  A X C
1 1 2 3
setNames(df1, ifelse(names(df1) == "C", "X", names(df1)))
  A B X
1 1 2 3

Another base R solution if you're ok to repeat the name of the old variable:

res <- transform(iris, a = Species, Species = NULL)
# [1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width"  "a" 

Regarding efficiency I'm not sure if the data is copied or not.

Related