Ainda tentando entrar na lógica R ... qual é a "melhor" maneira de descompactar (no LHS) os resultados de uma função retornando vários valores?
Aparentemente, não posso fazer isso:
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
devo realmente fazer o seguinte?
R> r <- functionReturningTwoValues()
R> a <- r[1]; b <- r[2]
ou o programador R escreveria algo mais parecido com isto:
R> functionReturningTwoValues <- function() {return(list(first=1, second=2))}
R> r <- functionReturningTwoValues()
R> r$first
[1] 1
R> r$second
[1] 2
--- editado para responder às perguntas de Shane ---
Eu realmente não preciso dar nomes às partes do valor resultante. Estou aplicando uma função agregada ao primeiro componente e outra ao segundo componente ( min
e max
. Se fosse a mesma função para os dois componentes, não precisaria dividi-los).
r
return-value
variable-assignment
assign
multiple-results
mariotomo
fonte
fonte
attr
valor de retorno.Respostas:
(1) list [...] <- Eu publiquei isso há mais de uma década no r-help . Desde então, ele foi adicionado ao pacote gsubfn. Não requer um operador especial, mas exige que o lado esquerdo seja escrito usando o
list[...]
seguinte:Se você precisar apenas do primeiro ou do segundo componente, tudo isso funcionará também:
(Claro, se você só precisava de um valor, em seguida,
functionReturningTwoValues()[[1]]
oufunctionReturningTwoValues()[[2]]
seria suficiente.)Veja o tópico r-help citado para mais exemplos.
(2) com Se a intenção é meramente combinar os vários valores subsequentemente e os valores de retorno forem nomeados, uma alternativa simples é usar
with
:(3) anexar Outra alternativa é anexar:
ADICIONADO:
with
eattach
fonte
list
e[<-.result
como mostrado lá?De alguma forma, eu tropecei nesse truque inteligente da Internet ... Não tenho certeza se é desagradável ou bonito, mas permite criar um operador "mágico" que permite descompactar vários valores de retorno em sua própria variável. A
:=
função é definida aqui e incluída abaixo para a posteridade:Com isso em mãos, você pode fazer o que procura:
Não sei como me sinto sobre isso. Talvez você ache útil no seu espaço de trabalho interativo. Usá-lo para criar bibliotecas (re) utilizáveis (para consumo em massa) pode não ser a melhor ideia, mas acho que depende de você.
... você sabe o que eles dizem sobre responsabilidade e poder ...
fonte
:=
operador mucho de uma maneira muito maisNormalmente, envolvo a saída em uma lista, que é muito flexível (você pode ter qualquer combinação de números, seqüências de caracteres, vetores, matrizes, matrizes, listas, objetos na saída)
assim como:
fonte
Eu acho que isso funciona.
fonte
Eu montei um fanático do pacote R para resolver esse problema. O zeallot inclui um operador de atribuição múltipla ou de descompactação
%<-%
,. O LHS do operador é qualquer número de variáveis a serem atribuídas, criadas usando chamadas parac()
. O RHS do operador é um vetor, lista, quadro de dados, objeto de data ou qualquer objeto personalizado com umdestructure
método implementado (consulte?zeallot::destructure
).Aqui estão alguns exemplos baseados na postagem original,
Confira a vinheta do pacote para obter mais informações e exemplos.
fonte
Não há resposta certa para esta pergunta. Eu realmente depende do que você está fazendo com os dados. No exemplo simples acima, eu sugeriria fortemente:
É importante que os valores 1 e 2 acima tenham nomes? Em outras palavras, por que é importante neste exemplo que 1 e 2 sejam nomeados aeb, em vez de apenas r [1] e r [2]? Uma coisa importante a entender neste contexto é que aeb também são vetores de comprimento 1. Portanto, você não está realmente alterando nada no processo de fazer essa atribuição, além de ter 2 novos vetores que não precisam de subscritos para ser referenciado:
Você também pode atribuir os nomes ao vetor original se preferir fazer referência à letra do que ao índice:
[Edit] Como você aplicará min e max a cada vetor separadamente, sugiro usar uma matriz (se aeb tiver o mesmo comprimento e o mesmo tipo de dados) ou quadro de dados (se aeb for o mesmo comprimento, mas podem ser tipos de dados diferentes) ou use uma lista como no seu último exemplo (se eles puderem ter comprimentos e tipos de dados diferentes).
fonte
r[1]
pode ajudar a tornar as coisas mais claras (tudo bem, não se nomes comoa
vierem em seu lugar).As listas parecem perfeitas para esse fim. Por exemplo, dentro da função que você teria
programa principal
fonte
Sim para sua segunda e terceira perguntas - é isso que você precisa fazer, pois não pode ter vários 'valores' à esquerda de uma tarefa.
fonte
Que tal usar o assign?
Você pode passar os nomes da variável que deseja que sejam passados por referência.
Se você precisar acessar os valores existentes, o inverso
assign
éget
.fonte
r <- function() { return(list(first=1, second=2)) }
e faça referência aos resultados usandor$first
er$second
.Se você deseja retornar a saída de sua função para o Global Environment, pode usar
list2env
, como neste exemplo:Esta função criará três objetos no seu ambiente global:
fonte
[A] Se cada foo e barra for um único número, não há nada errado com c (foo, barra); e você também pode nomear os componentes: c (Foo = foo, Bar = bar). Então você pode acessar os componentes do resultado 'res' como res [1], res [2]; ou, no caso nomeado, como res ["Foo"], res ["BAR"].
[B] Se foo e bar são vetores do mesmo tipo e comprimento, então novamente não há nada errado em retornar cbind (foo, bar) ou rbind (foo, bar); igualmente nomeado. No caso 'cbind', você acessaria foo e bar como res [, 1], res [, 2] ou como res [, "Foo"], res [, "Bar"]. Você também pode preferir retornar um quadro de dados em vez de uma matriz:
e acesse-os como res $ Foo, res $ Bar. Isso também funcionaria bem se foo e bar fossem do mesmo comprimento, mas não do mesmo tipo (por exemplo, foo é um vetor de números, exceto um vetor de cadeias de caracteres).
[C] Se foo e bar forem suficientemente diferentes para não combinar convenientemente como acima, você definitivamente retornará uma lista.
Por exemplo, sua função pode ajustar-se a um modelo linear e também calcular valores previstos, para que você possa ter
e então você faria
return list(Foo=foo,Bar=bar)
acessaria o resumo como res $ Foo, os valores previstos como res $ Barfonte: http://r.789695.n4.nabble.com/How-to-return-multiple-values-in-a-function-td858528.html
fonte
Para obter várias saídas de uma função e mantê-las no formato desejado, você pode salvar as saídas no disco rígido (no diretório de trabalho) de dentro da função e carregá-las de fora da função:
fonte
Com o R 3.6.1, eu posso fazer o seguinte
fonte