code

둘 이상의 값을 반환하는 함수에서 할당하는 방법은 무엇입니까?

starcafe 2023. 7. 2. 20:52
반응형

둘 이상의 값을 반환하는 함수에서 할당하는 방법은 무엇입니까?

아직도 R 논리로 들어가려는 중...여러 값을 반환하는 함수의 결과를 "가장 좋은" 방법은 무엇입니까(LHS에서)?

나는 분명히 이것을 할 수 없습니다:

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

셰인의 질문에 답하도록 편집되었습니다 ---

결과 값 부분에 이름을 붙일 필요가 없습니다.는 첫 요소에 하고 두 구성요소에 의 집계 함수를 적용하고 (저는첫번구요성하있소집습다니적두고용하함다수).min그리고.max두 구성 요소 모두에 대해 동일한 기능이면 분할할 필요가 없습니다.)

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 스레드를 참조하십시오.

단순히 여러 값을 나중에 결합하고 반환 값의 이름을 지정하는 것이 목적이라면 간단한 대안은 다음과 같습니다.with:

myfun <- function() list(a = 1, b = 2)

list[a, b] <- myfun()
a + b

# same
with(myfun(), a + b)

attach 다른 대안은 attach:

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

저는 이 문제를 해결하기 위해 R 패키지 zealot을 만들었습니다. zealot은 다중 할당 또는 할당 해제 연산자를 포함합니다.%<-%로, 연자의 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, ..)

자세한 정보와 예제는 패키지 vignett을 확인하십시오.

functionReturningTwoValues <- function() { 
  results <- list()
  results$first <- 1
  results$second <-2
  return(results) 
}
a <- functionReturningTwoValues()

효과가 있는 것 같아요.

이 질문에는 정답이 없습니다.저는 정말로 당신이 데이터로 무엇을 하는지에 달려있습니다.위의 간단한 예에서, 저는 강력하게 제안하고 싶습니다.

  1. 가능한 한 일을 단순하게 하세요.
  2. 가능한 한 기능을 벡터화하는 것이 좋습니다.이는 장기적으로 볼 때 최고의 유연성과 속도를 제공합니다.

위의 값 1과 2가 이름을 갖는 것이 중요합니까?다시 말해서, 이 예에서 1과 2를 단순히 r[1]과 r[2]가 아닌 a와 b로 명명하는 것이 왜 중요합니까?이 맥락에서 이해해야 할 중요한 한 가지는 a와 b가 모두 길이 1의 벡터라는 것입니다.따라서 할당 과정에서 서브스크립션을 참조할 필요가 없는 두 개의 새로운 벡터를 사용하는 것 외에는 실제로 변경할 수 있는 것이 없습니다.

> 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

을 Global Environment로 함의출글환되로돌다면려사수있다용습니할음을을 하면 됩니다.list2env예를 들어 다음과 같습니다.

myfun <- function(x) { a <- 1:x
                       b <- 5:x
                       df <- data.frame(a=a, b=b)

                       newList <- list("my_obj1" = a, "my_obj2" = b, "myDF"=df)
                       list2env(newList ,.GlobalEnv)
                       }
    myfun(3)

이 함수는 글로벌 환경에 다음과 같은 세 가지 개체를 만듭니다.

> my_obj1
  [1] 1 2 3

> my_obj2
  [1] 5 4 3

> myDF
    a b
  1 1 5
  2 2 4
  3 3 3

목록은 이 목적에 완벽한 것으로 보입니다.예를 들어 함수 내에서는

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]]

두 번째와 세 번째 질문에는 "예"입니다. 과제 왼쪽에 여러 개의 'l값'이 있을 수 없기 때문에 이를 수행해야 합니다.

assign을 사용하는 것은 어떻습니까?

functionReturningTwoValues <- function(a, b) {
  assign(a, 1, pos=1)
  assign(b, 2, pos=1)
}

