Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 将应用函数与向数据帧添加变量的用户定义函数一起使用_R_Dplyr_Apply - Fatal编程技术网

R 将应用函数与向数据帧添加变量的用户定义函数一起使用

R 将应用函数与向数据帧添加变量的用户定义函数一起使用,r,dplyr,apply,R,Dplyr,Apply,我定义了一个函数,它将在数据帧中动态创建新变量。对于该函数,输入是一个字符串,然后与其他字符串一起粘贴,以创建数据帧中已经存在的变量名,然后在mutate中使用case_进行比较。函数的输出是数据帧,末尾附加了新变量。我想将此函数应用于输入向量,并在数据帧中创建多个新列。我使用iris数据集创建了一个与我正在做的非常类似的函数 func <- function(x) { a <- paste0("Sepal.", x) b <- paste0("Petal.", x)

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

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")

func您想要构建输出的方式有细微的变化-

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)

您想要构建输出的方式有细微的变化-

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)

再玩一会儿,我确实找到了这个问题的答案。我没有让
func
输出数据帧,而是将其更改为仅输出向量,然后使用
do.call
lappy

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)))

func再玩一会儿,我确实找到了这个问题的答案。我没有让
func
输出数据帧,而是将其更改为仅输出向量,然后使用
do.call
lappy

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)))

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

  • iris[[1]]
    是第一个数据帧
  • iris[[2]]
    是第二个数据帧
您可以使用
merge
将两个数据帧合并为一个,如下所示:

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

comp.iris您的结果是两个数据帧(如您所示):

  • iris[[1]]
    是第一个数据帧
  • iris[[2]]
    是第二个数据帧
您可以使用
merge
将两个数据帧合并为一个,如下所示:

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

comp.iris一个更简单的选项是只在函数中生成新列,方法是用
transmute
替换
mutate
,用
map\u dfc
迭代并将它们连接到数据帧中,然后使用
bind\u cols
将它们添加到原始列中:

库(tidyverse)
func%head()
#>萼片。长萼片。宽花瓣。长花瓣。宽种比较。长
#>1 5.1 3.5 1.4 0.2刚毛萼片
#>2 4.9 3.0 1.4 0.2刚毛萼片
#>3 4.7 3.2 1.3 0.2刚毛萼片
#>4.6 3.1 1.5 0.2刚毛萼片
#>5.0 3.6 1.4 0.2刚毛萼片
#>6 5.4 3.9 1.7 0.4刚毛萼片
#>比较。宽度
#>1萼片
#>2萼片
#>3萼片
#>4萼片
#>5萼片
#>6萼片
一种稍微优雅一点的方法是将函数构造成一个向量,将所有迭代都移动到内部。您可以使用上述方法,或者只要生成向量,并在存在多个向量时将它们组合成一个数据帧:

func2 146 6.7 3.0 5.2 2.3弗吉尼亚州
#>147 6.3 2.5 5.0 1.9弗吉尼亚州
#>148 6.5 3.0 5.2 2.0弗吉尼亚州
#>149 6.2 3.4 5.4 2.3弗吉尼亚州
#>150 5.9 3.0 5.1 1.8弗吉尼亚州
#>比较。长度比较。宽度比较
#>145萼片
#>146萼片
#>147萼片
#>148萼片
#>149萼片
#>150萼片

一个更简单的选项是,只在函数中生成新列,方法是用
transmute
替换
mutate
,用
map\u dfc
迭代并将它们连接到数据帧中,然后使用
bind\u cols
将它们添加到原始列中:

库(tidyverse)
func%head()
#>萼片。长萼片。宽花瓣。长花瓣。宽种比较。长
#>1 5.1 3.5 1.4 0.2刚毛萼片
#>2 4.9 3.0 1.4 0.2刚毛萼片
#>3 4.7 3.2 1.3 0.2刚毛萼片
#>4.6 3.1 1.5 0.2刚毛萼片
#>5.0 3.6 1.4 0.2刚毛萼片
#>6 5.4 3.9 1.7 0.4刚毛萼片
#>比较。宽度
#>1萼片
#>2萼片
#>3萼片
#>4萼片
#>5萼片
#>6萼片
一种稍微优雅一点的方法是将函数构造成一个向量,将所有迭代都移动到内部。您可以使用上述方法,或者只要生成向量,并在存在多个向量时将它们组合成一个数据帧:

func2 146 6.7 3.0 5.2 2.3弗吉尼亚州
#>147 6.3 2.5 5.0 1.9弗吉尼亚州
#>148 6.5 3.0 5.2 2.0弗吉尼亚州
#>149 6.2 3.4 5.4 2.3弗吉尼亚州
#>150 5.9 3.0 5.1 1.8弗吉尼亚州
#>比较。长度比较。宽度比较
#>145萼片
#>146萼片
#>147萼片
#>148萼片
#>149萼片
#>150萼片

谢谢!这就是我在你发帖之前发现的我在回答我自己的问题。你知道你更新数据框的方式是否比我在下面使用
Do.call
所做的更好吗?@jamesguy0121我想说OP中的输出格式现在与我的答案更一致。但是您可以始终使用
colnames()
来解决这个问题,方法是使用
do.call()
。我认为这两种解决方案都是g