在 R 中使用 ... 编写函数并扩展到 dplyr::recode 中的命名替换

Writing a function using ... and expanding to named replacements in dplyr::recode in R

我发现自己经常进行相同的数据转换,唯一的区别是名称和列数。例如,

library(tidyverse)

test.data <- tribble(
  ~id.num, ~site, ~value1, ~value2, ~value3,
  "10-01", "log", 1.5, 2.5, 3.5,
  "10-02", "branch", 0.7, 2, 3.24,
  "10-03", "branch", 3.2, 2.3, 7.7
)

test.data <-
  gather(
    test.data,
    key = "test.code",
    value = "values",
    "value1",
    "value2",
    "value3"
  ) %>%
  mutate(
    test.code.order = recode(
      test.code,
      "value1" = 1,
      "value2" = 2,
      "value3" = 3
    )
  ) %>%
  arrange(id.num, test.code.order)

在我的实际数据中,通常会收集 16-30 列而不是 3 列。目前我最终为 mutate 创建命名对的做法是

c(
  "value1",
  "value2",
  "value3"
) -> columns

cat(paste0('"', columns, '" = ', 1:length(columns)), sep = ",\n")

并将输出复制并粘贴到代码中。

但是,我希望能够创建一个函数,使得

test.data <- wide.to.long(test.data, "value1", "value2", "value3")

给我的结果与上面的 gathermutatearrange 管道相同。我不确定如何将字符串从 "value1" 扩展到 "value1" = 1

我想它看起来像这样,

wide.to.long <- function(df, key = "test.code", value = "values", id = "id.num", ...) {
  test.order.numbers <- missing.code.here
  gather(df, key, value, ...) %>%
    mutate(test.code.order = recode(key, test.order.numbers)) %>%
    arrange(id, test.code.order)
}

但当然 cat 不起作用,我尝试过的任何版本的 paste 都会给我错误:"Argument 2 must be named, not unnamed"。我错过了什么?

wide.to.long <- function(df, ..., key = "test.code", 
                         value = "values", id = "id.num") {
  v <- quos(...)
  key <- rlang::sym(key)
  key <- enquo(key)
  id <- rlang::sym(id)
  id <- enquo(id)
  test.order.numbers <- setNames(seq_along(v), sapply(v, quo_name))
  gather(df, !! key, !! value, !!! v) %>% 
    mutate(test.code.order = recode(!! key, !!! test.order.numbers)) %>% 
    arrange(!! id, test.code.order)
}

wide.to.long(test.data, "value1", "value2", "value3")

# # A tibble: 9 x 5
#   id.num   site test.code values test.code.order
#    <chr>  <chr>     <chr>  <dbl>           <int>
# 1  10-01    log    value1   1.50               1
# 2  10-01    log    value2   2.50               2
# 3  10-01    log    value3   3.50               3
# 4  10-02 branch    value1   0.70               1
# 5  10-02 branch    value2   2.00               2
# 6  10-02 branch    value3   3.24               3
# 7  10-03 branch    value1   3.20               1
# 8  10-03 branch    value2   2.30               2
# 9  10-03 branch    value3   7.70               3

或者你可以直接传递裸变量名:wide.to.long(test.data, value1, value2, value3).