Home > Enterprise >  Mutate new column in a listed dataframes from a vector with Tidyverse
Mutate new column in a listed dataframes from a vector with Tidyverse

Time:08-03

Consider this vector

names <- c("Jon", "Nancy")

And, a list of dataframes with the same length

listed_dfs <- list(tibble(X = sample(1:5),
                          Y = sample(1:5)),
                   tibble(X = sample(11:15),
                          Y = sample(11:15)))

I would like to add a new column in each of them with a name according to their position in the vector. Such that the desired output would be:

[[1]]
# A tibble: 5 x 3
      X     Y name 
  <int> <int> <chr>
1     4     1 Jon  
2     2     5 Jon  
3     5     2 Jon  
4     3     4 Jon  
5     1     3 Jon  

[[2]]
# A tibble: 5 x 3
      X     Y name 
  <int> <int> <chr>
1    14    13 Nancy
2    11    14 Nancy
3    12    12 Nancy
4    15    11 Nancy
5    13    15 Nancy

I have tried imap and map without any results.

EDIT:

Okay, I managed to find a solution

imap(listed_dfs, ~ bind_cols(.x, name = names[.y])) 

But I'm still open to other suggestions, if there are cleaner ways

CodePudding user response:

You could use map2 from purrr:

map2(listed_dfs, names, ~ bind_cols(name = .y, .x))

[[1]]
# A tibble: 5 × 3
  name      X     Y
  <chr> <int> <int>
1 Jon       3     2
2 Jon       1     3
3 Jon       4     1
4 Jon       5     4
5 Jon       2     5

[[2]]
# A tibble: 5 × 3
  name      X     Y
  <chr> <int> <int>
1 Nancy    15    12
2 Nancy    13    14
3 Nancy    11    11
4 Nancy    14    13
5 Nancy    12    15

If your final goal is to bind them, you could directly use bind_rows(..., .id = 'name') from dplyr:

bind_rows(set_names(listed_dfs, names), .id = 'name')

# A tibble: 10 × 3
   name      X     Y
   <chr> <int> <int>
 1 Jon       3     2
 2 Jon       1     3
 3 Jon       4     1
 4 Jon       5     4
 5 Jon       2     5
 6 Nancy    15    12
 7 Nancy    13    14
 8 Nancy    11    11
 9 Nancy    14    13
10 Nancy    12    15

CodePudding user response:

If you wish to use map, I believe the syntax should be similar to lapply. And the output would still be a list of tibbles.

library(tidyverse)

map(seq_along(names), ~ bind_cols(listed_dfs[[.x]], name = names[.x]))

[[1]]
# A tibble: 5 × 3
      X     Y name 
  <int> <int> <chr>
1     2     1 Jon  
2     1     2 Jon  
3     4     3 Jon  
4     5     4 Jon  
5     3     5 Jon  

[[2]]
# A tibble: 5 × 3
      X     Y name 
  <int> <int> <chr>
1    12    14 Nancy
2    15    13 Nancy
3    11    11 Nancy
4    13    15 Nancy
5    14    12 Nancy
  • Related