【发布时间】:2020-03-24 09:25:28
【问题描述】:
作为一个更大的函数的一部分,它只保留在每个人受伤之前发生的植物生长时间序列中的值 (plantid),我正在编写 2 个块,其中依次包含一个函数
控制参数中给定的所有变量都是字符向量(如在第二个函数中,
%in%不识别命名因子),如果不是,则在提供警告时转换为字符。从上述给定变量中识别并标记行,这些变量包括参数
b中的字符串之一。
我很确定引用/准引用或 bang-bang (!!)/big-bang (!!!) 运算符有问题(这是我第一次编写带引号的函数) .我一直收到“!!! 可能无法在顶层使用”警告等,我不知道如何解决。我还需要帮助找到一种尝试转换非字符变量的好方法。
这是我到目前为止所得到的
参数说明
df:data.frameplantid:每个植物的唯一标识符year:观察年份injuries:(在我的情况下)3列可以包含伤害代码的列表,例如c("PrimaryInjury", "SecondaryInjury", "OtherInjury")forbidden_values:感兴趣的伤害代码,例如c("Rust", "Insect", "Snow break")
功能
id_injured <- function(df, plantid, year, injuries, forbidden_values){
#parsing unquoted strings.
plantid <- enquo(plantid)
year <- enquo(year)
forbidden_values <- enquos(forbidden_values)
injuries <- syms(injuries)
#if all variables in injuries are not characters, stop and warn (attempt to convert to character those variables which are not character)
if(!all(purrr::pmap_int(select(df, !!!injuries), ~is.character(...))))){
stop("All injury variables are not characters. Convert factors in injuries to character variables")} else {
(1) #Control to give output while testing function, replace with conversion and warning?
}
#Identify rows with matching injury codes with 1, else 0.
Dataplantid <- df %>% mutate(is_injured = purrr::pmap_int(select(df, !!!injuries), any(c(...) %in% !!!forbidden values)))
#End of function
}
预期用途
我删除了函数的第 (1) 部分,以便它只会尝试标记 1 或 0。
Dataplantid <- id_injured(df=df, plantid=plantid, year=year, injuries=c("PrimaryInjury","SecondaryInjury","OtherInjury"),forbidden_values=c("Rust","Insect","Snow break")
结果
错误:不能在顶层使用
!!!。
> last_trace()
<error/rlang_error>
Can't use `!!!` at top level.
Backtrace:
█
1. └─global::so_injured(...)
2. └─`%>%`(...)
3. ├─base::withVisible(eval(quote(`_fseq`(`_lhs`)), env, env))
4. └─base::eval(quote(`_fseq`(`_lhs`)), env, env)
5. └─base::eval(quote(`_fseq`(`_lhs`)), env, env)
6. └─`_fseq`(`_lhs`)
7. └─magrittr::freduce(value, `_function_list`)
8. ├─base::withVisible(function_list[[k]](value))
9. └─function_list[[k]](value)
10. ├─dplyr::mutate(...)
11. └─dplyr:::mutate.data.frame(...)
12. ├─base::as.data.frame(mutate(tbl_df(.data), ...))
13. ├─dplyr::mutate(tbl_df(.data), ...)
14. └─dplyr:::mutate.tbl_df(tbl_df(.data), ...)
15. └─rlang::enquos(..., .named = TRUE)
16. └─rlang:::endots(...)
17. └─rlang:::map(...)
18. └─base::lapply(.x, .f, ...)
19. └─rlang:::FUN(X[[i]], ...)
20. └─rlang::splice(...)
相关数据
plantid <- rep(c(1,2,3,4,5), times=c(3,3,3,3,3))
year <- rep(1:3, length.out=length(plantid))
set.seed(42)
PrimaryInjury <- sample(c(NA,NA,NA,"Rust","Insect", "Snow break"), 15, replace=TRUE)
SecondaryInjury <- rep(NA, length.out=length(plantid)) #Filled with NA for example
OtherInjury <- rep(NA, length.out=length(plantid)) #Filled NA for example
df <- data.frame(plantid,year,PrimaryInjury,SecondaryInjury,OtherInjury)
#Right now, PrimaryInjury is a factor, SecondaryInjury and OtherInjury are logical.
预期输出
Dataplantid <- df
Dataplantid$is_injured <- c(0,1,0,0,0,1,0,0,0,1,0,1,1,1,0)
【问题讨论】:
-
首先,您的函数缺少返回参数。新的数据框 Dataplantid 不会保存在全局环境中。您的目标是该函数返回一个数据框,该数据框标志着某种植物是否受到某种伤害?那么你只需要一个带有
ifelse()的mutate()语句。此外,由于您没有展示如何使用该功能,因此该问题不可重现。 -
@MKR,感谢您的回复!我将更新问题以反映该功能的使用方式。返回的 Dataplantid 将被返回但不保存,因为它是函数环境中的最后一个对象,因此我可以将输出分配给我选择的名称,是吗?在较大的函数中,Dataplantid 将被处理为按植物 ID 分组并按年份排列,然后将第一次伤害之前的所有观察结果标记为 0,否则为 1,之后它将加入原始数据帧 - 这样我就可以加入带有新变量“第一次受伤之前”的原始数据框。
-
@MKR Every R 中的函数返回一个值(不是“参数”!),包括这个值,尽管函数内部不必要的赋值肯定会产生误导。无论哪种方式,这部分代码都有效。
-
@KonradRudolph 你能分享你有什么吗?我无法让它工作。
-
@KonradRudolph 我的结果是
Error in c(...) %in% list(~c("Rust", "Insect", "Snow break")) : '...' used in an incorrect context
标签: r dplyr purrr rlang tidyeval