将列表的元素提取为 r 中自定义函数中的单个参数
Extract the elements of list as individual arguments within custom function in r
我在尝试将参数列表传递给自定义函数时遇到问题,但我希望函数的第一部分检查某些参数是否为 NULL,然后将值赋值为零,如果那是真实的。我发现了一个类似的问题 ,但它并没有帮助我找出我的特定问题。我试图将 4 个参数(aa、bb、dd 和 ff)传递给函数,然后检查 cc 和 ee 是否为 NULL。如果是这样,那么我想在函数的第一部分将 NULL 值(在本例中为 cc 和 ee)定义为零。我认为问题在于解包或取消列出 x 以便函数识别正在传递的参数。
考虑以下代码:
test <- list(aa = 2, bb = 0.5, dd = 2, ff = 16)
testfunc <- function(x, aa=NULL, bb=NULL, cc=NULL, dd=NULL, ee=NULL, ff=NULL) {
unlist(x, recursive = TRUE, use.names = TRUE)
if(!is.null(aa)) aa <- 0
if(!is.null(bb)) bb <- 0
if(!is.null(cc)) cc <- 0
if(!is.null(dd)) dd <- 0
if(!is.null(ee)) ee <- 0
if(!is.null(ff)) ff <- 0
q <- list(aa, bb, cc, dd, ee, ff)
return(q)
}
testfunc(test)
此代码有效,但它 returns 所有 NULL 值。如果我在定义函数时删除所有 NULL 调用,则会出现以下错误,“testfunc(test) 错误:未找到对象 'aa'”
testfunc <- function(x) {
unlist(x, recursive = TRUE, use.names = TRUE)
if(!is.null(aa)) aa <- 0
if(!is.null(bb)) bb <- 0
if(!is.null(cc)) cc <- 0
if(!is.null(dd)) dd <- 0
if(!is.null(ee)) ee <- 0
if(!is.null(ff)) ff <- 0
q <- list(aa, bb, cc, dd, ee, ff)
return(q)
}
testfunc(test)
也许将测试定义为数据框而不是列表会有所帮助?感谢您的帮助!
像这样的事情怎么样:
test <- list(aa = 2, bb = 0.5, dd = 2, ff = 16)
testfunc <- function(x, aa=NULL, bb=NULL, cc=NULL, dd=NULL, ee=NULL, ff=NULL) {
unlist(x, recursive = TRUE, use.names = TRUE)
if(!is.null(aa)) aa <- 0
if(!is.null(bb)) bb <- 0
if(!is.null(cc)) cc <- 0
if(!is.null(dd)) dd <- 0
if(!is.null(ee)) ee <- 0
if(!is.null(ff)) ff <- 0
q <- list(aa, bb, cc, dd, ee, ff)
return(q)
}
testfunc(test)
# $aa
# [1] 2
#
# $bb
# [1] 0.5
#
# $cc
# [1] 0
#
# $dd
# [1] 2
#
# $ee
# [1] 0
#
# $ff
# [1] 16
这是您要找的吗?关键是包装 formals()
in list()
,从而获得 testfunc()
.
的所有(“正式”)参数的命名列表
我对你的问题的解释是,你想将命名列表作为 x
参数传递给 testfunc()
,其中包含命名值以覆盖传递给 testfunc()
的其他参数x
。此列表可能是“不完整的”,因为它不一定命名所有其他参数(如 cc
和 ee
)。那些没有被覆盖的保持原样;除非它们拥有默认值 NULL
,在这种情况下它们将转换为 0
.
使用上面的formals()
,我们可以定义一个testfunc()
testfunc <- function(x, aa = NULL, bb = NULL, cc = NULL, dd = NULL, ee = NULL, ff = NULL) {
# Capture what values were passed to what parameters of 'testfunc()'.
params <- as.list(formals())
param_names <- names(params)
# For convenience, record the named variables listed under 'x'.
x_names <- names(x)
# Process each parameter (besides 'x' itself).
for(p_name in param_names[param_names != "x"]) {
# If the parameter is named in 'x', override it with the value from 'x'.
if(p_name %in% x_names) {
assign(p_name, x[[p_name]])
}
# Otherwise, leave the parameter alone...unless it is NULL and should be
# replaced with 0.
else if(is.null(get(p_name))) {
assign(p_name, 0)
}
}
# ...
# Any further operations; where parameters can be referenced like any other parameter
# in any other function, rather than having to be 'unlist'ed from 'x'.
# ...
# Explicitly name the parameters in the output list.
q <- list(
aa = aa,
bb = bb,
cc = cc,
dd = dd,
ee = ee,
ff = ff
)
return(q)
}
这样调用
test <- list(aa = 2, bb = 0.5, dd = 2, ff = 16)
testfunc(test)
产生以下 list
作为输出:
$aa
[1] 2
$bb
[1] 0.5
$cc
[1] 0
$dd
[1] 2
$ee
[1] 0
$ff
[1] 16
备注
我优先考虑x
。也就是说,我假设您想要在 x
中保留 明确指定 的任何 NULL
。所以明确地给 x
一个 NULL
元素,比如 aa
这里
test <- list(aa = NULL, bb = 0.5, dd = 2, ff = 16)
testfunc(test)
将在输出中为 aa
生成 NULL
:
$aa
NULL
$bb
[1] 0.5
$cc
[1] 0
$dd
[1] 2
$ee
[1] 0
$ff
[1] 16
如果您想覆盖此行为,并确保 any NULL
在输出中被 0
替换,则只需更改 else if
到一个 if
,在函数定义的第 18 行:
# ...
if(is.null(get(p_name))) {
assign(p_name, 0)
}
# ...
提示
您的原始解决方案失败,因为您使用了 !
is.null()
而不是 is.null()
;所以你避免用0
覆盖任何NULL
。
如果您希望 unlist(x)
使用 x
的内容填充 testfunc()
的环境,那您就大错特错了。 unlist()
所做的只是将 x
“扁平化”成其原子组件的(均质化)向量;所以我们得到
x <- list(
a = 1,
list(
b = TRUE,
"hi"
)
)
unlist(x, recursive = TRUE, use.names = TRUE)
#> a b
#> "1" "TRUE" "hi"
均质化为(已命名)character
向量。您的代码惰性地 returns 这个值并继续前进。
只有使用 assign
("a", 1)
(等等)之类的东西,您才能达到将这些值作为命名变量实际填充到您的环境中的效果。
我在尝试将参数列表传递给自定义函数时遇到问题,但我希望函数的第一部分检查某些参数是否为 NULL,然后将值赋值为零,如果那是真实的。我发现了一个类似的问题
考虑以下代码:
test <- list(aa = 2, bb = 0.5, dd = 2, ff = 16)
testfunc <- function(x, aa=NULL, bb=NULL, cc=NULL, dd=NULL, ee=NULL, ff=NULL) {
unlist(x, recursive = TRUE, use.names = TRUE)
if(!is.null(aa)) aa <- 0
if(!is.null(bb)) bb <- 0
if(!is.null(cc)) cc <- 0
if(!is.null(dd)) dd <- 0
if(!is.null(ee)) ee <- 0
if(!is.null(ff)) ff <- 0
q <- list(aa, bb, cc, dd, ee, ff)
return(q)
}
testfunc(test)
此代码有效,但它 returns 所有 NULL 值。如果我在定义函数时删除所有 NULL 调用,则会出现以下错误,“testfunc(test) 错误:未找到对象 'aa'”
testfunc <- function(x) {
unlist(x, recursive = TRUE, use.names = TRUE)
if(!is.null(aa)) aa <- 0
if(!is.null(bb)) bb <- 0
if(!is.null(cc)) cc <- 0
if(!is.null(dd)) dd <- 0
if(!is.null(ee)) ee <- 0
if(!is.null(ff)) ff <- 0
q <- list(aa, bb, cc, dd, ee, ff)
return(q)
}
testfunc(test)
也许将测试定义为数据框而不是列表会有所帮助?感谢您的帮助!
像这样的事情怎么样:
test <- list(aa = 2, bb = 0.5, dd = 2, ff = 16)
testfunc <- function(x, aa=NULL, bb=NULL, cc=NULL, dd=NULL, ee=NULL, ff=NULL) {
unlist(x, recursive = TRUE, use.names = TRUE)
if(!is.null(aa)) aa <- 0
if(!is.null(bb)) bb <- 0
if(!is.null(cc)) cc <- 0
if(!is.null(dd)) dd <- 0
if(!is.null(ee)) ee <- 0
if(!is.null(ff)) ff <- 0
q <- list(aa, bb, cc, dd, ee, ff)
return(q)
}
testfunc(test)
# $aa
# [1] 2
#
# $bb
# [1] 0.5
#
# $cc
# [1] 0
#
# $dd
# [1] 2
#
# $ee
# [1] 0
#
# $ff
# [1] 16
这是您要找的吗?关键是包装 formals()
in list()
,从而获得 testfunc()
.
我对你的问题的解释是,你想将命名列表作为 x
参数传递给 testfunc()
,其中包含命名值以覆盖传递给 testfunc()
的其他参数x
。此列表可能是“不完整的”,因为它不一定命名所有其他参数(如 cc
和 ee
)。那些没有被覆盖的保持原样;除非它们拥有默认值 NULL
,在这种情况下它们将转换为 0
.
使用上面的formals()
,我们可以定义一个testfunc()
testfunc <- function(x, aa = NULL, bb = NULL, cc = NULL, dd = NULL, ee = NULL, ff = NULL) {
# Capture what values were passed to what parameters of 'testfunc()'.
params <- as.list(formals())
param_names <- names(params)
# For convenience, record the named variables listed under 'x'.
x_names <- names(x)
# Process each parameter (besides 'x' itself).
for(p_name in param_names[param_names != "x"]) {
# If the parameter is named in 'x', override it with the value from 'x'.
if(p_name %in% x_names) {
assign(p_name, x[[p_name]])
}
# Otherwise, leave the parameter alone...unless it is NULL and should be
# replaced with 0.
else if(is.null(get(p_name))) {
assign(p_name, 0)
}
}
# ...
# Any further operations; where parameters can be referenced like any other parameter
# in any other function, rather than having to be 'unlist'ed from 'x'.
# ...
# Explicitly name the parameters in the output list.
q <- list(
aa = aa,
bb = bb,
cc = cc,
dd = dd,
ee = ee,
ff = ff
)
return(q)
}
这样调用
test <- list(aa = 2, bb = 0.5, dd = 2, ff = 16)
testfunc(test)
产生以下 list
作为输出:
$aa
[1] 2
$bb
[1] 0.5
$cc
[1] 0
$dd
[1] 2
$ee
[1] 0
$ff
[1] 16
备注
我优先考虑x
。也就是说,我假设您想要在 x
中保留 明确指定 的任何 NULL
。所以明确地给 x
一个 NULL
元素,比如 aa
这里
test <- list(aa = NULL, bb = 0.5, dd = 2, ff = 16)
testfunc(test)
将在输出中为 aa
生成 NULL
:
$aa
NULL
$bb
[1] 0.5
$cc
[1] 0
$dd
[1] 2
$ee
[1] 0
$ff
[1] 16
如果您想覆盖此行为,并确保 any NULL
在输出中被 0
替换,则只需更改 else if
到一个 if
,在函数定义的第 18 行:
# ...
if(is.null(get(p_name))) {
assign(p_name, 0)
}
# ...
提示
您的原始解决方案失败,因为您使用了 !
is.null()
而不是 is.null()
;所以你避免用0
覆盖任何NULL
。
如果您希望 unlist(x)
使用 x
的内容填充 testfunc()
的环境,那您就大错特错了。 unlist()
所做的只是将 x
“扁平化”成其原子组件的(均质化)向量;所以我们得到
x <- list(
a = 1,
list(
b = TRUE,
"hi"
)
)
unlist(x, recursive = TRUE, use.names = TRUE)
#> a b
#> "1" "TRUE" "hi"
均质化为(已命名)character
向量。您的代码惰性地 returns 这个值并继续前进。
只有使用 assign
("a", 1)
(等等)之类的东西,您才能达到将这些值作为命名变量实际填充到您的环境中的效果。