여전히 R 논리에 들어 가려고 시도하는 중 … 여러 값을 반환하는 함수의 결과를 압축 해제하는 가장 좋은 방법은 무엇입니까?
나는 분명히 이것을 할 수 없다 :
R> functionReturningTwoValues <- function() { return(c(1, 2)) }
R> functionReturningTwoValues()
[1] 1 2
R> a, b <- functionReturningTwoValues()
Error: unexpected ',' in "a,"
R> c(a, b) <- functionReturningTwoValues()
Error in c(a, b) <- functionReturningTwoValues() : object 'a' not found
내가 정말로 다음을해야합니까?
R> r <- functionReturningTwoValues()
R> a <- r[1]; b <- r[2]
또는 R 프로그래머가 다음과 같은 것을 더 작성하겠습니까?
R> functionReturningTwoValues <- function() {return(list(first=1, second=2))}
R> r <- functionReturningTwoValues()
R> r$first
[1] 1
R> r$second
[1] 2
— Shane의 질문에 답변하도록 편집 —
실제로 결과 값 부분에 이름을 지정할 필요는 없습니다. 하나의 집계 함수를 첫 번째 구성 요소에 적용하고 다른 집계 함수를 두 번째 구성 요소에 적용 min
하고 max
있습니다 ( 및 . 두 구성 요소 에 대해 동일한 기능인 경우 분할 할 필요가 없습니다).
답변
(1) list […] <- 나는 이것을 10 년 전에 r-help 에 게시했습니다 . 그 이후로 gsubfn 패키지에 추가되었습니다. 특수 연산자가 필요하지 않지만 list[...]
다음과 같이 왼쪽을 작성해야합니다 .
library(gsubfn) # need 0.7-0 or later
list[a, b] <- functionReturningTwoValues()
첫 번째 또는 두 번째 구성 요소 만 필요한 경우 모두 작동합니다.
list[a] <- functionReturningTwoValues()
list[a, ] <- functionReturningTwoValues()
list[, b] <- functionReturningTwoValues()
(물론, 경우 당신은 다음 하나 개의 값을 필요로 functionReturningTwoValues()[[1]]
하거나 functionReturningTwoValues()[[2]]
충분할 것이다.)
자세한 예는 인용 된 r-help 스레드를 참조하십시오.
(2) with 의도가 단순히 여러 값을 나중에 결합하고 반환 값의 이름을 지정하는 경우 간단한 대안을 사용하는 것입니다 with
.
myfun <- function() list(a = 1, b = 2)
list[a, b] <- myfun()
a + b
# same
with(myfun(), a + b)
(3) 첨부 다른 대안은 첨부입니다 :
attach(myfun())
a + b
추가 : with
및attach
답변
나는 어떻게 든 인터넷 에서이 영리한 해킹을 우연히 발견했습니다 … 불쾌하거나 아름다운지 확실하지 않지만 여러 반환 값을 자신의 변수에 풀 수있는 “매직”연산자를 만들 수 있습니다. 이 :=
함수 는 여기 에 정의 되어 있으며 후손을 위해 아래에 포함되어 있습니다.
':=' <- function(lhs, rhs) {
frame <- parent.frame()
lhs <- as.list(substitute(lhs))
if (length(lhs) > 1)
lhs <- lhs[-1]
if (length(lhs) == 1) {
do.call(`=`, list(lhs[[1]], rhs), envir=frame)
return(invisible(NULL))
}
if (is.function(rhs) || is(rhs, 'formula'))
rhs <- list(rhs)
if (length(lhs) > length(rhs))
rhs <- c(rhs, rep(list(NULL), length(lhs) - length(rhs)))
for (i in 1:length(lhs))
do.call(`=`, list(lhs[[i]], rhs[[i]]), envir=frame)
return(invisible(NULL))
}
그것을 손에 넣으면 다음과 같은 일을 할 수 있습니다.
functionReturningTwoValues <- function() {
return(list(1, matrix(0, 2, 2)))
}
c(a, b) := functionReturningTwoValues()
a
#[1] 1
b
# [,1] [,2]
# [1,] 0 0
# [2,] 0 0
나는 그것에 대해 어떻게 느끼는지 모르겠다. 대화식 작업 공간에서 도움이 될 수 있습니다. 그것을 사용하여 (재사용 가능한) 라이브러리 (대량 소 비용)를 만드는 것이 가장 좋은 아이디어는 아니지만 그것이 당신에게 달려 있다고 생각합니다.
… 당신은 그들이 책임과 힘에 대해 말하는 것을 알고 있습니다 …
답변
일반적으로 출력을 목록으로 래핑합니다. 매우 유연합니다 (숫자, 문자열, 벡터, 행렬, 배열, 목록, 출력 된 객체의 조합을 가질 수 있음)
그처럼:
func2<-function(input) {
a<-input+1
b<-input+2
output<-list(a,b)
return(output)
}
output<-func2(5)
for (i in output) {
print(i)
}
[1] 6
[1] 7
답변
functionReturningTwoValues <- function() {
results <- list()
results$first <- 1
results$second <-2
return(results)
}
a <- functionReturningTwoValues()
나는 이것이 효과가 있다고 생각한다.
답변
이 문제를 해결하기 위해 R 패키지 zeallot 을 구성했습니다. zeallot에는 다중 할당 또는 포장 풀기 할당 연산자가 포함되어 있습니다 %<-%
. 연산자의 LHS는에 대한 호출을 사용하여 할당 할 변수의 수입니다 c()
. 연산자의 RHS는 벡터, 목록, 데이터 프레임, 날짜 개체 또는 구현 된 destructure
방법이 있는 사용자 지정 개체입니다 (참조 ?zeallot::destructure
).
다음은 원래 게시물을 기반으로 한 몇 가지 예입니다.
library(zeallot)
functionReturningTwoValues <- function() {
return(c(1, 2))
}
c(a, b) %<-% functionReturningTwoValues()
a # 1
b # 2
functionReturningListOfValues <- function() {
return(list(1, 2, 3))
}
c(d, e, f) %<-% functionReturningListOfValues()
d # 1
e # 2
f # 3
functionReturningNestedList <- function() {
return(list(1, list(2, 3)))
}
c(f, c(g, h)) %<-% functionReturningNestedList()
f # 1
g # 2
h # 3
functionReturningTooManyValues <- function() {
return(as.list(1:20))
}
c(i, j, ...rest) %<-% functionReturningTooManyValues()
i # 1
j # 2
rest # list(3, 4, 5, ..)
자세한 내용과 예 는 패키지 비 네트 를 확인하십시오 .
답변
이 질문에 대한 정답은 없습니다. 나는 정말로 당신이 데이터로 무엇을하고 있는지에 달려 있습니다. 위의 간단한 예에서는 다음과 같이 강력하게 제안합니다.
- 가능한 한 간단하게 유지하십시오.
- 가능하면 함수를 벡터화하는 것이 가장 좋습니다. 이는 장기적으로 최대의 유연성과 속도를 제공합니다.
위의 값 1과 2에 이름이 있어야합니까? 다시 말해,이 예제에서 1과 2가 r [1]과 r [2]가 아닌 a와 b로 명명되는 것이 중요한 이유는 무엇입니까? 이 문맥에서 이해해야 할 한 가지 중요한 점은 a와 b 도 길이가 1 인 벡터라는 것입니다. 따라서 첨자를 필요로하지 않는 2 개의 새로운 벡터를 갖는 것 외에는 할당하는 과정에서 아무것도 변경하지 않습니다. 참조 :
> r <- c(1,2)
> a <- r[1]
> b <- r[2]
> class(r)
[1] "numeric"
> class(a)
[1] "numeric"
> a
[1] 1
> a[1]
[1] 1
인덱스보다 문자를 참조하려는 경우 원래 벡터에 이름을 지정할 수도 있습니다.
> names(r) <- c("a","b")
> names(r)
[1] "a" "b"
> r["a"]
a
1
[편집] 각 벡터에 min과 max를 개별적으로 적용한다는 것을 감안할 때 행렬 (a와 b가 동일한 길이와 동일한 데이터 유형 인 경우) 또는 데이터 프레임 (a와 b가 길이는 동일하지만 데이터 유형이 다를 수 있음) 또는 마지막 예와 같이 (길이와 데이터 유형이 다를 수있는 경우) 목록을 사용하십시오.
> r <- data.frame(a=1:4, b=5:8)
> r
a b
1 1 5
2 2 6
3 3 7
4 4 8
> min(r$a)
[1] 1
> max(r$b)
[1] 8
답변
목록은이 목적에 완벽 해 보입니다. 예를 들어 함수 내에서
x = desired_return_value_1 # (vector, matrix, etc)
y = desired_return_value_2 # (vector, matrix, etc)
returnlist = list(x,y...)
} # end of function
메인 프로그램
x = returnlist[[1]]
y = returnlist[[2]]