Reputation: 7147
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
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
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
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