R初识

前言

如何才能成功地处理、分析和理解数据:

  1. 获取数据(从各种数据源将数据导入程序);
  2. 整理数据(编码缺失值、修复或删除错误数据、将变量转换成更方便的格式);
  3. 注释数据(以记住每段数据的含义);
  4. 总结数据(通过描述性统计量了解数据的概况);
  5. 数据可视化(一图胜千言);
  6. 数据建模(解释数据间的关系,检验假设);
  7. 整理结果(创建具有出版水平的表格和图形)。

R简介

什么是R?

要是一本书里没有图画和对话,那还有什么意思呢?

​ ——爱丽丝《爱丽丝梦游仙境》

R是一个非常灵活的平台,是专用于探索、展示和理解数据的语言,因此我引用了《爱丽丝梦游仙境》的句子来表示当今统计分析的潮流——一个探索、展示和理解的交互式过程。

R简史,前世今生

R语言是从S统计绘图语言演变而来,可看作S的“方言”。

S语言上世纪70年代诞生于贝尔实验室,是一种用来进行数据探索、统计分析和作图的解释型语言。

1995年由新西兰Auckland大学,基于S语言的源代码,编写了一能执行S语言的软件,并将该软件的源代码全部公开,这就是R软件,其命令统称为R语言。

R的特点
  • 多领域的统计资源

    目前在R网站上约有5000多个程序包,涵盖了基础统计学、社会学、经济学、生物信息等诸多反面。

  • 跨平台

    R可在多种操作系统下运行,如Windows、MacOS、Linux等。

  • 命令行驱动

    R即时解释,输入命令,即可获得相应结果。

为什么选择R?
  • 丰富的资源

    涵盖了多种行业数据分析中几乎所有方法。

  • 良好的扩展性

    十分方便的编写函数和程序包,跨平台,可以胜任复杂的数据分析、绘制精美的图形。

  • 完备的帮助系统

    每个函数都有统一格式的帮助,运行实例。

  • GNU软件

    免费、软件本身及程序包的源代码公开

程序包

R程序包是多个函数的集合,具有详细的说明和示例。

Windows下的R包是经过编译的zip包。

每个程序包包含函数、数据、帮助文件、描述文件等。

R程序包是R功能扩展,特定的分析功能,需要用相应的程序包实现。

例如:画图常用到ggplot2程序包,系统发育分析,常用到ape程序包。

R语言数据类型与数据结构

