根据映射和用户数据创建新的标题栏

时间:2019-01-16 21:56:48

标签: r dplyr purrr mutate tibble

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

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长度的变化,我不知道该如何概括。我已经找到了答案repeated mutate in tidyverse,但是在现有列上重复了这些功能,而不是使用多个现有列进行映射。

有什么想法吗?

2 个答案:

答案 0 :(得分:3)

由于我们不必将函数或名称作为参数,因此这相对简单。您只需要使用一个函数返回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 package(v0.2.0)于2019-01-16创建。

答案 1 :(得分:2)

这使用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