如何在R中正确使用列表?

简要背景:广泛使用的许多(大多数?)当代编程语言至少有几个ADT[抽象数据类型]是共同的,特别是

  • 字符串(由字符组成的序列)

  • 列表(值的有序集合),以及

  • 基于映射的类型(将键映射到值的无序数组)

在R编程语言中,前两个分别实现为字符向量

当我开始学习R时,有两件事几乎从一开始就显而易见:list是R中最重要的数据类型(因为它是Rdata.frame的父类),其次,我只是不理解它们是如何工作的,至少不足以在代码中正确使用它们

首先,在我看来,R的list数据类型是map ADT的一个简单实现(Python中的dictionary,Objective C中的NSMutableDictionary,Perl和Ruby中的hash,Javascript中的object literal,等等)

例如,通过将键值对传递给构造函数(在Python中是dict而不是list),可以像创建Python字典一样创建它们:

x=list(“ev1”=10,“ev2”=15,“rv”=1组”)

您可以像访问Python字典一样访问R列表中的项目,例如,x['ev1']。同样,您可以通过以下方式仅检索的“键”的“值”

names(x)#只获取R列表中的“键”
#[1]“ev1”“ev2”“rv”
unlist(x)#只获取R列表的“值”
#ev1 ev2 rv
#10“15”组1
x=列表(“a”=6,“b”=9,“c”=3)
金额(未列出(x))
# [1] 18

但是Rlists也不同于其他地图类型的ADT(从我学过的语言中)。我的猜测是,这是S的初始规范的结果,即打算从头开始设计数据/统计DSL[领域特定语言]

Rlists与广泛使用的其他语言(例如,.Python、Perl、JavaScript)中的映射类型之间有三个显著差异:

首先列表在R中是一个有序的集合,就像向量一样,即使值是键控的(即键可以是任何可散列值,而不仅仅是顺序整数)。其他语言中的映射数据类型几乎总是无序的

列表可以从函数返回,即使调用函数时从未传入列表,并且即使返回列表的函数不包含(显式的)列表构造函数(当然,在实践中,您可以通过将返回的结果包装到调用unlist)来处理这个问题:

x=strsplit(字母[1:10],“”)#传入“character”类型的对象
类(x)#返回'list',而不是长度为2的向量
#[1]列表

R的列表的第三个特殊功能:它们似乎不可能是另一个ADT的成员,如果您尝试这样做,则主容器将被强制为列表。例如

x=c(0.5,0.8,0.23,列表(0.5,0.2,0.9),递归=TRUE)
类别(x)
#[1]列表

我在这里的目的不是批评语言或它的文档化方式;同样,我也不是说列表数据结构或它的行为有任何问题。我所要做的只是纠正我对它们如何工作的理解,以便我能在代码中正确使用它们

以下是我想更好地理解的事情:

  • 确定函数调用何时返回列表(例如上文所述的strsplit表达式)的规则有哪些

  • 如果我没有显式地为列表(例如,列表(10,20,30,40))指定名称,那么默认名称是以1开头的连续整数吗?(我假设,但我远不能确定答案是肯定的,否则我们将无法强制这种类型的列表为向量w/调用未列出

  • 为什么这两个不同的运算符,[][[]]返回相同的结果

    x=list(1,2,3,4)

    两个表达式都返回“1”:

    x[1]

    x[[1]]

  • 为什么这两个表达式不返回相同的结果

    x=list(1,2,3,4)

    x2=列表(1:4)

请不要指向R文档(?listR-intro)——我已经仔细阅读了它,它不能帮助我回答我刚才背诵的问题类型

(最后,我最近了解并开始使用一个名为hash的R包(可在CRAN上获得),它通过S4类实现常规的映射类型行为;我当然可以推荐这个包。)

请回答问题的最后一部分,因为这确实指出了R中列表向量之间的区别:

为什么这两个表达式不返回相同的结果

x=列表(1,2,3,4);x2=列表(1:4)

列表可以包含任何其他类作为每个元素。因此,您可以有一个列表,其中第一个元素是字符向量,第二个是数据帧等。在这种情况下,您创建了两个不同的列表。x有四个向量,每个向量的长度为1。x2有一个长度为4的向量:

>长度(x[[1]]
[1] 1
>长度(x2[[1]])
[1] 4

所以这些是完全不同的列表

R列表非常类似于哈希映射数据结构,因为每个索引值都可以与任何对象关联。下面是一个包含3个不同类(包括一个函数)的列表的简单示例:

>complex.list<-list("a"=1:4,"b"=1:3,"c"=矩阵(1:4,nrow=2),"d"=搜索)
>lappy(复杂列表,类)
一美元
[1] “整数”;
b美元
[1] “整数”;
$c
[1] “矩阵”;
美元
[1] “功能”;

鉴于最后一个元素是搜索函数,我可以这样调用它:

>复杂的列表[["d"]]()
[1] “GlobalEnv”。。。

最后一点:应该注意,data.frame实际上是一个列表(来自data.frame文档):

数据框是给定类“data.frame”的具有唯一行名称的相同行数的变量列表

这就是为什么data.frame中的列可以有不同的数据类型,而矩阵中的列不能有不同的数据类型。例如,我尝试创建一个包含数字和字符的矩阵:

>a<-1:4
>a类
[1] “整数”;
>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”;
>类别(d[,1])
[1] “字符”;

请注意,我无法将第一列中的数据类型更改为数字,因为第二列包含字符:

>d[,1]<-作为数字(d[,1])
>类别(d[,1])
[1] “字符”;

发表评论