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