在用户定义的函数中进行子集化以将值分配给目标列
Subsetting within user-defined function to assign values to target column
我想编写一个函数,根据数据框中其他三个列的值替换目标列的值。
data <-data.frame("exists" = c(1,0,1,0,1,0,0,0,1,1),
"specific" = c("yes", NA, "no", NA, NA, NA, NA, NA, NA, "no"),
"general" = c(NA, "yes", NA, "yes", "yes", NA, "no", NA, "no", NA),
"therefore" = 0)
目标列是therefore
,默认值为0。我可以用三行子集(或嵌套ifelse
语句)手动给therefore
赋值,但我已经看到了避免 ifelse
分配值的建议)。
data[data["exists"] == 0, "therefore"] <- NA
data[grepl("yes", data[["specific"]], ignore.case=T), "therefore"] <- 1
data[data["exists"] == 1 & grepl("yes", data[["general"]], ignore.case=T),
"therefore"] <- 1
这给出了正确的输出:
> data["therefore"]
therefore
1 1
2 NA
3 0
4 NA
5 1
6 NA
7 NA
8 NA
9 0
10 0
我尝试将代码编写为一个函数,这样我就可以更轻松地将它应用于各种专栏:
fun <- function (doesitapply, string, speccol, gencol, target) {
data[data[doesitapply] == 0, target] <- NA
data[grepl(string, data[[speccol]], ignore.case=T), target] <- 1
data[data[doesitapply] == 1 & grepl(string, data[[gencol]],
ignore.case=T), target] <- 1
}
当我使用我的新函数 fun()
时,没有出现任何错误,但 therefore
的默认值似乎没有变化。
fun(doesitapply = "exists", string = "yes", speccol = "specific", gencol =
"general", target = "therefore")
> data["therefore"]
therefore
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
10 0
这是否与在用户定义的函数中使用列名进行子集化有关?我尝试对函数中的所有子集实例使用 [[]]
而不是 []
,但是 ...
Error in `[[<-.data.frame`(`*tmp*`, data[[doesitapply]] == 0, target, :
only a single element should be replaced
我看过 this post,但我发现很难将其答案应用到我的案例中。指导或建议表示赞赏!
当您的函数中的代码 运行 位于函数外部时(在设置您使用的所有变量之后),它会按您预期的那样工作:
doesitapply <- "exists"
string <- "yes"
speccol <- "specific"
gencol <- "general"
target <- "therefore"
data[data[doesitapply] == 0, target] <- NA
data[grepl(string, data[[speccol]], ignore.case=T), target] <- 1
data[data[doesitapply] == 1 & grepl(string, data[[gencol]], ignore.case=T), target] <- 1
这提供了与您从原始的、未参数化的代码中提供的相同的输出。但是,这在函数中不起作用,因为它会尝试更新 data
.
的本地版本
您可以修改您的函数,将所有 3 行中的 <-
更改为 <<-
。 <-
运算符总是在本地范围内赋值,而 <<-
运算符搜索父环境以查找具有该名称的现有变量。
而不是分配超过 3 个语句,使用 ifelse
可能更典型,这在这里是可以接受的,或者可能是 dplyr
https://www.rdocumentation.org/packages/dplyr/versions/0.7.8/topics/case_when 中的 case_when
函数这避免了使用嵌套的需要。
根据您期望的值,也可以简化测试(例如避免 grepl
)。
我想编写一个函数,根据数据框中其他三个列的值替换目标列的值。
data <-data.frame("exists" = c(1,0,1,0,1,0,0,0,1,1),
"specific" = c("yes", NA, "no", NA, NA, NA, NA, NA, NA, "no"),
"general" = c(NA, "yes", NA, "yes", "yes", NA, "no", NA, "no", NA),
"therefore" = 0)
目标列是therefore
,默认值为0。我可以用三行子集(或嵌套ifelse
语句)手动给therefore
赋值,但我已经看到了避免 ifelse
分配值的建议)。
data[data["exists"] == 0, "therefore"] <- NA
data[grepl("yes", data[["specific"]], ignore.case=T), "therefore"] <- 1
data[data["exists"] == 1 & grepl("yes", data[["general"]], ignore.case=T),
"therefore"] <- 1
这给出了正确的输出:
> data["therefore"]
therefore
1 1
2 NA
3 0
4 NA
5 1
6 NA
7 NA
8 NA
9 0
10 0
我尝试将代码编写为一个函数,这样我就可以更轻松地将它应用于各种专栏:
fun <- function (doesitapply, string, speccol, gencol, target) {
data[data[doesitapply] == 0, target] <- NA
data[grepl(string, data[[speccol]], ignore.case=T), target] <- 1
data[data[doesitapply] == 1 & grepl(string, data[[gencol]],
ignore.case=T), target] <- 1
}
当我使用我的新函数 fun()
时,没有出现任何错误,但 therefore
的默认值似乎没有变化。
fun(doesitapply = "exists", string = "yes", speccol = "specific", gencol =
"general", target = "therefore")
> data["therefore"]
therefore
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
10 0
这是否与在用户定义的函数中使用列名进行子集化有关?我尝试对函数中的所有子集实例使用 [[]]
而不是 []
,但是 ...
Error in `[[<-.data.frame`(`*tmp*`, data[[doesitapply]] == 0, target, :
only a single element should be replaced
我看过 this post,但我发现很难将其答案应用到我的案例中。指导或建议表示赞赏!
当您的函数中的代码 运行 位于函数外部时(在设置您使用的所有变量之后),它会按您预期的那样工作:
doesitapply <- "exists"
string <- "yes"
speccol <- "specific"
gencol <- "general"
target <- "therefore"
data[data[doesitapply] == 0, target] <- NA
data[grepl(string, data[[speccol]], ignore.case=T), target] <- 1
data[data[doesitapply] == 1 & grepl(string, data[[gencol]], ignore.case=T), target] <- 1
这提供了与您从原始的、未参数化的代码中提供的相同的输出。但是,这在函数中不起作用,因为它会尝试更新 data
.
您可以修改您的函数,将所有 3 行中的 <-
更改为 <<-
。 <-
运算符总是在本地范围内赋值,而 <<-
运算符搜索父环境以查找具有该名称的现有变量。
而不是分配超过 3 个语句,使用 ifelse
可能更典型,这在这里是可以接受的,或者可能是 dplyr
https://www.rdocumentation.org/packages/dplyr/versions/0.7.8/topics/case_when 中的 case_when
函数这避免了使用嵌套的需要。
根据您期望的值,也可以简化测试(例如避免 grepl
)。