Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using lapply to change column names of a list of data frames

I'm trying to use lapply on a list of data frames; but failing at passing the parameters correctly (I think).

List of data frames:

df1 <- data.frame(A = 1:10, B= 11:20)
df2 <- data.frame(A = 21:30, B = 31:40) 

listDF <- list(df1, df2,df3)    #multiple data frames w. way less columns than the length of vector todos

Vector with columns names:

todos <-c('col1','col2', ......'colN')

I'd like to change the column names using lapply:

lapply (listDF, function(x) { colnames(x)[2:length(x)] <-todos[1:length(x)-1] }  )

but this doesn't change the names at all. Am I not passing the data frames themselves, but something else? I just want to change names, not to return the result to a new object.

Thanks in advance, p.

like image 920
user3310782 Avatar asked Nov 06 '15 12:11

user3310782


People also ask

How do I rename multiple columns in R?

To change multiple column names by name and by index use rename() function of the dplyr package and to rename by just name use setnames() from data. table . From R base functionality, we have colnames() and names() functions that can be used to rename a data frame column by a single index or name.

How do you name a list of data frames?

You can also use a setNames() function within a Map() function to rename each column for your list of dataframes. To keep your code clean as possible, it is best to avoid naming objects with the same names as functions. (Your example code uses a vector called "names" but also uses names() function.)

Can you use Lapply on a DataFrame?

If, instead of a list, you had a data frame of stock returns, could you still use lapply() ? Yes! Perhaps surprisingly, data frames are actually lists under the hood, and an lapply() call would apply the function to each column of the data frame.

Can you use Lapply on a DataFrame in R?

In R Programming Language to apply a function to every integer type value in a data frame, we can use lapply function from dplyr package. And if the datatype of values is string then we can use paste() with lapply.


2 Answers

You can also use setNames if you want to replace all columns

df1 <- data.frame(A = 1:10, B= 11:20)
df2 <- data.frame(A = 21:30, B = 31:40) 

listDF <- list(df1, df2)
new_col_name <- c("C", "D")

lapply(listDF, setNames, nm = new_col_name)
## [[1]]
##     C  D
## 1   1 11
## 2   2 12
## 3   3 13
## 4   4 14
## 5   5 15
## 6   6 16
## 7   7 17
## 8   8 18
## 9   9 19
## 10 10 20

## [[2]]
##     C  D
## 1  21 31
## 2  22 32
## 3  23 33
## 4  24 34
## 5  25 35
## 6  26 36
## 7  27 37
## 8  28 38
## 9  29 39
## 10 30 40

If you need to replace only a subset of column names, then you can use the solution of @Jogo

lapply(listDF, function(df) {
  names(df)[-1] <- new_col_name[-ncol(df)]
  df
})

A last point, in R there is a difference between a:b - 1 and a:(b - 1)

1:10 - 1
## [1] 0 1 2 3 4 5 6 7 8 9

1:(10 - 1)
## [1] 1 2 3 4 5 6 7 8 9

EDIT

If you want to change the column names of the data.frame in global environment from a list, you can use list2env but I'm not sure it is the best way to achieve want you want. You also need to modify your list and use named list, the name should be the same as name of the data.frame you need to replace.

listDF <- list(df1 = df1, df2 = df2)

new_col_name <- c("C", "D")

listDF <- lapply(listDF, function(df) {
  names(df)[-1] <- new_col_name[-ncol(df)]
  df
})

list2env(listDF, envir = .GlobalEnv)
str(df1)
## 'data.frame':    10 obs. of  2 variables:
##  $ A: int  1 2 3 4 5 6 7 8 9 10
##  $ C: int  11 12 13 14 15 16 17 18 19 20
like image 133
dickoa Avatar answered Sep 18 '22 18:09

dickoa


try this:

lapply (listDF, function(x) { 
  names(x)[-1] <- todos[-length(x)]
  x 
})

you will get a new list with changed dataframes. If you want to manipulate the listDF directly:

for (i in 1:length(listDF)) names(listDF[[i]])[-1] <- todos[-length(listDF[[i]])]
like image 35
jogo Avatar answered Sep 20 '22 18:09

jogo