R语言数据类型
类型
Numeric(数字) 12.3,5,999 v <- 23.5 print(class(v)) :”numeric”
Integer(整型) 2L,34L,0L v <- 2L print(class(v)) :”integer”
Complex(复合型) 3 + 2i v <- 2+5i print(class(v)) : “complex”
Character(字符) ‘a’ , ‘“good”, “TRUE”, ‘23.4’ v <- “TRUE” print(class(v)) :”character”
Raw(原型) “Hello” 被存储为 48 65 6c 6c 6f v <- charToRaw(“Hello”) print(class(v : “raw”
Logical(逻辑型) TRUE, FALSE v <- TRUE print(class(v)) : “logical”
R语言变量

变量为我们提供了我们的程序可以操作的命名存储。有效的变量名称由字母,数字和点或下划线字符组成。
变量名以字母或不以数字后跟的点开头。

变量名 合法性 原因
var_name2. 有效 有字母、数字、点和下划线
VAR_NAME% 无效 有字符%
2var_name 无效 数字开头
.var_name, 有效 可以用.开头
.2var_name 无效 .开头,后面接数字
_var_name 无效 _开头
R语言特殊运算符
符号 功能 例子
%% 两个向量求余 v <- c( 2,5.5,6) t <- c(8, 3, 4) print(v%%t) :2.0 2.5 2.0
%/% 两个向量相除求商 v <- c( 2,5.5,6) t <- c(8, 3, 4) print(v%/%t):0 1 1
^ 将第二向量作为第一向量的指数 v <- c( 2,5.5,6) t <- c(8, 3, 4) print(v^t) :256.000 166.375 1296.000
: 冒号运算符。 它为向量按顺序创建一系列数字。 v <- 2:8 print(v) :2 3 4 5 6 7 8
%in% 此运算符用于标识元素是否属于向量。 TRUE FALSE
R语言数据结构
  1. 向量

    向量是用于存储数值型、字符型或逻辑型数据的一维数组。执行组合功能的函数c()可用来创建向量。各类向量如下例所示:

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

    通过在方括号中给定元素所处位置的数值,我们可以访问向量中的元素。例如,a[c(1,2)]用于访问向量a中的第1个和第2个元素。

    1
    2
    a[c(1,2)]
    [1] 1 2

  2. 矩阵

    矩阵是一个二维数组,只是每个元素都拥有相同的模式(数值型、字符型或逻辑型)。可通过函数matrix创建矩阵。

  3. 数组

    数组(array)与矩阵类似,但是维度可以大于2。数组可通过array函数创建,形式如下:

    1
    myarray <-array(vector, dimensions, dimnames)

    其中vector包含了数组中的数据,dimensions是一个数值型向量,给出了各个维度下标的最大值,而dimnames是可选的、各维度名称标签的列表。

    示例:

    1
    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))
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    > 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

    从数组中选取元素的方式与矩阵相同。上例中,元素z[1,2,3]为15。

  4. 数据框

    由于不同的列可以包含不同模式(数值型、字符型等)的数据,数据框的概念较矩阵来说更为一般。它与你通常在SAS、SPSS和Stata中看到的数据集类似。数据框将是你在R中最常处理的数据结构。

    数据框可通过函数data.frame()创建:

    1
    mydata <-data.frame(col1, col2, col3,...)

    其中的列向量col1, col2,col3,…可为任何类型(如字符型、数值型或逻辑型)。每一列的名称可由函数names指定。

    1
    2
    3
    4
    5
    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)
    1
    2
    3
    4
    5
    6
    > 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
    • attach()、detach()和with()

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

      函数detach()将数据框从搜索路径中移除。值得注意的是,detach()并不会对数据框本身做任何处理。

      函数with(),大括号{}之间的语句都针对指定数据框执行

    • 实例标识符

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

      例如,语句:

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

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

  5. 因子

    变量可归结为名义型、有序型或连续型变量。名义型变量是没有顺序之分的类别变量。糖尿病类型Diabetes(Type1、Type2)是名义型变量的一例。有序型变量表示一种顺序关系,而非数量关系。病情Status(poor, improved, excellent)是顺序型变量的一个上佳示例。续型变量可以呈现为某个范围内的任意值,并同时表示了顺序和数量。

    类别(名义型)变量和有序类别(有序型)变量在R中称为因子(factor)。

    函数factor()以一个整数向量的形式存储类别值,整数的取值范围是[1… k ](其中k 是名义型变量中唯一值的个数),同时一个由字符串(原始值)组成的内部向量将映射到这些整数上。

    例子:

    1
    diabetes <- c("Type1","Type2","Type1","Type1")

    语句diabetes <-factor(diabetes)将此向量存储为(1, 2, 1, 1),并在内部将其关联为1=Type1和2=Type2(具体赋值根据字母顺序而定)。针对向量diabetes进行的任何分析都会将其作为名义型变量对待。

  6. 列表

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

    1
    mylist <-list(object1, object2, ...)

    其中的对象可以是目前为止讲到的任何结构。

    1
    2
    3
    4
    5
    g <- "My First List"
    h <- c(25,26,18,39)
    j <- matrix(1:10,nrow = 5)
    k <-c("noe","two","three")
    mylist <- list(title = g, ages = h, j, k)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    > 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] "noe" "two" "three"
    注意:
    1. 对象名称中的句点(.)没有特殊意义。但美元符号$却有着和其他语言中的句点类似的含义,即指定一个对象中的某些部分。例如,A$x是指数据框A中的变量x。
    2. R不提供多行注释或块注释功能。
    3. 将一个值赋给某个向量、矩阵、数组或列表中一个不存在的元素时,R将自动扩展这个数据结构以容纳新值。
    4. R中没有标量。标量以单元素向量的形式出现。
    5. R中的下标不从0开始,而从1开始。
    6. 变量无法被声明。它们在首次被赋值时生成。

数据的输入

R可从键盘、文本文件、Microsoft Excel和Access、流行的统计软件、特殊格式的文件,以及多种关系型数据库中导入数据。

初阶绘图

通过执行如plot()、hist()(绘制直方图)或barplot()(创建条形图),可以很方便的绘制图形。

例子:

1
2
H<- c(7,12,28,3,41)
barplot(H)

1
2
3
4
5
6
n=50000;
r=0.7;r_e=(1-r*r)^.5;
X=rnorm(n);
Y=Xr+r_ernorm(n);
Y=ifelse(X>0,Y,-Y);
plot(X,Y,col="pink")

案例展示

《红楼梦》文本分析以及关系网络的挖掘。

