R语言实战---第2章

2.2 数据结构

R拥有许多用于存储数据的对象类型,包括标量、向量、矩阵、数组、数据框和列表。


图片.png

2.2.1 向量

向量是存储数值型、字符型、逻辑型数据的一维数组。执行组合功能的函数c()可以创建向量。

> a <- c(1, 2, 5, 3, 6, -2, 4)
> b <- c("one", "two", "three")
> c <- c(TRUE, TRUE, TRUE, FALSE, TRUE, FALSE)

单个向量中的数据必须具有相同的数据类型和模式。
标量是只含一个元素的向量。如:

> f <- 3
> g <- "US"
> h <- TRUE

访问向量中的元素

> a <- c(1, 2, 5, 3, 6, -2, 4)
> a[3]
[1] 5
> a[c(1,3,5)]
[1] 1 5 6
> a[2:6]
[1]  2  5  3  6 -2

2.2.2 矩阵

矩阵是一个二维数组,每个元素都具有相同的数据类型和模式。可通过函数matrix()创建矩阵。

matrix(data = NA, nrow = 1, ncol = 1, byrow = FALSE,
       dimnames = NULL)

创建矩阵

> y <- matrix(1:20, nrow=5, ncol=4)
> y
     [,1] [,2] [,3] [,4]
[1,]    1    6   11   16
[2,]    2    7   12   17
[3,]    3    8   13   18
[4,]    4    9   14   19
[5,]    5   10   15   20
> cells <- c(1, 26, 24, 68)
> rnames <- c("R1", "R2")
> cnames <- c("C1", "C2")
> mymatrix <- matrix(cells, nrow = 2, ncol = 2, byrow = TRUE, dimnames = list(rnames, cnames))
> mymatrix
   C1 C2
R1  1 26
R2 24 68

矩阵下标的使用

> x <- matrix(1:10, nrow=2)
> x
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    3    5    7    9
[2,]    2    4    6    8   10
> x[2,]
[1]  2  4  6  8 10
> x[,2]
[1] 3 4
> x[1, 4]
[1] 7
> x[1, c(4, 5)]
[1] 7 9

2.2.3 数组

数组与矩阵类似,但是维度可以大于2。数组可以通过array函数创建,形式如下:
array(data = NA, dim = length(data), dimnames = NULL)
创建一个2×3×4的数组

> dim1 <- c("A1", "A2")
> dim2 <- c("B1", "B2", "B3")
> dim3 <- c("C1", "C2", "C3", "C4")
> Z <- array(1:24, c(2, 3, 4), dimnames = list(dim1, dim2, dim3))
> Z
, , C1

   B1 B2 B3
A1  1  3  5
A2  2  4  6

, , C2

   B1 B2 B3
A1  7  9 11
A2  8 10 12

, , C3

   B1 B2 B3
A1 13 15 17
A2 14 16 18

, , C4

   B1 B2 B3
A1 19 21 23
A2 20 22 24

2.2.4 数据框

数据框不同的列可以包含不同模式(数值型,字符型)的数据,较矩阵来说更为一般。
数据框可以通过函数data.frame()创建
mydata <- data.frame(col1, col2, col3, ...)
其中列向量可以为任意类型,每一列的名称可由函数names指定。
创建一个数据框

> patientID <- c(1, 2, 3, 4)
> age <- c(25, 34, 28, 52)
> diabetes <- c("Type1", "Type2", "Type1", "Type1")
> status <- c("Poor", "Improved", "Excellent", "Poor")
> patientdata <- data.frame(patientID, age, diabetes, status)
> patientdata
  patientID age diabetes    status
1         1  25    Type1      Poor
2         2  34    Type2  Improved
3         3  28    Type1 Excellent
4         4  52    Type1      Poor

选取数据框中的元素

> patientdata[1:2]
  patientID age
1         1  25
2         2  34
3         3  28
4         4  52
> patientdata[c("diabetes", "status")]
  diabetes    status
1    Type1      Poor
2    Type2  Improved
3    Type1 Excellent
4    Type1      Poor
> patientdata$age
[1] 25 34 28 52

第三个例子中的$用来选取给定数据框中的某个特定变量。
在每个变量名前都键入一次patientdata$可能会让人生厌,可使用函数attach()和detach()或单独使用函数with()来简化代码。

1.attach()、 detach()和with()

函数attach()将数据框添加到R的搜索路径中。R在遇到一个变量名后,将检查搜索路径中的数据框,以定位到这个变量。
以mtcars数据为例

> summary(mtcars$mpg)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  10.40   15.43   19.20   20.09   22.80   33.90 
> plot(mtcars$mpg, mtcars$disp)
> plot(mtcars$mpg, mtcars$wt)

上面的代码也可以写成

> attach(mtcars)
> summary(mpg)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  10.40   15.43   19.20   20.09   22.80   33.90 
> plot(mpg,disp)
> plot(mpg,wt)
> detach(mtcars)

detach()将数据框从搜索路径中移除。
当存在多个具有相同名称的对象时,这种方法的局限性就比较明显了。

