如何正确使用R中的列表?
简要背景:广泛使用的许多(大多数?)当代编程语言至少具有少数ADT [抽象数据类型],特别是,
字符串 (由字符组成的序列)
列表 (一个有序的值集合)和
基于地图的类型 (将键映射到值的无序数组)
在R编程语言中,前两个分别实现为character
和vector
。
当我开始学习R时,几乎从一开始就有两件事情是明显的: list
是R中最重要的数据类型(因为它是R data.frame
的父类),其次,我无法理解它们是如何工作,至少不够好,以便在我的代码中正确使用它们。
首先,在我看来,R的list
数据类型是ADT(Python中的dictionary
,Objective C中的NSMutableDictionary
,Perl和Ruby中的hash
,Javascript中的object literal
量等)的直接实现。
例如,你创建它们就像你会Python字典,通过传递键值对的构造方法(在Python的dict
没有list
):
x = list("ev1"=10, "ev2"=15, "rv"="Group 1")
你可以像访问Python字典那样访问R列表的项目,例如x['ev1']
。 同样,您可以通过以下方式检索“键”或“值”:
names(x) # fetch just the 'keys' of an R list
# [1] "ev1" "ev2" "rv"
unlist(x) # fetch just the 'values' of an R list
# ev1 ev2 rv
# "10" "15" "Group 1"
x = list("a"=6, "b"=9, "c"=3)
sum(unlist(x))
# [1] 18
但R list
也不像其他地图类型的ADT(从我学习的语言中)。 我的猜测是,这是S的初始规范的结果,即意图从头开始设计数据/统计数字DSL [领域特定语言]。
广泛使用的其他语言中的R list
和映射类型之间的三个显着差异(例如,Python,Perl,JavaScript):
首先,R中的list
s是一个有序集合,就像向量一样,即使值是键控的(即,键可以是任何可哈希值而不仅仅是顺序整数)。 几乎总是,其他语言的映射数据类型是无序的。
第二,即使您在调用函数时从未传入过list
,并且即使返回list
函数不包含(显式) list
构造函数,也可以从函数返回list
s(当然,您可以处理这在实践中是通过将返回的结果封装到未unlist
的调用中):
x = strsplit(LETTERS[1:10], "") # passing in an object of type 'character'
class(x) # returns 'list', not a vector of length 2
# [1] list
R的list
s的第三个特征:似乎它们不能成为另一个ADT的成员,并且如果尝试这样做,则主容器被强制为一个list
。 例如,
x = c(0.5, 0.8, 0.23, list(0.5, 0.2, 0.9), recursive=TRUE)
class(x)
# [1] list
我的意图不是批评这种语言,或者它是如何记录的; 同样,我并不是说list
数据结构有什么问题,或者它的行为如何。 我所追求的就是我对它们的工作方式的理解,以便我可以在我的代码中正确使用它们。
以下是我想更好理解的事情:
确定函数调用什么时候会返回一个list
(例如上面叙述的strsplit
表达式)的规则是什么?
如果我没有明确指定名称到list
(例如, list(10,20,30,40)
)是默认名称,只是以1开头的顺序整数? (我想,但我不能肯定的是,答案是肯定的很远,否则我们将无法对这类强制list
的向量w /调用unlist
。)
为什么这两个不同的运算符[]
和[[]]
返回相同的结果?
x = list(1, 2, 3, 4)
两个表达式都返回“1”:
x[1]
x[[1]]
为什么这两个表达式不会返回相同的结果?
x = list(1, 2, 3, 4)
x2 = list(1:4)
请不要将我指向R文档( ?list
, R-intro
) - 我已经仔细阅读了它,并且它无法帮助我回答刚才所述的问题类型。
(最后,我最近了解并开始使用R包(可在CRAN上获得)称为hash
,它通过S4类实现传统的地图类型行为;我当然可以推荐这个包。)
只是为了解决你的问题的最后部分,因为它真的指出了R中的list
和vector
之间的区别:
为什么这两个表达式不会返回相同的结果?
x = list(1,2,3,4); x2 =列表(1:4)
列表可以包含任何其他类作为每个元素。 所以你可以有一个列表,第一个元素是一个字符矢量,第二个是数据框等。在这种情况下,你创建了两个不同的列表。 x
有四个向量,每个长度为1. x2
有1个长度为4的向量:
> length(x[[1]])
[1] 1
> length(x2[[1]])
[1] 4
所以这些是完全不同的列表。
R列表非常像散列图数据结构,因为每个索引值都可以与任何对象关联。 下面是一个包含3个不同类(包括函数)的列表的简单示例:
> complicated.list <- list("a"=1:4, "b"=1:3, "c"=matrix(1:4, nrow=2), "d"=search)
> lapply(complicated.list, class)
$a
[1] "integer"
$b
[1] "integer"
$c
[1] "matrix"
$d
[1] "function"
鉴于最后一个元素是搜索功能,我可以这样调用它:
> complicated.list[["d"]]()
[1] ".GlobalEnv" ...
作为对此的最终评论:应该指出的是data.frame
是一个列表(来自data.frame
文档):
数据框是具有唯一行名的相同行数的变量列表,给定类'“data.frame''
这就是为什么data.frame
的列可以具有不同的数据类型,而矩阵中的列不能。 作为一个例子,在这里我尝试创建一个包含数字和字符的矩阵:
> a <- 1:4
> class(a)
[1] "integer"
> b <- c("a","b","c","d")
> d <- cbind(a, b)
> d
a b
[1,] "1" "a"
[2,] "2" "b"
[3,] "3" "c"
[4,] "4" "d"
> class(d[,1])
[1] "character"
请注意,我无法将第一列中的数据类型更改为数字,因为第二列中包含字符:
> d[,1] <- as.numeric(d[,1])
> class(d[,1])
[1] "character"
关于你的问题,让我按顺序解决它们并给出一些例子:
1 )如果返回语句添加一个,则返回一个列表。 考虑
R> retList <- function() return(list(1,2,3,4)); class(retList())
[1] "list"
R> notList <- function() return(c(1,2,3,4)); class(notList())
[1] "numeric"
R>
2 )名称根本没有设置:
R> retList <- function() return(list(1,2,3,4)); names(retList())
NULL
R>
3 )他们不会返回相同的东西。 你的例子给出了
R> x <- list(1,2,3,4)
R> x[1]
[[1]]
[1] 1
R> x[[1]]
[1] 1
其中x[1]
返回的第一个元素x
-这是一样的x
。 每个标量都是长度为1的矢量。 另一方面, x[[1]]
返回列表的第一个元素。
4 )最后,他们分别创建了一个包含四个标量的列表和一个带有单个元素的列表(它恰好是四个元素的向量)。
只是想了解一些问题:
这篇关于索引的文章解决了[]
和[[]]
之间差异的问题。
简而言之,[[]]从列表中选择单个项目, []
返回所选项目的列表。 在你的例子中, x = list(1, 2, 3, 4)'
item 1是一个整数,但x[[1]]
返回一个单独的1, x[1]
返回一个只有一个值的列表。
> x = list(1, 2, 3, 4)
> x[1]
[[1]]
[1] 1
> x[[1]]
[1] 1
链接地址: http://www.djcxy.com/p/53633.html