참조로 전달할 변수의 이름을 전달할 수 있습니다.

> functionReturningTwoValues('a', 'b')
> a
[1] 1
> b
[1] 2

기존 값에 액세스해야 하는 경우, 반대로assign이라get.

2021년 그리고 이것은 제가 자주 사용하는 것입니다.

tidyverse패키지에는 다음과 같은 기능이 있습니다.lst목록을 만들 때 목록 요소에 이름을 할당합니다.내가 사용하는 게시물list2env()변수를 할당하거나 목록을 직접 사용합니다.

library(tidyverse)
fun <- function(){
  a<-1
  b<-2
  lst(a,b)
}
list2env(fun(), envir=.GlobalEnv)#unpacks list key-values to variable-values into the current environment

foo와 bar가 각각 하나의 숫자일 경우 c(foo, bar)에는 아무런 문제가 없으며 구성 요소의 이름을 c(Foo=foo, Bar=bar)로 지정할 수도 있습니다.따라서 결과 'res'의 구성 요소를 res[1], res[2] 또는 이름이 지정된 경우 res["Foo"], res["BAR"].

foo와 bar가 같은 유형과 길이의 벡터라면 cbind(foo, bar) 또는 rbind(foo, bar)를 반환해도 문제가 없습니다. 마찬가지로 이름을 지정할 수 있습니다.'cbind'의 경우 foo 및 bar asres[,1], res[,2] 또는 res[,"Foo", res[,"Bar"]에 액세스합니다.또한 행렬 대신 데이터 프레임을 반환하는 것이 좋습니다.

data.frame(Foo=foo,Bar=bar)

res$Foo, res$Bar로 액세스합니다.foo와 bar가 같은 길이이지만 같은 유형이 아닌 경우에도 잘 작동합니다(예: foo는 숫자의 벡터, bar는 문자열의 벡터).

위와 같이 foo와 bar가 쉽게 결합할 수 없을 정도로 충분히 다르다면, 당신은 반드시 목록을 반환해야 합니다.

예를 들어, 함수가 선형 모형을 적합하고 예측 값을 계산할 수 있으므로 다음과 같은 방법을 사용할 수 있습니다.

LM<-lm(....) ; foo<-summary(LM); bar<-LM$fit

그리고 나서 당신은return list(Foo=foo,Bar=bar)그런 다음 요약을 res$Foo로 액세스하고 예측 값을 res$Bar로 액세스합니다.

출처: http://r.789695.n4.nabble.com/How-to-return-multiple-values-in-a-function-td858528.html

이것은 단지 완성도를 위한 것일 뿐, 제가 개인적으로 선호하기 때문이 아닙니다.피리를 불 수 있습니다.%>%결과를 곱슬곱슬하게 교정하여 평가합니다.{}그리고 이중 변수를 사용하여 상위 환경에 변수를 수행합니다.<<-.

library(tidyverse)
functionReturningTwoValues() %>% {a <<- .[1]; b <<- .[2]}

업데이트: 에서 다중 할당 연산자를 사용할 수도 있습니다.zeallot 패지키:%<-%

c(a, b) %<-% list(0, 1)

벡터를 통해 여러 개체를 반환하는 함수를 게시합니다.

Median <- function(X){
  X_Sort <- sort(X)
  if (length(X)%%2==0){
    Median <- (X_Sort[(length(X)/2)]+X_Sort[(length(X)/2)+1])/2
  } else{
    Median <- X_Sort[(length(X)+1)/2]
  }
  return(Median)
}

이것은 중위수를 계산하기 위해 만든 함수입니다.나는 R에 내장된 기능이 있다는 것을 알고 있습니다.median()그러나 그럼에도 불구하고 나는 그것을 사용하여 숫자 데이터 세트의 사분위수를 계산하는 다른 함수를 구축하도록 프로그래밍했습니다.Median()내가 방금 프로그래밍한 기능.Median()기능은 다음과 같이 작동합니다.

  1. 숫자 벡터인 경우X 짝수개즉요소의즉(요,length(X)%%2==0을 통해 됩니다.sort(X)[length(X)/2]그리고.sort(X)[(length(X)/2+1)].
  2. 한다면X의 원소가는 짝수 개 원 없 가 습 니 다 소 의 니 다 ▁doesn 없습 ,입니다. 중위수는sort(X)[(length(X)+1)/2].

로 합니다.QuartilesFunction():

QuartilesFunction <- function(X){
X_Sort <- sort(X) # Data is sorted in ascending order

if (length(X)%%2==0){
  
  # Data number is even
  
  HalfDN <- X_Sort[1:(length(X)/2)] 
  HalfUP <- X_Sort[((length(X)/2)+1):length(X)]
  
  QL <- Median(HalfDN)
  QU <- Median(HalfUP)
  
  QL1 <- QL
  QL2 <- QL
  QU1 <- QU
  QU2 <- QU
  QL3 <- QL
  QU3 <- QU
  
  Quartiles <- c(QL1,QU1,QL2,QU2,QL3,QU3)
  names(Quartiles) = c("QL (1)", "QU (1)", "QL (2)", "QU (2)","QL (3)", "QU (3)")
  
} else{ # Data number is odd
  
  # Including the median
  
  Half1DN <- X_Sort[1:((length(X)+1)/2)] 
  Half1UP <- X_Sort[(((length(X)+1)/2)):length(X)]
  
  QL1 <- Median(Half1DN)
  QU1 <- Median(Half1UP)
  
  # Not including the median
  
  Half2DN <- X_Sort[1:(((length(X)+1)/2)-1)] 
  Half2UP <- X_Sort[(((length(X)+1)/2)+1):length(X)]
  
  QL2 <- Median(Half2DN)
  QU2 <- Median(Half2UP)
  
  # Methods (1) and (2) averaged
  
  QL3 <- (QL1+QL2)/2
  QU3 <- (QU1+QU2)/2
  
  Quartiles <- c(QL1,QU1,QL2,QU2,QL3,QU3)
  names(Quartiles) = c("QL (1)", "QU (1)", "QL (2)", "QU (2)","QL (3)", "QU (3)") 
}
return(Quartiles)
}

이 함수는 다음 세 가지 방법을 사용하여 숫자 벡터의 사분위수를 반환합니다.

  1. 숫자 벡터의 요소 수가 많은 경우 사분위수 계산을 위한 중위수 삭제X이상합니다.
  2. 숫자 벡터의 요소 수에 대한 사분위수 계산을 위한 중위수 유지X이상합니다.
  3. 방법 1과 방법 2를 사용하여 얻은 결과의 평균화.

숫자 벡터의 요소 수가 다음과 같을 때X짝수입니다. 세 가지 방법이 일치합니다.

『 』 『 』의입니다.QuartilesFunction()는 개요에 설명된 세 가지 방법을 사용하여 계산된 첫 번째 및 세 번째 사분위수를 나타내는 벡터입니다.

R 3.6.1을 사용하여 다음을 수행할 수 있습니다.

fr2v <- function() { c(5,3) }
a_b <- fr2v()
(a_b[[1]]) # prints "5"
(a_b[[2]]) # prints "3"

함수에서 여러 출력을 가져와 원하는 형식으로 유지하려면 함수 내에서 출력을 하드 디스크(작업 디렉토리)에 저장한 다음 함수 외부에서 로드할 수 있습니다.

myfun <- function(x) {
                      df1 <- ...
                      df2 <- ...
                      save(df1, file = "myfile1")
                      save(df2, file = "myfile2")
}
load("myfile1")
load("myfile2")

언급URL : https://stackoverflow.com/questions/1826519/how-to-assign-from-a-function-which-returns-more-than-one-value

반응형