如何从返回多个值的函数进行赋值?
仍在尝试进入 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
--- 编辑以回答 Shane 的问题 ---
我真的不需要为结果值部分命名。我将一个聚合函数应用于第一个组件,另一个聚合函数应用于第二个组件(min
和 max
。如果这两个组件的函数相同,则不需要拆分他们)。
Still trying to get into the R logic... what is the "best" way to unpack (on LHS) the results from a function returning multiple values?
I can't do this apparently:
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
must I really do the following?
R> r <- functionReturningTwoValues()
R> a <- r[1]; b <- r[2]
or would the R programmer write something more like this:
R> functionReturningTwoValues <- function() {return(list(first=1, second=2))}
R> r <- functionReturningTwoValues()
R> r$first
[1] 1
R> r$second
[1] 2
--- edited to answer Shane's questions ---
I don't really need giving names to the result value parts. I am applying one aggregate function to the first component and an other to the second component (min
and max
. if it was the same function for both components I would not need splitting them).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(17)
(1) list[...]<- 我十多年前在 r-帮助。从那时起它就被添加到 gsubfn 包中。它不需要特殊的运算符,但需要使用
list[...]
编写左侧,如下所示:如果您只需要第一个或第二个组件,那么这些都可以工作:
(Of当然,如果您只需要一个值,则
functionReturningTwoValues()[[1]]
或functionReturningTwoValues()[[2]]
就足够了。)请参阅引用的 r-帮助线程以获取更多示例。
(2) with 如果目的只是随后组合多个值并且返回值被命名,那么一个简单的替代方法是使用
with
:(3)另一种选择是附加:
添加:
with
和attach
(1) list[...]<- I had posted this over a decade ago on r-help. Since then it has been added to the gsubfn package. It does not require a special operator but does require that the left hand side be written using
list[...]
like this:If you only need the first or second component these all work too:
(Of course, if you only needed one value then
functionReturningTwoValues()[[1]]
orfunctionReturningTwoValues()[[2]]
would be sufficient.)See the cited r-help thread for more examples.
(2) with If the intent is merely to combine the multiple values subsequently and the return values are named then a simple alternative is to use
with
:(3) attach Another alternative is attach:
ADDED:
with
andattach
我在互联网上偶然发现了这个聪明的黑客......我不确定它是令人讨厌还是美丽,但它可以让你创建一个“神奇”运算符,允许你将多个返回值解压到它们自己的变量中。
:=
函数在此处定义< /a>,并包含在下面供后代使用:有了它,你就可以做你想做的事:
我不知道我对此有何感受。也许您可能会发现它对您的交互式工作区很有帮助。使用它来构建(重新)可用的库(用于大众消费)可能不是最好的主意,但我想这取决于你。
...你知道他们如何谈论责任和权力...
I somehow stumbled on this clever hack on the internet ... I'm not sure if it's nasty or beautiful, but it lets you create a "magical" operator that allows you to unpack multiple return values into their own variable. The
:=
function is defined here, and included below for posterity:With that in hand, you can do what you're after:
I don't know how I feel about that. Perhaps you might find it helpful in your interactive workspace. Using it to build (re-)usable libraries (for mass consumption) might not be the best idea, but I guess that's up to you.
... you know what they say about responsibility and power ...
通常我将输出包装到一个列表中,这是非常灵活的(你可以在输出中使用数字、字符串、向量、矩阵、数组、列表、对象的任意组合),
如下所示:
Usually I wrap the output into a list, which is very flexible (you can have any combination of numbers, strings, vectors, matrices, arrays, lists, objects int he output)
so like:
我整理了一个 R 包 zeallot 来解决这个问题。 zeallot 包含多重赋值或解包赋值运算符
%<-%
。运算符的 LHS 是要分配的任意数量的变量,通过调用c()
构建。运算符的 RHS 是向量、列表、数据框、日期对象或任何具有已实现的destruct
方法的自定义对象(请参阅?zeallot::destruct
)。以下是基于原始帖子的一些示例,
请查看包 vignette 了解更多信息和示例。
I put together an R package zeallot to tackle this problem. zeallot includes a multiple assignment or unpacking assignment operator,
%<-%
. The LHS of the operator is any number of variables to assign, built using calls toc()
. The RHS of the operator is a vector, list, data frame, date object, or any custom object with an implementeddestructure
method (see?zeallot::destructure
).Here are a handful of examples based on the original post,
Check out the package vignette for more information and examples.
我认为这有效。
I think this works.
这个问题没有正确答案。我真的取决于你对数据的处理方式。在上面的简单示例中,我强烈建议:
上面的值 1 和 2 有名称重要吗?换句话说,为什么在这个例子中将 1 和 2 命名为 a 和 b 而不仅仅是 r[1] 和 r[2] 很重要?在这种情况下需要理解的一件重要的事情是,a 和 b 也是长度为 1 的向量。因此,除了拥有 2 个新向量之外,在进行分配的过程中您并没有真正改变任何内容不需要引用下标:
如果您宁愿引用字母而不是索引,也可以将名称分配给原始向量:
[编辑] 鉴于您将应用最小值和最大值分别对于每个向量,我建议使用矩阵(如果 a 和 b 具有相同的长度和相同的数据类型)或数据帧(如果 a 和 b 具有相同的长度但可以是不同的数据类型),否则使用上一个示例中的列表(如果它们可以具有不同的长度和数据类型)。
There's no right answer to this question. I really depends on what you're doing with the data. In the simple example above, I would strongly suggest:
Is it important that the values 1 and 2 above have names? In other words, why is it important in this example that 1 and 2 be named a and b, rather than just r[1] and r[2]? One important thing to understand in this context is that a and b are also both vectors of length 1. So you're not really changing anything in the process of making that assignment, other than having 2 new vectors that don't need subscripts to be referenced:
You can also assign the names to the original vector if you would rather reference the letter than the index:
[Edit] Given that you will be applying min and max to each vector separately, I would suggest either using a matrix (if a and b will be the same length and the same data type) or data frame (if a and b will be the same length but can be different data types) or else use a list like in your last example (if they can be of differing lengths and data types).
如果要将函数的输出返回到全局环境,可以使用
list2env
,如下例所示:此函数将在全局环境中创建三个对象:
If you want to return the output of your function to the Global Environment, you can use
list2env
, like in this example:This function will create three objects in your Global Environment:
列表似乎非常适合此目的。例如,在函数中,您将有
主程序
Lists seem perfect for this purpose. For example within the function you would have
main program
对你的第二个问题和第三个问题是的——这就是你需要做的,因为你不能在作业的左侧有多个“左值”。
Yes to your second and third questions -- that's what you need to do as you cannot have multiple 'lvalues' on the left of an assignment.
使用分配怎么样?
您可以传递要通过引用传递的变量的名称。
如果您需要访问现有值,
assign
的逆过程是get
。How about using assign?
You can pass the names of the variable you want to be passed by reference.
If you need to access the existing values, the converse of
assign
isget
.2021 年,这是我经常使用的东西。
tidyverse
包有一个名为lst
的函数,它在创建列表时为列表元素分配名称。发布我使用
list2env()
分配变量或直接使用列表Year 2021 and this is something I frequently use.
tidyverse
package has a function calledlst
that assigns name to the list elements when creating the list.Post which I use
list2env()
to assign variable or use the list directly[一个]
如果 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 作为 res[,1]、res[,2] 或 res[,"Foo"]、res[,"Bar"] 访问。您可能还更喜欢返回数据帧而不是矩阵:
并以 res$Foo、res$Bar 的形式访问它们。如果 foo 和 bar 的长度相同但类型不同(例如 foo 是数字向量,bar 是字符串向量),这也可以很好地工作。
[C]
如果 foo 和 bar 有足够的不同而不能像上面那样方便地组合,那么你肯定应该返回一个列表。
例如,您的函数可能适合线性模型并且
还可以计算预测值,因此您可以
返回 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
[A]
If each of foo and bar is a single number, then there's nothing wrong with c(foo,bar); and you can also name the components: c(Foo=foo,Bar=bar). So you could access the components of the result 'res' as res[1], res[2]; or, in the named case, as res["Foo"], res["BAR"].
[B]
If foo and bar are vectors of the same type and length, then again there's nothing wrong with returning cbind(foo,bar) or rbind(foo,bar); likewise nameable. In the 'cbind' case, you would access foo and bar as res[,1], res[,2] or as res[,"Foo"], res[,"Bar"]. You might also prefer to return a dataframe rather than a matrix:
and access them as res$Foo, res$Bar. This would also work well if foo and bar were of the same length but not of the same type (e.g. foo is a vector of numbers, bar a vector of character strings).
[C]
If foo and bar are sufficiently different not to combine conveniently as above, then you shuld definitely return a list.
For example, your function might fit a linear model and
also calculate predicted values, so you could have
and then you would
return list(Foo=foo,Bar=bar)
and then access the summary as res$Foo, the predicted values as res$Barsource: http://r.789695.n4.nabble.com/How-to-return-multiple-values-in-a-function-td858528.html
这只是为了完整性,而不是因为我个人更喜欢它。您可以通过管道传输
%>%
结果,使用大括号{}
对其进行评估,并使用双箭头<<- 将变量写入父环境
。更新:
您还可以使用
zeallot
包中的多重赋值运算符::%<-%
This is only for the sake of completeness and not because I personally prefer it. You can pipe
%>%
the result, evaluate it with curly braces{}
and write variables to the parent environment using double-arrow<<-
.UPDATE:
Your can also use the multiple assignment operator from the
zeallot
package::%<-%
我将发布一个通过向量返回多个对象的函数:
这是我创建的用于计算中位数的函数。我知道 R 中有一个名为
median()
的内置函数,但我仍然对其进行编程来构建其他函数,以使用Median()
计算数值数据集的四分位数code> 我刚刚编写的函数。Median()
函数的工作原理如下:X
具有偶数个元素(即length(X)%%2==0
),中位数是通过对元素sort(X)[length(X)/2]
和sort(X)[(length(X)/2+) 求平均值来计算的1)]
。关于
QuartilesFunction()
:该函数使用三种方法返回数值向量的四分位数:
X 时,丢弃计算四分位数的中位数很奇怪。
当数值向量
X
中的元素个数为偶数时,三种方法一致。QuartilesFunction()
的结果是一个向量,描述使用上述三种方法计算出的第一和第三四分位数。I will post a function that returns multiple objects by way of vectors:
That was a function I created to calculate the median. I know that there's an inbuilt function in R called
median()
but nonetheless I programmed it to build other function to calculate the quartiles of a numeric data-set by using theMedian()
function I just programmed. TheMedian()
function works like this:X
has an even number of elements (i.e.,length(X)%%2==0
), the median is calculated by averaging the elementssort(X)[length(X)/2]
andsort(X)[(length(X)/2+1)]
.X
doesn't have an even number of elements, the median issort(X)[(length(X)+1)/2]
.On to the
QuartilesFunction()
:This function returns the quartiles of a numeric vector by using three methods:
X
is odd.X
is odd.When the number of elements in the numeric vector
X
is even, the three methods coincide.The result of the
QuartilesFunction()
is a vector that depicts the first and third quartiles calculated by using the three methods outlined.keas 库与 zeallot 具有类似的功能:
The keas library has similar functionality to zeallot:
要从函数获取多个输出并将它们保留为所需的格式,您可以从函数内部将输出保存到硬盘(在工作目录中),然后从函数外部加载它们:
To obtain multiple outputs from a function and keep them in the desired format you can save the outputs to your hard disk (in the working directory) from within the function and then load them from outside the function:
使用 R 3.6.1,我可以执行以下操作
With R 3.6.1, I can do the following