1

I have a situation where I need to add an arbitrary number of columns to a tibble. The column names that I need to add will come from a list.

If it were just one column, it's easy, I would just use add_column().

For example, starting with tibble, df, I can add column c like this:

library(tidyverse)

df <- tibble(a = 1:3, b = 3:1)
df <- add_column(df, c = 0)

Which yields...

# A tibble: 3 × 3
      a     b     c
  <int> <int> <dbl>
1     1     3     0
2     2     2     0
3     3     1     0

That leads me to believe that if I want to add multiple columns, for example from a list, new_cols, I could just map them onto add_column() but for some reason, I can't.

library(tidyverse)

df <- tibble(a = 1:3, b = 3:1)

new_cols <- c('d','e','f')

map(new_cols, ~ df <- add_column(df, . = 0))

... thinking about this some more of course map() is the wrong idea-- the whole point of map is to generate a list and not side-effects.

I am sure there's an easy one-liner for this, but it escapes me right now.

Angelo
  • 2,936
  • 5
  • 29
  • 44
  • Yes, there was an answer from 8 years ago that answers this question, however, the question was phrased somewhat differently, so I decided to not delete this question in case anyone comes across this again (I had missed the existing answers when I looked for it). Also, one of the other answers here discusses using purrr to do this which isn't addressed in the old answers. – Angelo Mar 14 '23 at 14:52
  • If you specify in this question that you want to add columns from a list of names by `tibble::add_column`, or by other `tidyverse` solution, then this question will no longer be duplicate because you search for a new solution different from an existing one. – Darren Tsai Mar 14 '23 at 15:08

2 Answers2

3
df[new_cols] <- 0

# A tibble: 3 × 5
      a     b     d     e     f
  <int> <int> <dbl> <dbl> <dbl>
1     1     3     0     0     0
2     2     2     0     0     0
3     3     1     0     0     0
Maël
  • 45,206
  • 3
  • 29
  • 67
1

If you search for a purrr solution like map, try reduce:

reduce(new_cols, ~ add_column(.x, '{.y}' := 0), .init = df)

# # A tibble: 3 × 5
#       a     b     d     e     f
#   <int> <int> <dbl> <dbl> <dbl>
# 1     1     3     0     0     0
# 2     2     2     0     0     0
# 3     3     1     0     0     0

You can also inject a named vector or named list of arguments into add_column() with the splice operator !!!.

new_names <- c('d','e','f')
new_cols <- set_names(rep(0, length(new_names)), new_names)

new_cols
# d e f 
# 0 0 0

add_column(df, !!!new_names)

# # A tibble: 3 × 5
#       a     b     d     e     f
#   <int> <int> <dbl> <dbl> <dbl>
# 1     1     3     0     0     0
# 2     2     2     0     0     0
# 3     3     1     0     0     0
Darren Tsai
  • 32,117
  • 5
  • 21
  • 51
  • Thanks, yes, also works! "map()" has a lesser known cousin, "reduce()", that I forgot about! – Angelo Mar 14 '23 at 14:03