0

I'm writing a function that takes a data frame and a column names as arguments, and returns the data frame with the column indicated being transformed to character type. However, I'm stuck at the non-standard evaluation part of dplyr.

My current code:

df <- tibble(id = 1:5, value = 6:10)
col <- "id"
mutate(df, "{col}" := as.character({{ col }}))

# # A tibble: 5 x 2
#   id    value
#   <chr> <int>
# 1 id        6
# 2 id        7
# 3 id        8
# 4 id        9
# 5 id       10

As you can see, instead of transforming the contents of the column to character type, the column values are replaced by the column names. {{ col }} isn't evaluated like I expected it to be. What I want is a dynamic equivalent of this:

mutate(df, id = as.character(id))

# # A tibble: 5 x 2
# id    value
# <chr> <int>
# 1 1         6
# 2 2         7
# 3 3         8
# 4 4         9
# 5 5        10

I've tried to follow the instructions provided in dplyr's programming vignette, but I'm not finding a solution that works. What am I doing wrong?

A. Stam
  • 2,148
  • 14
  • 29

2 Answers2

2

Use the .data pronoun -

library(dplyr)

df <- tibble(id = 1:5, value = 6:10)
col <- "id"
mutate(df, "{col}" := as.character(.data[[col]]))

#  id    value
#  <chr> <int>
#1 1         6
#2 2         7
#3 3         8
#4 4         9
#5 5        10

Some other alternatives -

mutate(df, "{col}" := as.character(get(col)))
mutate(df, "{col}" := as.character(!!sym(col)))
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
1

We may use across which can also do this on multiple columns

library(dplyr)
df %>%
    mutate(across(all_of(col), as.character))
# A tibble: 5 x 2
  id    value
  <chr> <int>
1 1         6
2 2         7
3 3         8
4 4         9
5 5        10

data

df <- tibble(id = 1:5, value = 6:10)
col <- "id"
akrun
  • 874,273
  • 37
  • 540
  • 662