基于映射和用户数据创建新的 tibble 列

creating new tibble columns based on mapping plus user data

我正在尝试根据一个函数的输出在一个小标题中生成新列,该函数将该小标题的几个现有列加上用户数据作为输入。作为一个简化的例子,我想使用这个函数

addup <- function(x, y, z){x + y + z}

并用它来添加此标题中现有列中的数字...

set.seed(1)
(tib <- tibble(num1 = sample(12), num2 = sample(12)))
# A tibble: 12 x 2
    num1  num2
   <int> <int>
 1     8     5
 2     6     3
 3     7     7
 4     3    11
 5     1     2
 6     2     1
 7    11     6
 8    10     9
 9     4     8
10     9    12
11     5    10
12    12     4

...连同用户输入。例如,如果用户定义向量

vec <- c(3,6,4)

我想在 vec 中为每个项目生成一个新列,将映射值与用户输入值相加。

在这种情况下,期望的结果类似于:

# A tibble: 12 x 5
    num1  num2   `3`   `6`   `4`
   <int> <int> <dbl> <dbl> <dbl>
 1     5     7    15    18    16
 2     8     2    13    16    14
 3     7     9    19    22    20
 4     1    11    15    18    16
 5     3     3     9    12    10
 6     9    12    24    27    25
 7     6     6    15    18    16
 8    10    10    23    26    24
 9    11     4    18    21    19
10    12     5    20    23    21
11     4     1     8    11     9
12     2     8    13    16    14

如果我事先知道vec,我可以通过

实现
tib %>% 
  mutate("3" = map2_dbl(num1, num2, ~addup(.x, .y, 3)),
         "6" = map2_dbl(num1, num2, ~addup(.x, .y, 6)), 
         "4" = map2_dbl(num1, num2, ~addup(.x, .y, 4))) 

但由于 vec 的长度可能会有所不同,我不知道如何概括这一点。我找到了这个答案 ,但是函数在现有列上重复,而不是使用多个现有列进行映射。

有什么想法吗?

因为我们不必将函数或列名作为参数,所以这相对简单。您只需要使用 returns 求和列的函数迭代 vec,然后与原始 table 组合。如果你有一个接受向量输入的 addup 函数,那么你可以跳过整个 map2 部分;事实上这个是可以的,但我不知道你的真实功能是否可以。

library(tidyverse)
vec <- c(3,6,4)
set.seed(1)
tib <- tibble(num1 = sample(12), num2 = sample(12))

addup <- function(c1, c2, z) {c1 + c2 + z}
addup_vec <- function(df, vec) {
  new_cols <- map_dfc(
    .x = vec,
    .f = function(v) {
      map2_dbl(
        .x = df[["num1"]],
        .y = df[["num2"]],
        .f = ~ addup(.x, .y, v)
      )
    }
  )
  colnames(new_cols) <- vec
  bind_cols(df, new_cols)
}

tib %>%
  addup_vec(vec)
#> # A tibble: 12 x 5
#>     num1  num2   `3`   `6`   `4`
#>    <int> <int> <dbl> <dbl> <dbl>
#>  1     4     9    16    19    17
#>  2     5     5    13    16    14
#>  3     6     8    17    20    18
#>  4     9    11    23    26    24
#>  5     2     6    11    14    12
#>  6     7     7    17    20    18
#>  7    10     3    16    19    17
#>  8    12     4    19    22    20
#>  9     3    12    18    21    19
#> 10     1     1     5     8     6
#> 11    11     2    16    19    17
#> 12     8    10    21    24    22

reprex package (v0.2.0) 创建于 2019-01-16。

这使用 lapply 将函数应用于向量的每个元素,然后将结果绑定到原始数​​据框并添加列名。

# Given example
set.seed(1)
(tib <- tibble(num1 = sample(12), num2 = sample(12)))
addup <- function(x, y, z){x + y + z}
vec <- c(3,6,4)

# Add columns and bind to original data frame
foo <- cbind(tib, lapply(vec, function(x)addup(tib$num1, tib$num2, x)))

# Correct column names
colnames(foo)[(ncol(tib)+1):ncol(foo)] <- vec

# Print result
print(foo)

#    num1 num2  3  6  4
# 1     4    9 16 19 17
# 2     5    5 13 16 14
# 3     6    8 17 20 18
# 4     9   11 23 26 24
# 5     2    6 11 14 12
# 6     7    7 17 20 18
# 7    10    3 16 19 17
# 8    12    4 19 22 20
# 9     3   12 18 21 19
# 10    1    1  5  8  6
# 11   11    2 16 19 17
# 12    8   10 21 24 22