除此之外,另一种方式是使用函数with()。

 > with(mtcars, {
    summary(mpg, disp, wt)
    plot(mpg, wt)
    plot(mpg, disp)})

在这种情况下,大括号{}之间的语句都针对数据框mtcars执行,这样就无须担心名称冲突了。如果仅有一条语句(例如summary(mpg)),那么大括号{}可以省略。
函数with()的局限性在于,赋值仅在此函数的括号内生效。考虑以下代码:

> with(mtcars, {
+     stats <- summary(mpg)
+     stats})
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  10.40   15.43   19.20   20.09   22.80   33.90 
> stats
Error: object 'stats' not found

如果你需要创建在with()结构以外存在的对象,使用特殊赋值符<<-替代标准赋值符(<-)即可,它可将对象保存到with()之外的全局环境中。这一点可通过以下代码阐明:

> with(mtcars, {
+     nokeepstats <- summary(mpg)
+     keepstats <<- summary(mpg)
+ })
> nokeepstats
Error: object 'nokeepstats' not found
> keepstats
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  10.40   15.43   19.20   20.09   22.80   33.90 

2.实例标识符

在病例数据中,病人编号(patientID)用于区分数据集中不同的个体。在R中,实例标识符(case identifier)可通过数据框操作函数中的rowname选项指定。例如,语句:

> patientdata <- data.frame(patientID, age, diabetes, status, row.names = patientID)

将patientID指定为R中标记各类打印输出和图形中实例名称所用的变量。

2.2.5 因子(factor)

如你所见,变量可归结为名义型、有序型或连续型变量。名义型变量是没有顺序之分的类别变量。糖尿病类型Diabetes(Type1、Type2)是名义型变量的一例。即使在数据中Type1编码为1而Type2编码为2,这也并不意味着二者是有序的。有序型变量表示一种顺序关系,而非数量关系。病情Status(poor, improved, excellent)是顺序型变量的一个上佳示例。我们明白,病情为poor(较差)病人的状态不如improved(病情好转)的病人,但并不知道相差多少。连续型变量可以呈现为某个范围内的任意值,并同时表示了顺序和数量。年龄Age就是一个连续型变量,它能够表示像14.5或22.8这样的值以及其间的其他任意值。很清楚,15岁的人比14岁的人年长一岁。
类别(名义型)变量和有序类别(有序型)变量在R中称为因子(factor)。因子在R中非常重要,因为它决定了数据的分析方式以及如何进行视觉呈现。你将在本书中通篇看到这样的例子。
函数factor()以一个整数向量的形式存储类别值,整数的取值范围是[1... k ](其中k 是名义型变量中唯一值的个数),同时一个由字符串(原始值)组成的内部向量将映射到这些整数上。

> diabetes <- factor(diabetes)
> status <- factor(status, ordered = TRUE)
> patientdata <- data.frame(patientID, age, diabetes, status)
> str(patientdata)
'data.frame':   4 obs. of  4 variables:
 $ patientID: num  1 2 3 4
 $ age      : num  25 34 28 52
 $ diabetes : Factor w/ 2 levels "Type1","Type2": 1 2 1 1
 $ status   : Ord.factor w/ 3 levels "Excellent"<"Improved"<..: 3 2 1 3
> summary(patientdata)
   patientID         age         diabetes       status 
 Min.   :1.00   Min.   :25.00   Type1:3   Excellent:1  
 1st Qu.:1.75   1st Qu.:27.25   Type2:1   Improved :1  
 Median :2.50   Median :31.00             Poor     :2  
 Mean   :2.50   Mean   :34.75                          
 3rd Qu.:3.25   3rd Qu.:38.50                          
 Max.   :4.00   Max.   :52.00   

对于字符型向量,因子的水平默认依字母顺序创建。这对于因子status是有意义的,因为“Excellent”、“Improved”、“Poor”的排序方式恰好与逻辑顺序相一致。如果“Poor”被编码为“Ailing”,会有问题,因为顺序将为“Ailing”、“Excellent”、“Improved”。如果理想中的顺序是“Poor”、“Improved”、“Excellent”,则会出现类似的问题。按默认的字母顺序排序的因子很少能够让人满意。你可以通过指定levels选项来覆盖默认排序。

> status <- factor(status, order=TRUE, levels = c("Poor", "Improved", "Excellent"))

2.2.6 列表

列表(list)是R的数据类型中最为复杂的一种。一般来说,列表就是一些对象(或成分,component)的有序集合。列表允许你整合若干(可能无关的)对象到单个对象名下。例如,某个列表中可能是若干向量、矩阵、数据框,甚至其他列表的组合。可以使用函数list()创建列表。
创建一个列表

> g <- "My First List"
> h <- c(25, 26, 18, 39)
> j <- matrix(1:10, nrow=5)
> k <- c("one", "two", "three")
> mylist <- list(title=g, ages=h, j , k)
> mylist
$`title`
[1] "My First List"

$ages
[1] 25 26 18 39

[[3]]
     [,1] [,2]
[1,]    1    6
[2,]    2    7
[3,]    3    8
[4,]    4    9
[5,]    5   10

