R数据结构课程。要进行任何有意义的数据分析,我们需要收集数据到R数据结构。这节课我们会探讨最常用的数据类型和数据结构。 R能被用来分析许多不同形式的数据。我们会探讨R的内置数据类型。 数据分析通常需要大量相似的数据集。这节课我们会探讨能用来保存和计算数据集的不同数据结构。 R可以处理许多不同的数据类型。
- Data types
- Data structures
- Vector
- List
- Multi-Dimensional
- Matrix
- Array
这里我们检查最常用的:数值型, 逻辑型,和字符类型。 数值型数据通常分为整型或者实型。 缺省地,R会把数值型存储为实型,在其它地方也叫双精度浮点数值。如果我们想把数据存成整型数值,我们使用as.integer()函数。 逻辑型或者布尔型表达是或非情况。是或非数值可以在一个数据集中存在,或者在这个例子里,我们使用一个返回逻辑型数值的函数。
Data Types:
1、real
>c<-75.3
>ctypeof(c)
[1]"double"
2、integer
>b<-as.integer(8)
>typeof(b)
[1]"integer"
3、logical
>is.integer(b)
TRUE
4、character
>typeof(grade<-"B")
[1]"character"
>str(1Grade<-as.factor("A+"))
Factor w/ 1 level "A+": 1
字符或者字符串是数据集中常见的数据。字符数据以常量形式提供附上单引号或者双引号。如果字符数据表达一个类别,那么你可能想要R把它当成一个因子,而不是字符串。 我们会在以后的课程中考察因子的使用。这里我们决定一个字母应该被当作因子而不是字符串。 一个向量用来维护相同类型数值的一个有序集。 任何R数据类型都可以用在向量里。 向量里的元素可以用索引来获取。 索引从1开始。 这里我们有一个三个名字组成的字符型向量。 向量在需要的时候,也可以扩展到更多的元素。 向量里的元素也可以修改。
最常用的创建向量的技术是使用c()或者组合函数。 这个函数会组合它的参数来生成一个新的向量。 有许多获取向量内部元素的方法。
Creation
>ages<-c(10,23,42)
Numberic indexing
>ages[1]
[1]10
>ages[-1] #All items except item 1
[1]23 42
>ages[1:2]
[1]10 23
>ages[length(ages)]
[1]42
在第一个例子我们使用一个整数作为索引方法来得到年龄向量的第一个元素。方括号用来从数据结构中获取元素。 负数能用来去除元素。 一个数值范围,或者另一个索引向量。 可以加上方括号,来从数据结构中选取特定素。 另一个非常有用的函数可以用在不同数据结构上的是length()函数。 如果你传递一个向量给length()函数 它会返回向量中元素的个数。
Logical indexing
>ages<-c(10,23,42)
>s.ages<-c(TRUE,FALSE,TRUE)
>typeof(s.ages)
[1]"logical"
>m<-ages[s.ages]
[1]10 42
向量可以用任何R支持的数据类型创建。 这里我们决定生成一个名为年龄的向量。 我们不用数值型而是用逻辑型向量来获取向量元素。 我们创建一个有相同个数元素的逻辑型向量,取名为s.ages。 当我们使用一个逻辑向量,获取年龄向量中的元素,只有年龄向量中对应True的元素返回了。 我们的结果向量m只包含10到42的数值。 我们会很快发现为什么用作数据结果分析的条件获取函数是R的一个非常强大的特征。
Conditional access to vector elements
>nums<-c(2,3,4,5,6,8)
>evens<-nums[(nums%%2)==0]
>print(evens)
[1]2 4 6 8
让我们看我们能怎样基于条件动态获取一个向量的元素。 我们有一个简单的数值向量叫做num。我们要从向量中提取偶数,并且存到新向量中。 R可以用条件获取处理这个任务。 我们使用这个模块以及相等运算符来帮助我们判断元素是偶还是奇。 R会应用条件表达式到向量的每个元素,因为向量被方括号里的数索引了。如果表达式被认为是真的, 元素的一个复制被添加到新的向量偶数里。 最后,我们检查新向量的内容来验证正确的数值被复制了。
Generating a sequence of values - vector
>evens<-seq(from=2,to=12,by=2)
>str(evens) #structure str()
num [1:6] 2 4 6 8 10 12
>evens<-as.integer(evens) #type conversion as.*()
int [1:6] 2 4 6 8 10 12
>digits<-0:9
digits
[1]0 1 2 3 4 5 6 7 8 9
R提供一个新的不同技术来生成一系列值。 这里使用或者seq()序列函数。 函数str()被用来显示一个对象的结构。在这里我们注意到初始结构是一个数字向量。 我们使用这个类型转换函数叫做as.integer()来把缺省的双精度类型数值 转为整型。
R will vectorize most operations
>salaries<-c(14.25,23,25)
>salaries *1.10
[1]15.675 25.300 27.500
>salaries
[1]14.25 23.00 25.00
>salaries <- salaries * 1.10
[1]15.675 25.300 27.500
R有不同的类型转换函数。另一个创建简单序列的方法是使用冒号运算符:。这里我们创建一个从0到9的整数生成的向量。R是一个函数型语言带有向量运算符的内置支持。每当可能的时候,最好是使用向量运算符而不是迭代或循环。R会为许多向量操作使用非常有效的自带库,因此你的R脚本会比每个运算都用循环运行得更快。例如,让我们使用一个小时薪水的向量。我们愿意把所有的小时薪水提高10%。为了完成这个任务,我们把现有薪水乘以1.10来得到新的薪水。使用了乘法运算符或者星号。在R里,常数1.10和每个向量元素相乘。这是一个R的向量再利用规则的例子。注意,由于我们没有存储新的薪水,原始数值保持不变。为了替换已有数值,我们必须使用赋值运算符。
RULE:Smaller vector is recycled to match length
>temps<-c(10,11,12,13)
>n.tempsn.temps
[1]13 15 15 17
如我们在先前的例子中到的,当R向量运算被 使用不同大小的向量执行,当运算结束后更小的向量被回收或者再使用。 在这个例子里,我们进行向量加,但是temps有4个元素,它和一个 两个元素的向量n.temps相加。 下面这个运算我们注意到为了temps向量的最后两个元素,元素3和4第二次用到了 这个可能是你想要的结果,也可能不是你想要的结果。 所以对向量使用内置函数的时候要小心。
Large datasets often have missing data
Most R functions can handle
>ages<-c(23,45,NA)
>mean(ages)
[1]NA
>mean(ages,na.rm=TRUE)
[1]34
当你用大数据集的时候有缺失数值是很正常的。 R有一个特殊数值来代表缺失值。 缺失数据可以用NA表示 NA表示"Not Available"。 缺省地,R会识别NA数值,在这个例子中当有确实数值时, mean()不会被计算。 如果你愿意忽略缺失值,你可以传递可选参数na.rm=TRUE。 R中有一些特殊数值,但是我们这节课不会讨论。
Matrix - Two (2) dimensional vector
>scores<-matrix(data=c(1,2,80,85,67,56),nrow=2,ncol=3)
>scores
| [,1] | [,2] | [,3] |
[1,] | 1 | 80 | 67 |
[2,] | 2 | 85 | 56 |
>mean(scores[,2])
[1]82.5
一个矩阵是一个二维向量。我们仍然这个限制,所有 的元素必须是相同数据类型。 在这个例子里我们用matrix()函数创建了一个矩阵来代表两个不同 学生的分数。当创建矩阵的时候必须提供维度。 这里我们会创建2-3个矩阵,因为我们有2个学生以及3个不同的属性。 第一列被用作唯一的学生标识符,另外2个元素代表两个 不同考试的结果。当我们使用matrix()函数时,数据以 一维向量的方式提供,但是我们也描述R用来表示数据的行数 和列数。 缺省地,向量中的数据以列的方式填充数据结构。 在我们的例子里,这里我们有学生1的考试分数80和67, 学生2的分数85和56。 矩阵中的数据可以用逗号操作符作为单一元素或者一个范围的元素被分析。 这里我们计算学生第一次考试的分数均值。 记住第一个索引值代表 矩阵行,第二个索引值代表列索引。
Matrix access using names
>sores
[,1] | [,2] | [,3] |
1 | 80 | 67 |
2 | 85 | 56 |
>colnames(scores)<-c("id","test1","test2")
>scores
id | test1 | test2 |
1 | 80 | 67 |
2 | 85 | 56 |
>mean(scores[,"test1"])
[1]82.5
我们先前提到R矩阵中的数据必须有相同的数据类型。 但是行和列可以被命名,而不是简单地使用数值索引值。 在这个例子里,我们要说明列确是代表学生id,考试1,考试1元素。 我们用colnames()函数。这个函数接收一个和矩阵中每一列都关联的向量。 现在,我们用列名标示test1的对分数矩阵进行相同的计算。 当索引值随时间发生变化时,使用列名提供灵活性使得你不再担心这种变化。 A列表示一个对象的有序集。不象向量,这个对象可以是混合的数据类型,他们可以有不同的长度。 在这个例子里,我们从两个独立的向量开始。 一个学生名字字符向量和一个年龄数值向量。 使用一个list()函数创建一个列表结构叫做教室。
Lists
Collection of vectors
- mixed data types
- varying length objects are allowed
>students<-c("Mary","Bob","John")
>ages<-c(14,15,18)
>classroom<-list(students,ages)
>classroom[1] # [] copy of students [[1]]
[1]"Mary","Bob","John"
>classroom[[1]] # [[]] access list member
[1]"Mary","Bob","John"
>classroom[[1]][1]<-"Eva" #modify 1st item
>classroom[[1]]
[1]"Eva" "Bob" "John"
>students
[1]"Mary" "Bob" "John" #original unchanged
这个列表包含学生和年龄向量的复本。 用一个方括号集来获得列表中数据的一个复本。 数据通常以一个数据结构列表的方式返回。 学生名字用一个或单独或者双方括号集可以获得。 如果我们想修改教室列表中的数值,我们可以使用双方括号索引方法 这里我们在教室列表结构中替换第一个学生,"Mary" 为新学生"Eva"。 用来创建初始教室数据结构的名字叫做学生的初始向量没有改变。
Lists - Naming Members
>s<-c("Mary","Bob","John")
>a<-c(14,15,18)
>classroom<-list(students=s,ages=a)
>classroom$students # slice reference
[1]"Mary","Bob","John"
>classroom["students"] #slice reference
$students
[1]"Mary","Bob","John"
就像我们可以对矩阵数据结构的每一列命名一样,我们可以命名我们列表的每个组件。这里我们要用词"students" 和 "ages" 来命名我们的教室的列表组件。 现在我们可以用美元符号来索引列表元素或者使用列表组件的名字。由于列表允许我们将在数据分析任务重常用的不同数据类型组合在一起。
Data Frame
- mixed data frame
- defined size (#row,#columns)
>df1<-data.frame(students=c("Mary","Jane","Eva"),test1=c(80,90,70))
>df1
| students | test1 |
1 | Mary | 80 |
2 | Jane | 90 |
3 | Eva | 70 |
数据帧是表示列表数据的有用的数据集。 类似列表,一个数据帧可以包含不同数据类型。 不同于列表,数据帧有一个定义好的大小 -- 或者一个行和列的数目。 这里我们用data.frame()函数创建一个名叫df1的数据帧。 数据帧表示我们的三个学生以及他们在一次考试中的分数。
Adding columns of data
>df1<-cbind(df1,ages=c(15,16,18))
| students | test1 | ages |
1 | Mary | 80 | 15 |
2 | Jane | 90 | 16 |
3 | Eva | 70 | 18 |
cbind()或者列表绑定函数可以用来一个向量添加到我们数据帧的新的一列。
Adding rows of data>
>df2<-data.frame(students="Bob",marks=78,ages=16)
>df1<-rbind(df1,df2)
>df1
| students | marks | ages |
1 | Mary | 80 | 15 |
2 | Jane | 90 | 16 |
3 | Eva | 70 | 18 |
4 | Bob | 78 | 16 |
在这个案例中新向量表示3个学生的一个年龄集。 可以用rbind()或者行绑定函数来把新的一行添加到数据帧, 在这个例子里我们添加一个新的学生到我们的数据框架里。 谢谢你完成这节课。现在练习使用R数据结构。
花朵开放的时候花蕾消逝,人们会说花蕾是花朵否定了的;同样地,当结果的时刻花朵又被解释为植物的一种虚假的存在形式,而果实是作为植物的真实形式而取代花朵的。这些形式不但彼此不同,而且互相排斥,互不相容。但是,他们的流动性却使他们成为有机统一体的环节,他们在有机统一体中不但互相抵触,而且彼此都同样是必要的;而正是这种同样的必要性才构成整体的生命。