R语言函数如何返回多个值
问题
之前想尝试一下使用perl中的或者python风格的方式来写R的函数的时候,想返回两个参数
于是就这样写了:
return_two_value <- function(a, b){
return(a, b)
}
运行一下
return_two_value(2, 3)
结果
Error in return(a, b) : multi-argument returns are not permitted
报错了,之前的那种写法不可以,原因是return
不能返回多个值。
于是又想到把这个值存到向量里面再取出来不就好了
return_two_value <- function(a, b){
l <- c(a, b)
return(l)
}
运行
# 先赋值
result <- return_two_value(2, 3)
a <- result[1] # 2
b <- result[2] # 3
这样就可以了,但是有时候函数的返回值根本就不是单个元素,很多时候是向量啊,数据框之类的,这个时候在这么写可以试一下
# 试一下向量
result <- return_two_value(2, c(1,2,3))
a <- result[1] # 2
b <- result[2] # 1
# 试一下数据框
result <- return_two_value(2, data.frame(c("A", "B", "C"), c("a", "b", "c")))
a <- result[1] # [[1]] [1] 2
b <- result[2] # $c..A....B....C.. [1] A B C Levels: A B C
感觉已经乱了乱了!这样做只能用于两个标量的时候,对于传入比较复杂的数据的时候返回结果就不行了,当然你可能也会说把结果放在数据框中,但是数据框会自动填值,也不是个好办法。
解决办法
在stackoverflow上面找到了一个解决办法,它是将数据放在列表里面的。
- 首先写一个示例函数,将返回值放在列表中,并且指明两个返回值的标题
return_two_value <- function(a, b){
# 当然这里为了说明,将返回结果及其简化,你可以按照自己的方式编写然后以类似的方式返回
out <- list(one=a, two=b)
return(out)
}
- 使用
$
根据标题索引两个元素(或者根据位置索引也可以啊)
result <- return_two_value(2, data.frame("group1" = c("A", "B", "C"), "group2" = c("a", "b", "c")))
# 或者 first = result[[1]]
first = result$one # [1] 2
# 或者 second = result[[2]]
second = result$two
# group1 group2
# 1 A a
# 2 B b
# 3 C c
😵试了试排名第一的回答,发现这样做好像不好使
library(gsubfn)
return_two_value <- function(a, b){
out <- list(one=a, two=b)
return(out)
}
list[first, second] = return_two_value(2, data.frame("group1" = c("A", "B", "C"), "group2" = c("a", "b", "c")))
好像报错了,不知道是我没有安装某些依赖的包,不过上面那种直接索引的方式还是可以的。
实际应用
之前是因为想写一个类似于perl中的shift
或者python中pop
的功能的函数,这个函数就是将一个数组(对应到R中可能就是向量)中的第一个元素取出并且返回。
- python
l = [1, 2, 3, 4]
l.pop(0)
print(l) # [2, 3, 4]
- perl
my @list = (1, 2, 3, 4);
shift(@list);
print join(",", @list); # 2,3,4
我首先是这么写的
- R
l <- c(1, 2, 3, 4)
# 传入一个向量
shift <- function(l) {
first = l[1]
a = l[-1]
return(first)
}
i <- shift(l) # [1] 1
print(l) # [1] 1 2 3 4
我是先拿到第一个元素first = l[1]
,然后去除第一个元素a = l[-1]
,但是后来发现传入的向量并没有发生更改,就是函数好像不能改变外部的变量。
后来就尝试使用另外一种方式,就是返回两个东西,代码已经在开头示出了。
后来尝试新的方法写了一下
l <- c(1, 2, 3, 4)
shift <- function(l) {
first = l[1]
a = l[-1]
return( list( one=first, two=a ) )
}
result <- shift(l)
first_item <- result$one # [1] 1
# 这个时候再将返回值赋值给l
l <- result$two # [1] 2 3 4
这种方法我想在处理大文件的时候可能不快,但是好歹也算弄出来了。
方法来源
- stackoverflow - How to assign from a function which returns more than one value?
参考
- philzang的回答 - R 如何实现 向量中某个元素的删除?