将apply函数与用户定义的函数结合使用,该函数将变量添加到数据框

时间:2018-12-23 05:53:37

标签: r dplyr apply

我已经定义了一个函数,该函数将在数据框中动态创建新变量。对于此功能,输入是一个字符串,然后将其与其他字符串粘贴以创建数据帧中已存在的变量名,然后在mutate中使用case_w比较它们。函数的输出是将新变量附加到末尾的数据框。我想将此功能应用于输入向量,并在数据框中创建多个新列。我已经使用了虹膜数据集来创建与我正在执行的功能非常相似的功能。

func <- function(x) {
  a <- paste0("Sepal.", x)
  b <- paste0("Petal.", x)
  x <- iris %>% 
    mutate(
      !!(paste0("Compare.", x)) :=
        case_when(
          iris[[a]] > iris[[b]] ~ "Sepal",
          iris[[a]] < iris[[b]] ~ "Petal",
          TRUE ~ "Equal"
      )
    )
  return(x)
}

inputVector <- c("Length", "Width")

我想将此函数应用于inputVector并返回一个数据帧,该数据帧中将包含两个新变量,最好没有循环。我正在寻找使用类似的东西

iris <- lapply(inputVector, func)

但是这将返回两个数据帧的列表。我也知道我可以在<<-中使用func,但是我想避免这种情况。

4 个答案:

答案 0 :(得分:1)

要更改输出结构的方式略有变化-

func <- function(x) {
  a <- paste0("Sepal", x)
  b <- paste0("Petal", x)
  x1 <- iris %>% 
    mutate(
      !!(paste0("Compare.", x)) :=
        case_when(
          a > b ~ "Sepal",
          a < b ~ "Petal",
          TRUE ~ "Equal"
        )
    )
  return(x1[[paste0('Compare.',x)]])
}

inputVector <- c("Length", "Width")
op <- iris
op[,paste0('Compare.',inputVector)] <- lapply(inputVector, func)

输出

> head(op)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species Compare.Length Compare.Width
1          5.1         3.5          1.4         0.2  setosa          Sepal         Sepal
2          4.9         3.0          1.4         0.2  setosa          Sepal         Sepal
3          4.7         3.2          1.3         0.2  setosa          Sepal         Sepal
4          4.6         3.1          1.5         0.2  setosa          Sepal         Sepal
5          5.0         3.6          1.4         0.2  setosa          Sepal         Sepal
6          5.4         3.9          1.7         0.4  setosa          Sepal         Sepal

答案 1 :(得分:1)

一个更简单的选择是通过用Getting Started代替transmute,然后使用mutate将它们迭代并连接到数据框中,然后使用{{ 1}},将它们添加到原始文件中:

map_dfc

一种稍微更优雅的方法是构造函数以采用向量,将所有迭代移入内部。您可以使用上面的方法,或者只要有多个向量,就可以生成向量并将它们组合成数据帧:

bind_cols

答案 2 :(得分:0)

多玩一点我确实找到了这个问题的答案。与其让func输出数据帧,不如将其更改为仅输出向量,然后使用do.calllapply

func <- function(x) {
  a <- paste0("Sepal", x)
  b <- paste0("Petal", x)
  x <- iris %>% 
    transmute(
      !!(paste0("Compare.", x)) :=
        case_when(
          a > b ~ "Sepal",
          a < b ~ "Petal",
          TRUE ~ "Equal"
      )
    )
  return(x)
}

do.call(cbind, c(iris, lapply(inputVector, func)))

我绝对愿意接受其他解决方案,因为我想这可能不是最好的。

答案 3 :(得分:0)

您的结果是两个数据帧(如您所述):

  • iris[[1]]是第一个数据帧
  • iris[[2]]是第二个数据帧。

您可以使用merge将两个数据帧合并为一个,如下所示:

comp.iris <- lapply(inputVector, func) 
comp.iris <- merge(comp.iris[[1]], comp.iris[[2]], sort = FALSE)

希望有帮助。