[[4]]
[1] "one"   "two"   "three"

> mylist[[2]]
[1] 25 26 18 39
> mylist[["ages"]]
[1] 25 26 18 39

可以通过在双重方括号中指明代表某个成分的数字或名称来访问列表中的元素。此例中,mylist[[2]]和mylist[["ages"]]均指那个含有四个元素的向量.

2.3 数据的输入

2.3.1 使用键盘输入数据

R中的函数edit()会自动调用一个允许手动输入数据的文本编辑器。
具体步骤如下:
(1) 创建一个空数据框(或矩阵),其中变量名和变量的模式需与理想中的最终数据集一致;
(2) 针对这个数据对象调用文本编辑器,输入你的数据,并将结果保存回此数据对象中。

> mydata <- data.frame(age=numeric(0), gender=character(0), weight=numeric(0))
> mydata <- edit(mydata)

类似于age=numeric(0)的赋值语句将创建一个指定模式但不含实际数据的变量。注意,编辑的结果需要赋值回对象本身。函数edit()事实上是在对象的一个副本上进行操作的。如果你不将其赋值到一个目标,你的所有修改将会全部丢失!

2.3.2 从带分隔符的文本文件导入数据

使用read.table()从带分隔符的文本文件中导入数据。

read.table(file, header = FALSE, sep = "", quote = "\"'",
           dec = ".", numerals = c("allow.loss", "warn.loss", "no.loss"),
           row.names, col.names, as.is = !stringsAsFactors,
           na.strings = "NA", colClasses = NA, nrows = -1,
           skip = 0, check.names = TRUE, fill = !blank.lines.skip,
           strip.white = FALSE, blank.lines.skip = TRUE,
           comment.char = "#",
           allowEscapes = FALSE, flush = FALSE,
           stringsAsFactors = default.stringsAsFactors(),
           fileEncoding = "", encoding = "unknown", text, skipNul = FALSE)

其中,file是一个带分隔符的ASCII文本文件,header是一个表明首行是否包含了变量名的逻辑值(TRUE或FALSE),sep用来指定分隔数据的分隔符,row.names是一个可选参数,用以指定一个或多个表示行标识符的变量。

2.3.3 导入EXCEL数据

读取一个Excel文件的最好方式,就是在Excel中将其导出为一个逗号分隔文件(csv),并使用前文描述的方式将其导入R中。在Windows系统中,你也可以使用RODBC包来访问Excel文件。
电子表格的第一行应当包含变量/列的名称。

> intall.packages("RODBC")
> library(RODBC)
> channel <- odbcConnectExcel("myfile.xls")
> mydataframe <- sqlFetch(channel, "mysheet")
> odbcClose(channel)

这里的myfile.xls是一个Excel文件,mysheet是要从这个工作簿中读取工作表的名称,channel是一个由odbcConnectExcel()返回的RODBC连接对象,mydataframe是返回的数据框。RODBC也可用于从Microsoft Access导入数据.

2.3.11 访问数据库管理接口

R中有多种面向关系型数据库管理系统(DBMS)的接口,包括Microsoft SQL Server、MicrosoftAccess、MySQL、Oracle、PostgreSQL、DB2、Sybase、Teradata以及SQLite。其中一些包通过原生的数据库驱动来提供访问功能,另一些则是通过ODBC或JDBC来实现访问的。使用R来访问存
储在外部数据库中的数据是一种分析大数据集的有效手段,并且能够发挥SQL和R各自的优势。

  1. ODBC接口
    在R中通过RODBC包访问一个数据库也许是最流行的方式,这种方式允许R连接到任意一种拥有ODBC驱动的数据库,其实几乎就是市面上的所有数据库。
    第一步是针对你的系统和数据库类型安装和配置合适的ODBC驱动——它们并不是R的一部分。如果你的机器尚未安装必要的驱动,上网搜索一下应该就可以找到。
    针对选择的数据库安装并配置好驱动后, 请安装RODBC 包。你可以使用命令install.packages("RODBC")来安装它。
    RODBC包中的主要函数列于表2-2中。


    图片.png

2.5 处理数据对象的实用函数

图片.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容

  • 2017年夏天开始学习R语言。 第1章 R语言介绍 1.1 R的获取和安装 下载Rgui:http://cran....
    弹跳骑士阅读 7,902评论 0 10
  • 一、下载composer.phar php -r "readfile('https://getcomposer.o...
    吃口奶阅读 1,819评论 0 0
  • 正逢重阳的第二天,于老像往常一样在距离家方圆五百里远的小湖面上划着小船,他这大半生可都在这小船上度过,远处白茫茫的...
    西瓜E阅读 258评论 0 0
  • 先汇报一下今天的活动。上午学习彩泥画,下午传统文化,学习孝道,晚上联欢会。 昨天晚上有两个孩子因为发烧回家治疗。三...
    豆豆疯长阅读 409评论 1 4
  • 又一个同学因病医治无效走了,因为不敢面对,几个女同学都被去探望过的男同学劝住,说他几天水米不进,器官...
    灏钰阅读 1,992评论 0 0