在这里主要进行和挖掘了如下内容:

  1. 《红楼梦》数据的准备、预处理、分词等
  2. 《红楼梦》各个章节的字数、词数、段落等相关方面的关系
  3. 《红楼梦》整体词频和词云的展示
  4. 《红楼梦》各个章节的聚类分析并可视化,主要进行了根据IF-IDF的系统聚类和根据词频的LDA主题模型聚类
  5. 《红楼梦》中关系网络的探索,主要探索了各个章节的关系图和人物关系网路图
  • 《红楼梦》数据的准备、预处理、分词等
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
##   [1] "金荣"       "人多势众"   "贾瑞"       "勒令"       "秦钟"      
## [6] "宝玉" "吵闹" "金荣" "回到" "家中"
## [11] "越想" "越气" "秦钟" "贾蓉" "小舅子"
## [16] "贾家" "子孙" "附学" "读书" "因仗"
## [21] "宝玉" "目中无人" "该行" "正经事" "素日"
## [26] "宝玉" "鬼鬼祟祟" "瞎子" "看不见" "今日"
## [31] "勾搭" "眼睛" "出事" "母亲" "胡氏"
## [36] "听见" "咕咕" "嘟嘟" "问道" "闲气"
## [41] "好容易" "我望" "姑妈" "姑妈" "千方百计"
## [46] "西府里" "琏二奶奶" "跟前" "念书" "地方"
## [51] "家里" "力量" "学里" "现成" "现成"
## [56] "二年" "念书" "家里" "嚼用" "穿件"
## [61] "鲜明" "衣服" "念书" "认得" "薛大爷"
## [66] "薛大爷" "一年" "二年" "七八十两" "银子"
## [71] "学房" "再要" "地方" "告诉" "比登"
## [76] "难呢" "一会" "觉去" "多着呢" "金荣"
  • 《红楼梦》各个章节的字数、词数、段落等相关方面的关系

  • 段落数、字数、词数三维散点图

  • 段落数、字数、词数矩阵散点图

  • 《红楼梦》整体词频和词云的展示

  • 《红楼梦》中章节关系

    源码实例

    基础导入

    1
    2
    3
    4
    library(rJava)
    library(Rwordseg)
    library(RColorBrewer)
    library(wordcloud)

    读入数据

    1
    lecture<-read.csv("E:/users/zeng/R/hongloumeng.txt", stringsAsFactors=FALSE,header=FALSE)

    优化词库

    1
    2
    3
    installDict("E:\\users\\zeng\\ciku\\红楼梦词汇大全.scel","hongloumeng1")
    installDict("E:\\users\\zeng\\ciku\\红楼梦群成员名字词库.scel","hongloumeng2")
    installDict("E:\\users\\zeng\\ciku\\红楼梦词汇.scel","hongloumeng3")

    分词+统计词频

    1
    2
    3
    4
    5
    6
    words=unlist(lapply(X=lecture, FUN=segmentCN))
    #unlist将list类型的数据,转化为vector
    #lapply()返回一个长度与X一致的列表,每个元素为FUN计算出的结果,且分别对应到X中的每个元素。
    word=lapply(X=words, FUN=strsplit, " ")
    v=table(unlist(word))
    #table统计数据的频数

    完整代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    library(rJava)
    library(Rwordseg)
    library(RColorBrewer)
    library(wordcloud)
    #读入数据
    lecture<-read.csv("E:/users/zeng/R/hongloumeng.txt", stringsAsFactors=FALSE,header=FALSE)
    #文本预处理
    res=lecture[]
    #分词+频数统计
    installDict("E:\\users\\zeng\\ciku\\红楼梦词汇大全.scel","hongloumeng1")
    installDict("E:\\users\\zeng\\ciku\\红楼梦群成员名字词库.scel","hongloumeng2")
    installDict("E:\\users\\zeng\\ciku\\红楼梦词汇.scel","hongloumeng3")
    words=unlist(lapply(X=res, FUN=segmentCN))

    #unlist将list类型的数据,转化为vector
    #lapply()返回一个长度与X一致的列表,每个元素为FUN计算出的结果,且分别对应到X中的每个元素。
    word=lapply(X=words, FUN=strsplit, " ")
    v=table(unlist(word))
    #table统计数据的频数
    # 降序排序
    v=rev(sort(v))

    d=data.frame(词汇=names(v), 词频=v) #创建数据框
    #过滤掉1个字和词频小于200的记录
    d=subset(d, nchar(as.character(d$词汇))>1 & d$词频>=100)

    #输出结果
    write.csv(d, file="E:/users/zeng/hongloumongresult.csv", row.names=FALSE)

    #画出标签云
    mydata<-read.csv("E:/users/zeng/hongloumengresult.csv",head=TRUE)
    mycolors <- brewer.pal(12,"Paired")
    windowsFonts(myFont=windowsFont("锐字巅峰粗黑简1.0"))
    wordcloud(mydata$词汇,mydata$词频,random.order=FALSE,random.color=TRUE,colors=mycolors,family="myFont")

    在黑板上写下50个数字:1至50.在接下来的49轮操作中,每次做如下动作:选取两个黑板上的数字a和b,擦去,在黑板上写|b – a|。请问最后一次动作之后剩下数字可能是什么?为什么?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    w=rep(0,7000)
    for(j in 1:7000){
    t=c(1:50)
    for(i in 1:49){
    q=sample(t,2)
    a=q[1];b=q[2];c=abs(a-b)
    t=t[-which(t==a)]
    len1=length(t)-50+i
    if(len1<0) t=c(t,rep(b,abs(len1)))
    t=t[-which(t==b)]
    len2=length(t)-49+i
    if(len2<0) t=c(t,rep(b,abs(len2)))
    t[length(t)+1]=c
    if(length(t)==1) w[j]=t
    }
    }
    summary(w)