R 함수에서 선택적 인수를 지정하는 "올바른" 방법
저는 R에서 선택적 인수로 함수를 작성하는 "정확한" 방법이 무엇인지 관심이 있습니다.시간이 지나면서, 저는 여기서 다른 경로를 사용하는 몇 개의 코드를 우연히 발견했고, 이 주제에 대한 적절한 (공식적인) 입장을 찾을 수 없었습니다.
지금까지 저는 다음과 같은 선택적 인수를 작성했습니다.
fooBar <- function(x,y=NULL){
if(!is.null(y)) x <- x+y
return(x)
}
fooBar(3) # 3
fooBar(3,1.5) # 4.5
함수는 다음과 같은 경우 인수를 반환합니다.x
공급됩니다.기본값을 사용합니다.NULL
두 번째 인수에 대한 값 및 해당 인수가 아닐 경우NULL
그런 다음 함수는 두 숫자를 추가합니다.
또는 함수를 다음과 같이 쓸 수 있습니다(여기서 두 번째 인수는 이름으로 지정해야 하지만 하나는 이름으로 지정할 수도 있습니다).unlist(z)
또는 정의z <- sum(...)
대신):
fooBar <- function(x,...){
z <- list(...)
if(!is.null(z$y)) x <- x+z$y
return(x)
}
fooBar(3) # 3
fooBar(3,y=1.5) # 4.5
개인적으로 저는 첫 번째 버전을 선호합니다.하지만, 저는 둘 다 좋은 점과 나쁜 점을 볼 수 있습니다.첫 번째 버전은 오류 발생 가능성이 약간 낮지만 두 번째 버전은 임의의 수의 옵션을 통합하는 데 사용될 수 있습니다.
R에서 선택적 인수를 지정하는 "올바른" 방법이 있습니까?지금까지 저는 첫 번째 접근법을 결정했지만, 둘 다 가끔 약간 "해키"하다고 느낄 수 있습니다.
사용할 수도 있습니다.missing()
주장의 여부를 시험해 보다y
제공됨:
fooBar <- function(x,y){
if(missing(y)) {
x
} else {
x + y
}
}
fooBar(3,1.5)
# [1] 4.5
fooBar(3)
# [1] 3
솔직히 저는 OP의 첫 번째 방법을 좋아합니다.NULL
값을 매긴 다음 확인합니다.is.null
(매우 간단하고 이해하기 쉽기 때문에 가능합니다.사람들이 코딩에 익숙한 방식에 따라 다를 수 있지만 해들리는 그것을 지지하는 것 같습니다.is.null
방법도:
Hadley의 책 "Advanced-R" 6장, Functions, p.84 (여기서 온라인 버전 확인)에서:
인수가 missing() 함수와 함께 제공되었는지 여부를 확인할 수 있습니다.
i <- function(a, b) {
c(missing(a), missing(b))
}
i()
#> [1] TRUE TRUE
i(a = 1)
#> [1] FALSE TRUE
i(b = 2)
#> [1] TRUE FALSE
i(1, 2)
#> [1] FALSE FALSE
계산하는 데 여러 줄의 코드가 필요할 수 있는 사소한 기본값을 추가하려는 경우가 있습니다.함수 정의에 코드를 삽입하는 대신 missing()을 사용하여 필요한 경우 조건부로 코드를 계산할 수 있습니다.그러나 문서를 주의 깊게 읽지 않으면 어떤 인수가 필요하고 어떤 인수가 선택적인지 알 수 없습니다. 대신, 저는 보통 기본값을 NULL로 설정하고 is.null()을 사용하여 인수가 제공되었는지 확인합니다.
제 경험칙은 다음과 같습니다.
다른 파라미터에서 기본값을 계산할 수 있는 경우 다음과 같이 기본 식을 사용합니다.
fun <- function(x,levels=levels(x)){
blah blah blah
}
달리 missing을 사용하는 경우
fun <- function(x,levels){
if(missing(levels)){
[calculate levels here]
}
blah blah blah
}
드물게 사용자가 전체 R 세션을 지속하는 기본값을 지정할 수도 있습니다.getOption
fun <- function(x,y=getOption('fun.y','initialDefault')){# or getOption('pkg.fun.y',defaultValue)
blah blah blah
}
첫 번째 인수의 클래스에 따라 일부 매개 변수가 적용되는 경우 S3 제네릭을 사용합니다.
fun <- function(...)
UseMethod(...)
fun.character <- function(x,y,z){# y and z only apply when x is character
blah blah blah
}
fun.numeric <- function(x,a,b){# a and b only apply when x is numeric
blah blah blah
}
fun.default <- function(x,m,n){# otherwise arguments m and n apply
blah blah blah
}
사용하다...
합니다.
cat0 <- function(...)
cat(...,sep = '')
한다면, 사막선택할경, 을우로으용지마....
점을 다른 함수에 전달하지 않고 사용자에게 사용하지 않는 매개 변수를 무시하고 있음을 경고합니다. 그렇지 않으면 매우 혼란스러울 수 있습니다.
fun <- (x,...){
params <- list(...)
optionalParamNames <- letters
unusedParams <- setdiff(names(params),optionalParamNames)
if(length(unusedParams))
stop('unused parameters',paste(unusedParams,collapse = ', '))
blah blah blah
}
여러 가지 옵션이 있지만 공식적인 올바른 방법은 없으며, 컴퓨터와 코드를 읽는 다른 사람에게 다른 정보를 전달할 수 있지만 실제로는 잘못된 옵션은 없습니다.
주어진 예에서 가장 명확한 옵션은 ID 기본값을 제공하는 것입니다. 이 경우 다음과 같은 작업을 수행하십시오.
fooBar <- function(x, y=0) {
x + y
}
이는 지금까지 표시된 옵션 중 가장 짧은 것이며 짧은 것이 가독성(때로는 실행 속도)에 도움이 될 수 있습니다.반환되는 것이 x와 y의 합이라는 것은 분명하며 y에 0이 되는 값이 주어지지 않는다는 것을 알 수 있습니다. x에 더하면 x가 됩니다. 분명히 덧셈보다 더 복잡한 것이 사용되면 (존재하는 경우) 다른 ID 값이 필요합니다.
이 접근 방식에 대해 제가 정말 좋아하는 한 가지는 사용할 때 기본값이 무엇인지 명확하다는 것입니다.args
기능 또는 도움말 파일을 볼 수도 있습니다(세부 정보로 스크롤할 필요가 없습니다. 바로 사용법에 있습니다).
때 (코드가 할 때) 수 입니다.missing
또는NULL
접근 방식이 훨씬 더 합리적이 됩니다.
함수로 될 때 할 때 의 다른 중 .match.call
또는sys.call
기능들.
그래서 저는 "정확한" 방법은 당신이 그 특정한 주장으로 무엇을 할 계획인지 그리고 당신의 코드의 독자들에게 어떤 정보를 전달하고 싶은지에 달려있다고 생각합니다.
단지 그 내장된 것이sink
함수에는 함수에서 인수를 설정하는 다양한 방법의 좋은 예가 있습니다.
> sink
function (file = NULL, append = FALSE, type = c("output", "message"),
split = FALSE)
{
type <- match.arg(type)
if (type == "message") {
if (is.null(file))
file <- stderr()
else if (!inherits(file, "connection") || !isOpen(file))
stop("'file' must be NULL or an already open connection")
if (split)
stop("cannot split the message connection")
.Internal(sink(file, FALSE, TRUE, FALSE))
}
else {
closeOnExit <- FALSE
if (is.null(file))
file <- -1L
else if (is.character(file)) {
file <- file(file, ifelse(append, "a", "w"))
closeOnExit <- TRUE
}
else if (!inherits(file, "connection"))
stop("'file' must be NULL, a connection or a character string")
.Internal(sink(file, closeOnExit, FALSE, split))
}
}
저는 무엇이 필요하고 무엇이 선택 사항인지 명확하게 하기 위해 NULL을 사용하는 것을 선호합니다.Jthorpe가 제안한 것처럼 다른 인수에 의존하는 기본값을 사용하는 것에 대한 경고의 한 마디.함수가 호출될 때 값이 설정되지 않고 인수가 처음 참조될 때 값이 설정됩니다!예를 들어:
foo <- function(x,y=length(x)){
x <- x[1:10]
print(y)
}
foo(1:20)
#[1] 10
반면 x를 변경하기 전에 y를 참조하는 경우:
foo <- function(x,y=length(x)){
print(y)
x <- x[1:10]
}
foo(1:20)
#[1] 20
함수의 초기에 호출되지 않은 것처럼 초기화되는 "y"를 추적하는 것이 어렵기 때문에 이것은 약간 위험합니다.
이건 어때?
fun <- function(x, ...){
y=NULL
parms=list(...)
for (name in names(parms) ) {
assign(name, parms[[name]])
}
print(is.null(y))
}
그런 다음 시도:
> fun(1,y=4)
[1] FALSE
> fun(1)
[1] TRUE
언급URL : https://stackoverflow.com/questions/28370249/correct-way-to-specifiy-optional-arguments-in-r-functions
'programing' 카테고리의 다른 글
mongoimport를 사용하여 1개 이상의 json 파일 가져오기 (0) | 2023.06.22 |
---|---|
AWS boto와 boto3의 차이점은 무엇입니까? (0) | 2023.06.22 |
C/C++의 프로젝트에 대한 메이크 파일에 대한 종속성 생성 (0) | 2023.06.22 |
(또는 기타 및 기타) 및 (및 기타) - 언제 사용해야 합니까? (0) | 2023.06.22 |
Angular2 - 데바운스 시간이 있는 테스트 호출 (0) | 2023.06.22 |