首页 > 解决方案 > 基于映射和用户数据创建新的 tibble 列

问题描述

我正在尝试从一个函数的输出中生成一个 tibble 中的新列,该函数将该 tibble 的几个现有列以及用户数据作为输入。作为一个简化的例子,我想使用这个功能

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

并使用它来添加此 tibble 中现有列中的数字...

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 的长度可以变化,我不知道如何概括这一点。我发现这个答案在 tidyverse 中重复 mutate,但是函数在现有列上重复,而不是使用多个现有列进行映射。

有任何想法吗?

标签: rpurrrdplyrtibble

解决方案


由于我们不必将函数或列名作为参数,因此这相对简单。您只需要使用返回总和列的函数进行迭代vec,然后与原始表结合。如果你有一个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 包(v0.2.0) 于 2019 年 1 月 16 日创建。


推荐阅读