user113156
user113156

Reputation: 7147

map over and change column names from a data frame

I have a data frame and a list. The list consists of 12 lists and the data frame consists of 12 rows and 2 columns. How can I map over the lists and change each of the list column names according to the data frame?.

That is, the data frame looks like:

           Var1         Var2
1   Sepal.Width Sepal.Length
2  Petal.Length Sepal.Length
3   Petal.Width Sepal.Length

The lists look like:

[[1]]
# A tibble: 2 x 2
      x     y
  <dbl> <dbl>
1   2     2  
2   3.8   3.8

[[2]]
# A tibble: 2 x 2
      x     y
  <dbl> <dbl>
1   3     3  
2   6.9   6.9

[[3]]
# A tibble: 2 x 2
      x     y
  <dbl> <dbl>
1   1     1  
2   2.5   2.5

The expected output

[[1]]
# A tibble: 2 x 2
Sepal.Width Sepal.Length
  <dbl> <dbl>
1   2     2  
2   3.8   3.8

[[2]]
# A tibble: 2 x 2
Petal.Length Sepal.Length
  <dbl> <dbl>
1   3     3  
2   6.9   6.9

[[3]]
# A tibble: 2 x 2
Petal.Width Sepal.Length
  <dbl> <dbl>
1   1     1  
2   2.5   2.5

Where now the column names of each of the lists are labeled according to the data frame.

Data

var_lists <- list(structure(list(x = c(2, 3.8), y = c(2, 3.8)), row.names = c(NA, 
-2L), class = c("tbl_df", "tbl", "data.frame")), structure(list(
    x = c(3, 6.9), y = c(3, 6.9)), row.names = c(NA, -2L), class = c("tbl_df", 
"tbl", "data.frame")), structure(list(x = c(1, 2.5), y = c(1, 
2.5)), row.names = c(NA, -2L), class = c("tbl_df", "tbl", "data.frame"
)), structure(list(x = c(4.9, 7.9), y = c(4.9, 7.9)), row.names = c(NA, 
-2L), class = c("tbl_df", "tbl", "data.frame")), structure(list(
    x = c(3, 6.9), y = c(3, 6.9)), row.names = c(NA, -2L), class = c("tbl_df", 
"tbl", "data.frame")), structure(list(x = c(1, 2.5), y = c(1, 
2.5)), row.names = c(NA, -2L), class = c("tbl_df", "tbl", "data.frame"
)), structure(list(x = c(4.9, 7.9), y = c(4.9, 7.9)), row.names = c(NA, 
-2L), class = c("tbl_df", "tbl", "data.frame")), structure(list(
    x = c(2, 3.8), y = c(2, 3.8)), row.names = c(NA, -2L), class = c("tbl_df", 
"tbl", "data.frame")), structure(list(x = c(1, 2.5), y = c(1, 
2.5)), row.names = c(NA, -2L), class = c("tbl_df", "tbl", "data.frame"
)), structure(list(x = c(4.9, 7.9), y = c(4.9, 7.9)), row.names = c(NA, 
-2L), class = c("tbl_df", "tbl", "data.frame")), structure(list(
    x = c(2, 3.8), y = c(2, 3.8)), row.names = c(NA, -2L), class = c("tbl_df", 
"tbl", "data.frame")), structure(list(x = c(3, 6.9), y = c(3, 
6.9)), row.names = c(NA, -2L), class = c("tbl_df", "tbl", "data.frame"
)))

var_combos <- structure(list(Var1 = structure(c(2L, 3L, 4L, 1L, 3L, 4L, 1L, 
2L, 4L, 1L, 2L, 3L), .Label = c("Sepal.Length", "Sepal.Width", 
"Petal.Length", "Petal.Width"), class = "factor"), Var2 = structure(c(1L, 
1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L), .Label = c("Sepal.Length", 
"Sepal.Width", "Petal.Length", "Petal.Width"), class = "factor")), out.attrs = list(
    dim = c(4L, 4L), dimnames = list(Var1 = c("Var1=Sepal.Length", 
    "Var1=Sepal.Width", "Var1=Petal.Length", "Var1=Petal.Width"
    ), Var2 = c("Var2=Sepal.Length", "Var2=Sepal.Width", "Var2=Petal.Length", 
    "Var2=Petal.Width"))), class = "data.frame", row.names = c(NA, 
-12L))

Upvotes: 1

Views: 2752

Answers (3)

Brian Goodwin
Brian Goodwin

Reputation: 391

I was trying to find a solution to this problem too and came across the rename_with() function!

Say you have a data frame:

library(tidyverse)

df <- tibble(V0 = runif(10), V1 = runif(10), V2 = runif(10), key=letters[1:10])

And you want to change all of the "V" columns. Usually, my reference for columns like this comes from a json file, which in R is a labeled list. e.g.,

colmapping <- c("newcol1", "newcol2", "newcol3")
names(colmapping) <- paste0("V",0:2)

You can then use the following to change the names of df to the strings in the colmapping list:

df <- rename_with(.data = df, .cols = starts_with("V"), .fn = function(x){colmapping[x]})

Upvotes: 0

dario
dario

Reputation: 6483

Using a loop:

for (i in seq_along(var_lists)) {
  names(var_lists[[i]]) <- as.character(unlist(var_combos[i, ]))
}

If the strings in var_combos were not factors it you could omit the as.character part

Upvotes: 1

akrun
akrun

Reputation: 887881

We can split the 'var_combos' by row, and use that in map2

library(dplyr)
library(purrr)
map2(var_lists, asplit(var_combos, 1), ~ .x %>% 
             set_names(.y))
#[[1]]
# A tibble: 2 x 2
#  Sepal.Width Sepal.Length
#        <dbl>        <dbl>
#1         2            2  
#2         3.8          3.8

#[[2]]
# A tibble: 2 x 2
#  Petal.Length Sepal.Length
#         <dbl>        <dbl>
#1          3            3  
#2          6.9          6.9

#[[3]]
# A tibble: 2 x 2
#  Petal.Width Sepal.Length
#        <dbl>        <dbl>
#1         1            1  
#2         2.5          2.5
#...

Or without anonymous function call

map2(var_lists, asplit(var_combos, 1), set_names)

In base R, the equivalent operation can be done with setNames/Map

Map(setNames, var_lists, asplit(var_combos, 1))

Upvotes: 3

Related Questions