如何使用dplyr将函数应用于多个输入的数据框并使用输出创建列?

时间:2019-02-08 09:14:10

标签: r dplyr

给出以下数据

data_in <- data.frame(X1 = c(1, 3, 5, 2, 6), 
       X2 = c(2, 4, 5, 1, 8),
       X3 = c(3, 2, 4, 1, 4))

我编写了一个函数,该函数接收数据帧,一个值(在此称为距离)和一个字符串(用于添加列名),以计算小于或等于输入值的值的数量。

custom_function <- function(some_data_frame, distance, name) {
   some_data_frame %>% 
   mutate(!!name := rowSums(. <= distance, na.rm = TRUE)) %>% 
   return()
}

我可以将函数应用于数据,如下所示:

data_in %>% 
 custom_function(., 5, "some_name")

我现在想要的是使用距离矢量,并使用我的自定义函数为每个距离创建一列。假设对于c(1、3、5),我想自动获取三列,而不要进行硬编码(手动应用函数三遍)。

2 个答案:

答案 0 :(得分:1)

使用mapply(使用与@Sotos ansswer中相同的distances)可以很容易地做到这一点:

(dst <- c(5, 3, 1, 6, 7, 8))
# [1] 5 3 1 6 7 8

(cnm <- paste('some_name', dst, sep = '_'))
# [1] "some_name_5" "some_name_3" "some_name_1" "some_name_6" "some_name_7" "some_name_8"

data_in[, cnm] <- mapply(function(d) rowSums(data_in <= d, na.rm = T), d = dst)

data_in
#   X1 X2 X3 some_name_5 some_name_3 some_name_1 some_name_6 some_name_7 some_name_8
# 1  1  2  3           3           3           1           3           3           3
# 2  3  4  2           3           2           0           3           3           3
# 3  5  5  4           3           0           0           3           3           3
# 4  2  1  1           3           3           2           3           3           3
# 5  6  8  4           1           0           0           2           2           3

您可以使用tidyversepurrr::map2中获得相同的结果:

cbind(
  data_in,
  purrr::map2(dst, cnm, ~custom_function(data_in, .x, .y))
)

#   X1 X2 X3 some_name_5 some_name_3 some_name_1 some_name_6 some_name_7 some_name_8
# 1  1  2  3           3           3           1           3           3           3
# 2  3  4  2           3           2           0           3           3           3
# 3  5  5  4           3           0           0           3           3           3
# 4  2  1  1           3           3           2           3           3           3
# 5  6  8  4           1           0           0           2           2           3

custom_function()定义为:

custom_function <- function(some_data_frame, distance, name) {
  some_data_frame %>% 
    transmute(!!name := rowSums(. <= distance, na.rm = TRUE))
}

答案 1 :(得分:0)

您可以使用sapply遍历向量,最后使用cbind,即

cbind.data.frame(data_in, 
                 do.call(cbind.data.frame, sapply(c(5, 3, 1, 6, 7, 8), function(i) 
                   custom_function(data_in, i, paste0('some_name_', i))[ncol(data_in) + 1])))

给出,

  X1 X2 X3 some_name_5 some_name_3 some_name_1 some_name_6 some_name_7 some_name_8
1  1  2  3           3           3           1           3           3           3
2  3  4  2           3           2           0           3           3           3
3  5  5  4           3           0           0           3           3           3
4  2  1  1           3           3           2           3           3           3
5  6  8  4           1           0           0           2           2           3