@evilking
2017-10-15T02:37:46.000000Z
字数 4998
阅读 1427
R基础篇
数据框同样是R中非常重要也是最常用的数据结构之一,一般可以用来操作数据表
从直观上看,数据框类似于矩阵,有行和列两个维度,与矩阵不同的是,数据框的每列可以具有不同的模式(mode),例如一列是数值型数据,另一列是字符型数据
从技术层面而言,数据框是每个组件长度都相等的列表,按列排列存储
> id <- c(1:5)> name <- c("Tom","Jack","Rose","Ketty","Hello")> salary <- seq(from=2000,to=6000,by=1000)> (x <- data.frame(id,name,salary,stringsAsFactors = FALSE))id name salary1 1 Tom 20002 2 Jack 30003 3 Rose 40004 4 Ketty 50005 5 Hello 6000> names(x)[1] "id" "name" "salary">
实例代码的前三句好理解,就是分别生成了三个长度为5的向量,最后一句就是利用data.frame()来生成数据框
该函数的前面三个参数表示三个向量,作为数据源来填充数据框,按列排列,每个向量在数据框中就成了一个字段,字段名即为向量对象的字符串名
最后一个stringsAsFactors=FALSE参数就表示不将字符串自动转换为“因子”(factor),保留字符串的属性,该参数默认去TRUE,表示会自动将字符串转换为“因子”
关于因子的概念我们在后面篇幅中专门讲解
一般使用read.table()等函数从文件中读取数据,读取的结果也是一个数据框,例如我们在R的工作空间中创建一个文件my_data_frame.txt,内容为:
"id" "name" "salary"1 "Tom" 20002 "Jack" 30003 "Rose" 40004 "Ketty" 50005 "Hello" 6000
则用R代码去读取这个文件:
> y <- read.table("my_data_frame.txt",header = TRUE)> yid name salary1 1 Tom 20002 2 Jack 30003 3 Rose 40004 4 Ketty 50005 5 Hello 6000> class(y) #查看读取数据后的结果对象的类型[1] "data.frame">
对象y的第一列显示的是行索引,第一行表示的是列的字段名,查看对象y的数据类型为"data.frame",可知读取文件数据的结果创建了一个数据框
这里使用的read.table()函数部分,在后面的基础篇之文件数据的存储于读取的文章中会详细讲解,现在可以暂时不用过多理会
访问数据框
> x #使用的数据框id name salary1 1 Tom 20002 2 Jack 30003 3 Rose 40004 4 Ketty 50005 5 Hello 6000> x[[1]] #按数字索引的方式访问数据框字段[1] 1 2 3 4 5> x[["name"]] #按字段名的方式访问数据框[1] "Tom" "Jack" "Rose" "Ketty" "Hello"> x$salary #用$符合访问字段[1] 2000 3000 4000 5000 6000> x[,1] #使用类似于访问矩阵的方式访问数据框[1] 1 2 3 4 5> class(x[,1])[1] "integer"> x[2:4,2] #用类似于矩阵的方式提取子数据框[1] "Jack" "Rose" "Ketty"> mode(x[2:4,2]) #自动降维成向量[1] "character"> x[2:4,2,drop = FALSE] #使用drop =FALSE参数保持数据框属性name2 Jack3 Rose4 Ketty> class(x[2:4,2,drop = FALSE])[1] "data.frame">> x[2:4,2:3] #子数据框自动变成了列表name salary2 Jack 30003 Rose 40004 Ketty 5000> mode(x[2:4,2:3])[1] "list"> x[1:2] #类似于列表,以单括号的方式访问数据框,结果为子数据框id name1 1 Tom2 2 Jack3 3 Rose4 4 Ketty5 5 Hello> class(x[["name"]]) #查看字段的类型[1] "character"> class(x[1]) #单括号索引访问结果为子数据框[1] "data.frame"> str(x) #使用str()函数查看对象的内部结构'data.frame': 5 obs. of 3 variables:$ id : int 1 2 3 4 5$ name : chr "Tom" "Jack" "Rose" "Ketty" ...$ salary: num 2000 3000 4000 5000 6000>
上述实例代码展示了四种访问数据框的方法,可以使用[[1]]数字索引访问第几列元素,使用[["name"]]字段名索引访问指定列元素,使用$salary$符合的方式访问指定列元素,以及使用类似于[2:4,2]矩阵取值操作的方式访问数据框元素,这也是提取子数据框的方法
其中x[1:2]的用法类似于列表,可以提取序列索引对应的列,结果的数据类型为数据框
str()函数很重要,它可以方便的查看R中所以对象的内部结构,包括多少行数据、多少个字段、字段名、每个字段的值是什么,都可以从中清楚的获知。当我们在用别人的库时,函数调用返回的对象不知道有哪些变量,就可以使用该函数查看
向数据框中添加列或行
> xid name salary1 1 Tom 20002 2 Jack 30003 3 Rose 40004 4 Ketty 50005 5 Hello 6000> (x <- rbind(x,list(6,"World",7000))) #行绑定,向数据框中添加新行id name salary1 1 Tom 20002 2 Jack 30003 3 Rose 40004 4 Ketty 50005 5 Hello 60006 6 World 7000> (x <- cbind(x,flag = TRUE,new = x$id)) #列绑定,向数据框中添加新列,这里还用到了循环补齐id name salary flag new1 1 Tom 2000 TRUE 12 2 Jack 3000 TRUE 23 3 Rose 4000 TRUE 34 4 Ketty 5000 TRUE 45 5 Hello 6000 TRUE 56 6 World 7000 TRUE 6> x[4:5] <- NULL #删除序列索引指定的列> xid name salary1 1 Tom 20002 2 Jack 30003 3 Rose 40004 4 Ketty 50005 5 Hello 60006 6 World 7000>
类似于矩阵的添加行或列,数据框也是使用的rbind()函数添加新行,使用cbind()函数添加新列;当要删除列时,可将对应的列设为NULL即可
————————————————————————————————————
修改列名
> xid name salary1 1 Tom 20002 2 Jack 30003 3 Rose 40004 4 Ketty 50005 5 Hello 60006 6 World 7000> names(x) <- c(names(x)[1:2],"old_salary") #修改第三列字段的字段名> xid name old_salary1 1 Tom 20002 2 Jack 30003 3 Rose 40004 4 Ketty 50005 5 Hello 60006 6 World 7000> names(x) <- NULL #删除字段名> x1 1 Tom 20002 2 Jack 30003 3 Rose 40004 4 Ketty 50005 5 Hello 60006 6 World 7000>
数据框也可以用names()函数来查看和修改字段名,若要删除字段名,只需要将names(x)设为NULL即可
> x1 1 Tom 20002 2 Jack 30003 3 Rose 40004 4 Ketty 50005 5 Hello 60006 6 World 7000> apply(x,2,max) #对每一列使用max()函数[1] "6" "World" "7000"> (y <- lapply(x,sort)) #对每列使用sort()函数[[1]][1] 1 2 3 4 5 6[[2]][1] "Hello" "Jack" "Ketty" "Rose" "Tom" "World"[[3]][1] 2000 3000 4000 5000 6000 7000> (z <- sapply(x,sort))[,1] [,2] [,3][1,] "1" "Hello" "2000"[2,] "2" "Jack" "3000"[3,] "3" "Ketty" "4000"[4,] "4" "Rose" "5000"[5,] "5" "Tom" "6000"[6,] "6" "World" "7000">
数据框是列表的特例,数据框的列构成了列表的组件,所以也可以在数据框的每列上应用apply()函数和lapply()函数,包括sapply()函数
> xid name salary1 1 Tom 20002 2 Jack 30003 3 Rose 40004 4 Ketty 50005 5 Hello 60006 6 World 7000> yid1 32 43 54 65 76 8> merge(x,y) #按照x和y中共有的字段的值相等来做合并id name salary1 3 Rose 40002 4 Ketty 50003 5 Hello 60004 6 World 7000
在关系型数据库中经常会需要合并,即将两张表根据某个共同变量的值相等来组合到一起,join操作;在R中可以用 merge()来实现。比如上例,将x和y按照id字段的相等值合并
> names(y) <- "old_id"> yold_id1 32 43 54 65 76 8> merge(x,y)id name salary old_id1 1 Tom 2000 32 2 Jack 3000 33 3 Rose 4000 34 4 Ketty 5000 35 5 Hello 6000 36 6 World 7000 37 1 Tom 2000 48 2 Jack 3000 49 3 Rose 4000 410 4 Ketty 5000 411 5 Hello 6000 412 6 World 7000 413 1 Tom 2000 514 2 Jack 3000 515 3 Rose 4000 516 4 Ketty 5000 517 5 Hello 6000 518 6 World 7000 519 1 Tom 2000 620 2 Jack 3000 621 3 Rose 4000 622 4 Ketty 5000 623 5 Hello 6000 624 6 World 7000 625 1 Tom 2000 726 2 Jack 3000 727 3 Rose 4000 728 4 Ketty 5000 729 5 Hello 6000 730 6 World 7000 731 1 Tom 2000 832 2 Jack 3000 833 3 Rose 4000 834 4 Ketty 5000 835 5 Hello 6000 836 6 World 7000 8> merge(x,y, by.x = "id", by.y = "old_id")id name salary1 3 Rose 40002 4 Ketty 50003 5 Hello 60004 6 World 7000>
当merge()函数中没有共同的字段时,结果就是全连接操作,也就是两个表做笛卡尔积;如果想按指定的列的值相等做合并操作,可以设置by.x和by.y参数
> xid name salary1 1 Tom 20002 2 Jack 30003 3 Rose 40004 4 Ketty 50005 5 Hello 60006 6 World 7000> x[3:4,3] <- NA> x #假设数据框中有缺失值存在id name salary1 1 Tom 20002 2 Jack 30003 3 Rose NA4 4 Ketty NA5 5 Hello 60006 6 World 7000> complete.cases(x) #可以用该函数查看某行是否不存在缺失值[1] TRUE TRUE FALSE FALSE TRUE TRUE> (w <- x[complete.cases(x),]) #提取没有缺失值的行id name salary1 1 Tom 20002 2 Jack 30005 5 Hello 60006 6 World 7000>
若假设数据框中存在缺失值,则可以用complete.cases()函数检查某行是否不存在缺失值,结果是一个boolean型向量,每个元素指示对应的行是否不存在缺失值;若存在,则对应行的值为FALSE,不存在则为TRUE;得到这个指示的索引向量后,便可以提取数据框中不存在缺失值的行