标签: 教程

  • 第七章 R语言中的列表

    列表是一个能组织值、向量、数据框、矩阵等的容器,可以把各种变量按照顺序组织在一起。

    还是以表4-1为例,我们知道,计算只能在数值上,那么,实际上数据框是不适合直接计算的。我们把这个数据框改成列表。

    数据表4-1

    姓名性别英语成绩评定
    张三男95优秀
    李四女84良好
    王五男61合格
    name <- c("张三","李四","王五")
    gender <- c("男","女","男")
    English_score <- c(95,84,61)
    English_grade <- c("优秀","良好","合格")
    # 创建列表
    English_class <- list(name,gender,English_score,English_grade)
    # 显示列表内容
    English_class
    

    结果如下:

    > English_class
    [[1]]
    [1] "张三" "李四" "王五"
    
    [[2]]
    [1] "男" "女" "男"
    
    [[3]]
    [1] 95 84 61
    
    [[4]]
    [1] "优秀" "良好" "合格"

    像其他数据组织形式一样,列表也能命名。

    English_class <- list("姓名" = name, "性别" = gender, "英语成绩" = English_score, "英语评级" = English_grade)
    English_class
    

    结果如下:

    $姓名
    [1] "张三" "李四" "王五"
    
    $性别
    [1] "男" "女" "男"
    
    $英语成绩
    [1] 95 84 61
    
    $英语评级
    [1] "优秀" "良好" "合格"

    数据的提取:

    # 提取列表中的第一个元素,以列表形式展现
    English_class[1]
    
    # 提取列表中的第一个元素,以非列表形式展现,如向量、矩阵
    English_class[[1]]
    
    # 提取列表中第一个元素的第一个元素
    English_class[[1]][1]
    unlist(English_class[1])[1]
    
    # 已经命名的列表,可以用$符号提取元素,也可以直接用名称提取
    English_class["姓名"]
    English_class[["姓名"]]
    English_class$姓名
    English_class$姓名[1]
    

    结果如下:

    > # 提取列表中的第一个元素,以列表形式展现
    > English_class[1]
    $姓名
    [1] "张三" "李四" "王五"
    
    > 
    > # 提取列表中的第一个元素,以非列表形式展现,如向量、矩阵
    > English_class[[1]]
    [1] "张三" "李四" "王五"
    > 
    > # 提取列表中第一个元素的第一个元素
    > English_class[[1]][1]
    [1] "张三"
    > unlist(English_class[1])[1]
     姓名1 
    "张三" 
    > 
    > # 已经命名的列表,可以用$符号提取元素,也可以直接用名称提取
    > English_class["姓名"]
    $姓名
    [1] "张三" "李四" "王五"
    
    > English_class[["姓名"]]
    [1] "张三" "李四" "王五"
    > English_class$姓名
    [1] "张三" "李四" "王五"
    > English_class$姓名[1]
    [1] "张三"

    列表是有长度的,列表中元素的个数即为列表的长度,列表中某个元素中子元素的个数,为该子元素的长度。

    # 列表的长度
    length(English_class)
    # 列表中,子元素"姓名"的长度
    length(English_class$姓名)
    

    结果如下:

    > length(English_class)
    [1] 4
    > length(English_class$姓名)
    [1] 3

    我们可以向列表中添加内容,也就是元素。比如我们要加入数学和语文成绩。

    # 向列表中添加元素
    English_class[[length(English_class) + 1]] <- data.frame("数学成绩" = c(99, 88, 77), "语文成绩" = c(66, 55, 44))
    

    结果如下:

    > English_class
    $姓名
    [1] "张三" "李四" "王五"
    
    $性别
    [1] "男" "女" "男"
    
    $英语成绩
    [1] 95 84 61
    
    $英语评级
    [1] "优秀" "良好" "合格"
    
    [[5]]
      数学成绩 语文成绩
    1       99       66
    2       88       55
    3       77       44

    删除列表中的元素也是非常简单的,类似于向量的操作。

    # 删除元素
    (English_class[-2])   # 删除性别
    (English_class[[3]] <- NULL)   # 删除英语成绩
    English_class
    

    结果如下:

    > (English_class[-2])
    $姓名
    [1] "张三" "李四" "王五"
    
    $英语成绩
    [1] 95 84 61
    
    $英语评级
    [1] "优秀" "良好" "合格"
    
    [[4]]
      数学成绩 语文成绩
    1       99       66
    2       88       55
    3       77       44
    
    > (English_class[[3]] <- NULL)
    NULL
    > English_class
    $姓名
    [1] "张三" "李四" "王五"
    
    $性别
    [1] "男" "女" "男"
    
    $英语评级
    [1] "优秀" "良好" "合格"
    
    [[4]]
      数学成绩 语文成绩
    1       99       66
    2       88       55
    3       77       44

    列表是可以叠加的,把一个列表和另一个列表相连。我们把数学成绩和语文成绩从这个列表中删除,然后放在另一个列表内。

    (English_class[-4])
    other_score <- list("数学成绩" = c(99, 88, 77), "语文成绩" = c(66, 55, 44))
    list_in_list <- list(English_class,other_score)   # list_in_list <- append(English_class,other_score)两者有区别
    list_in_list
    

    结果如下:

    > (English_class[-4])
    $姓名
    [1] "张三" "李四" "王五"
    
    $性别
    [1] "男" "女" "男"
    
    $英语评级
    [1] "优秀" "良好" "合格"
    
    > other_score <- list("数学成绩" = c(99, 88, 77), "语文成绩" = c(66, 55, 44))
    > other_score
    $数学成绩
    [1] 99 88 77
    
    $语文成绩
    [1] 66 55 44
    
    > list_in_list <- list(English_class,other_score)
    > list_in_list
    [[1]]
    [[1]]$姓名
    [1] "张三" "李四" "王五"
    
    [[1]]$性别
    [1] "男" "女" "男"
    
    [[1]]$英语评级
    [1] "优秀" "良好" "合格"
    
    [[2]]
    [[2]]$数学成绩
    [1] 99 88 77
    
    [[2]]$语文成绩
    [1] 66 55 44

    类似的,查看列表的元素,可以用下面的代码。

    list_in_list[[1]]
    list_in_list[[2]]
    list_in_list[[1]]$姓名
    

    结果如下:

    > list_in_list[[1]]
    $姓名
    [1] "张三" "李四" "王五"
    
    $性别
    [1] "男" "女" "男"
    
    $英语评级
    [1] "优秀" "良好" "合格"
    
    > list_in_list[[2]]
    $数学成绩
    [1] 99 88 77
    
    $语文成绩
    [1] 66 55 44
    
    > list_in_list[[1]]$性别
    [1] "男" "女" "男"

  • 第四章 R语言的数据框(data.frame)

    数据框是R语言最重要的数据表现形式,数以万计的数据通过形成一个巨大的“表”来标准化数据结构,再从中抽取部分或全部数据用于分析,这个“表”叫做数据框。数据框和矩阵非常类似,不同点在于,数据框可以指定每一列的数据类型,而整个矩阵只能有且只有一种数据类型。

    下面,我们尝试录入数据类型。

    数据表4-1

    姓名性别英语成绩评定
    张三男95优秀
    李四女84良好
    王五男61合格

    从表4-1中不难发现,数据并非都是数值型,还有字符型的列,比如性别和评定。此时,用数据框就更为合适,因为数据框可以为每一列分配不同的数据类型。数据框在使用上更加符合人类的习惯,因为数据并不只有数值型,还是有很多其他类型,如定性类:姓名、性别、邮政编码、民族、态度(同意、不同意)、分级等。这些可以用字符串(string)来表示,也可以用因子(factor)表示。

    我们可以通过下面的方法构建数据框:

    names <- c("张三", "李四", "王五")

    gender <- c("男", "女", "男")

    English_scores <- c(95, 84, 61)

    evaluation <- c("优", "良", "合格")

    dataframe <- data.frame(names=names,
    gender=gender,
    English_scores=English_scores,
    evaluation=evaluation)

    dataframe

    class(dataframe)

    上面列举了一种通过向量获得数据框的方法,当然还可以先将向量转换成矩阵,再转换成数据框。

    dataframe2 <- cbind(names,gender,English_scores,evaluation)

    dataframe2 <- as.data.frame(dataframe2)

    dataframe2

    当只有纸制记录的原始数据,需要录入的时候,比较麻烦,可以通过下面的方式录入的R语言的数据框。

    dataframe <- data.frame(names=c("张三", "李四", "王五"),
    gender=c("男", "女", "男"),
    English_scores=c(95, 84, 61),
    evaluation=c("优", "良", "合格"))

    dataframe

    在数据量大的时候,通过上述方式逐个录入是很容易出错的,最好是先录入到Excel中,在读取到R程序,后面会有章节专门介绍。

    思考题

    1. 数据框和矩阵有哪些区别?
    2. 自己编造一个四行四列的数据,手动录入到R的一个变量中,并显示出来。
  • 第六章 R语言的逻辑值

    R语言的逻辑值(也称布尔值,Boolean)共有两种,TRUE和FALSE,可以简写为T和F,注意都是大写的。它们也可以用数值1和0表示。

    一般而言,判断运算得到的是逻辑值。例如,1>2,会返回FALSE;5>=1,会返回TRUE;10==10,会返回TRUE,这里要注意,判断运算的相等需要写2个等号,因为一个等号已经做赋值符号用了等同于'<-‘。

    在R语言中,不仅数值可以计算逻辑值,逻辑值和字符串也可以计算逻辑值。你可以尝试使用TRUE==TRUE来计算逻辑结果;也可以利用”a”==”A”来计算逻辑结果;还可以计算TRUE==1。

    不等于也是一个判断符号,但是R语言中的不等于符号并不是≠,而是!=。例如,4!=5,会返回TRUE。!的作用是取反,!=的意思是对相等取反,就是不等于的意思。同理,!可以与逻辑值连用,起到对逻辑值取反的作用。如:!TRUE的结果是FALSE;!FALSE的结果是TRUE。!可以和不等式连用,像!5>7得到的结果是TRUE,这里的计算顺序是先算5>7,结果为FALSE,再取反,得到TRUE。可以看出,计算的优先顺序,不等式计算优先级要高于取反运算。

    在实际应用中,我们常常会遇到多个条件判断的情形。看这个例子,一群学生考研,英语需要高于40,政治需要高于60,专业课需要高于70分才能录取。此时,就需要多个判断运算同时起作用。

    假如:小红的英语、政治和专业课成绩分别为xiaohong <- c(41,75,90),用判断语句判断小红是否考上的判断是:

    xiaohong[1] > 40 & xiaohong[2] > 60 & xiaohong[3] > 70

    不难看出,多个条件并列用&符号链接,&表示与,必须所有条件都为TRUE才为TRUE;相应的,|符合表示或,只要有一个条件为TRUE即为TRUE。

    当一个逻辑值和一个逻辑值向量并列时,&符号会将单个逻辑值复制为向量的个数,然后一一进行运算。

    TRUE & c(TRUE,FALSE,FALSE)

    这可能并不是我们想要的结果,如果我们只想对向量中的第一个逻辑值进行运算,可以使用严格并列符号&&和严格或符号||。这样,向量中只有第一个逻辑值会和前面的逻辑值发生运算。

    TRUE || c(TRUE, FALSE ,FALSE)

    判断函数,isTRUE()和isFALSE(),判断逻辑值的判断函数,说起来很拗口。顾名思义,isTRUE的参数为TRUE时,结果为TRUE,否则为FALSE;isFALSE的参数为FALSE是,结果为TRUE,否则为FALSE。自己可以练习一下。

    identical()函数可以判断两个对象是否完全相等。完全相等则为TRUE,不完全相等则为FALSE。传入的两个参数顺序可以颠倒,可以使用变量。

    identical(c(1,2,3),c(1,2,3))

    xor()函数叫做亦或判断函数,如果两个参数一个是TRUE一个是FALSE则返回TRUE,否则返回FALSE。在该函数中,FALSE可以用0表示,0以外的其他数字都相当于TRUE。

    xor(0,-1)
    xor(1,-1)
    xor(TRUE,FALSE)

    逻辑值在筛选数据上具有巨大的作用。当学校的英语成绩为14,34,56,34,78,68,87,69,88,100时,要快速挑出不及格的分数,可以用which函数和逻辑运算。

    scores <- c(14, 34, 56, 34, 78, 68, 87, 69, 88, 100)
    which(scores < 60)
    scores[which(scores < 60)]

    当统计全校的分数时,数据量已经很大,很难一眼看出是否有不及格的同学,这个时候可以使用any()函数:只要有一个满足条件即为TRUE。any(scores < 60)返回TRUE,说明数据中有不及格的分数。

    scores <- c(14, 34, 56, 34, 78, 68, 87, 69, 88, 100)
    any(scores < 60)

    同理,我们可以用all()函数判断是否所有人都及格了。很明显,并不是所有人都及格了。

    all(scores > 60)

    当需要加载R包的时候,用requrie()函数可以返回逻辑值,加载成功为TRUE,加载失败为FALSE。

    思考题

    1. 下列返回FALSE的是哪个选项?
    A:9 >= 10
    B:7 == 7
    C:0 > -36
    D:6 < 8

    2. 下列哪个选项返回TRUE?
    A:9 >= 10
    B:57 < 8
    C:7 == 9
    D:-6 > -7

    3. 下列哪个选项返回FALSE?
    A:9 < 10
    B:!FALSE
    C:!(0 >= -1)
    D:7 != 8

    4. 请说明逻辑与&和严格逻辑与&&的区别?

    5. 5>8||6!=8&&4>3.9的结果?

    6. 下列结果为TRUE的是?
    A:TRUE && FALSE || 10 >= 5 && 1 < 8
    B:FALSE || TRUE && FALSE
    C:99.99 > 100 || 28 < 2.3 || 8 != 8.0
    D:TRUE && 15 < 15 && 6 >= 6

    7. 下列结果为FALSE的是?
    A:FALSE && 12 >= 12 || 1 >= 4 || 80 <= 49.5
    B:6 >= -3 && !(9 > 10) && !(!TRUE)
    C:FALSE || TRUE && 8 != 1 || 26 > 3
    D:!(8 > 7) || 19 == 19.0 && 7.8 >= 7.79

    8. 下列哪个结果是TRUE?
    A:isTRUE(!TRUE)
    B:isTRUE(3)
    C:!isTRUE(4 < 3)
    D:!isTRUE(8 != 5)
    E:isTRUE(NA)

    9. 下列哪个选项的结果为TRUE?
    A:!identical(7, 7)
    B:identical(4, 3.1)
    C:identical(5 > 4, 3 < 3.1)
    D:identical(‘hello’, ‘Hello’)

    10. xor(12,-1)的结果是什么?

    11. 下列选项为FALSE的是哪个?
    A:xor(!isTRUE(TRUE), 6 > -1)
    B:xor(identical(xor, ‘xor’), 7 == 7.0)
    C:xor(!!TRUE, !!FALSE)
    D:xor(4 >= 9, 8 != 8.0)

    12. 请说明any()函数的作用?

    13. 请说明all()函数的作用?

  • 第五章 R语言的缺失值

    我们在记录数据时,经常会遇到缺失值。比如,统计一下全班同学的身高,恰巧有些同学今天生病没来,只记录了姓名或序号,却没有记录身高数值,这就造成了缺失。在R语言中,缺失值有两种形式,一种是NA,另一种是NaN,注意大小写。缺失值在实际统计运算中会对结果造成干扰,因此,在一些运算中需要先删除缺失值或使用补缺失(imputation)的方法,将缺失填充上值,再进行计算,降低对结果的影响。

    NA表示的是测定的时候为空(Missing)或当前值不可用(Not available)。NaN表示无意义的值,比如0除以0(0/0)或者无穷减去无穷(Inf-Inf)。NaN在实际应用中并不常用,而NA在实际应用中非常常见。NA和NaN都是占位符,无意义,无法进行运算。

    可以看一下实例,我们假设记录一个班级同学的身高(height),全班共7名同学(n=7)。

    height <- c(171,165,159,198,146,NA,184) # 其中有一个缺失值

    接下来,我们需要验证我们一共调差了几个同学,用到之前的length()函数。

    length(height) # 查看向量中元素的个数

    [1] 7

    得到的答案是7,也就是我们一共调查了7个人。接下来,我们做一些基本的统计运算,比如计算这几个人的平均身高。还记得求平均值的函数吗?mean()

    mean(height) # 计算平均身高,可以看到,下面的结果是NA,也就是NA对数据的计算造成了干扰

    [1] NA

    那么,我们应该怎么计算带有NA的均值呢?最简单的方法就是将NA去掉,然后再进行计算。R的内置函数中,已经集成了去掉NA的功能,即是用na.rm=T参数先去除数据中的NA再进行计算。

    mean(height, na.rm=T) # 先去掉NA,再计算均值

    [1] 170.5

    在一些高级运算中,没有直接可用的R语言的内置函数,需要我们自己编写代码进行计算。我们该怎样处理缺失值呢?这就要求我们先知道缺失值的位置或个数,然后再进行相应处理。这里我们用sum()函数再算一次均值。

    sumHeight <- sum(height, na.rm=T) # 对所有数据求和

    numberHeight <- length(height)-sum(is.na(height)) # 有效数据数量

    sumHeight/numberHeight # 计算均值

    [1] 170.5

    is.na()是专门处理缺失值的函数,它会得到一个与原向量等长的向量,并标注每一个对应的位置是否为缺失值。我们将sum()函数与is.na()函数连用,可以得到缺失值的个数,这可能很难理解,原因很简单,逻辑值FALSE被视为0,而逻辑值TRUE被视为1;is.na()得到的向量中,NA变成了TRUE(也就是1),非NA变成了FLASE(0),因此,用sum()函数可以求出缺失个数。下面,我们手动去掉缺失值,然后再计算平均值,用到which()函数,用来显示某个值的下标(位置)。

    heightNoNA <- height[-which(is.na(height))] # 将有NA的数据去掉

    heightNoNA <- height[!is.na(height)] # 将有NA的数据去掉

    mean(heightNoNA) # 计算均值

    [1] 170.5

    思考题:

    1. 用is.na()求缺失值个数。
    2. 不使用is.na()求出缺失值的个数。
    3. 写出能将NA下标(位置)显示出来的函数组合。
    4. 组合上面函数,写一行代码,直接算出平均值。
      # mean(height[!is.na(height)])
  • 第三章 R语言的矩阵(Matrix)

    利用向量,我们可以计算某个班级同学某一门课的平均分数,例如英语成绩:张三(95),李四(88),王二(79),这五(59),那六(92),这时候先建立向量并赋值给一个变量:

    English <- c(95,88,79,59,92)

    然后可以进行各种运算,比如求和,取均值,计算方差、标准差等。

    但是,我们的成绩并非只有英语一门,而是有很多门。在计算多门课程的分数时,可以用到R语言中的矩阵。矩阵是一种“矩形”的表格数据,有行有列,行通常情况表示“记录”,列表示“变量”或“字段”,虽然两者“颠倒”后仍然可以进行计算,但是依照国际惯例,最好遵从行为“记录”列为“变量”。每一条“记录”实际上就是你测试的对象及其在所有变量上的测定值或调查值。比如本例中,每个同学都有一个英语成绩,如表3-1,每一行为一条记录,英语成绩叫做“变量”或者“字段”。在矩阵中,全部值只能是一种类型,因此,作为字符型的姓名列不能在矩阵中,只能作为矩阵的行名。后文会继续介绍。

    姓名row.names英语成绩
    张三95
    李四88
    王二79
    这五59
    那六92
    表3-1 英语成绩的矩阵

    矩阵还有一个特别需要了解的概念是维度。每个变量表示1个维度,简单来说,有几列就是几维,例如有10个变量的矩阵即为10维矩阵。表3-1是有一个维度的矩阵。要查看一个对象的维度,可以使用dim()函数。注意在R语言中,向量是不能查询维度的,因为向量的维度固定为1。

    dim(English)

    NULL

    接下来是有趣的事情了,假如说,我们班级有5位同学,即张三,李四,王二,这五,那六。他们的英语成绩为:95、88、79、59、92;数学成绩为:98、60、58、82、71;体育成绩为:100、95、98、100、100。那么我们可以用向量的形式将成绩录入到R中。

    scores <- c(95, 88, 79, 59, 92, 98, 60, 58, 82, 71, 100, 95, 98, 100, 100)

    接下来,我们需要将这个向量转换成矩阵。用到上面的dim()函数。

    dim(scores) <- c(5,3) # 为向量增加维度属性,5条记录,3个变量

    scores # 查看结果

    class(scores) # 查看对象类型

    从上面结果可以看到,向量已经转换成我们期望的矩阵了。查看对象类型,也出现的矩阵字样。

    同样的,使用R内置的matrix()函数,也可以这样建立矩阵:

    scores <- c(95, 88, 79, 59, 92, 98, 60, 58, 82, 71, 100, 95, 98, 100, 100)
    matrix(scores, nrow=5)

    这个矩阵看起来略微别扭,没有显示人名和科目,我们现在将这个信息添加到矩阵中。用到rownames()和colnames()函数。

    rownames(scores) <- c(“张三”,”李四”,”王二”,”这五”,”那六”)
    colnames(scores) <- c(“英语”,”数学”,”体育”)
    scores

    从向量转变成矩阵还有另一种方法:1. 将每门功课的分数分别输入到向量;2. 利用cbind()函数将这些向量按照列组合起来。

    English <- c(95, 88, 79, 59, 92)
    mathematics <- c(98, 60, 58, 82, 71)
    P.E. <- c(100, 95, 98, 100, 100)
    scores2 <- cbind(English,mathematics,P.E.)
    socres2

    前面我们说了,矩阵内只能存储一种数据类型。那么,我们把多个数据类型放入矩阵中,看看会出现什么结果,比如:我们同学的姓名整合进矩阵中。

    cnames <- c(“张三”,”李四”,”王二”,”这五”,”那六”)
    scores3 <- cbind(cnames,English,mathematics,P.E.)
    scores3

    从结果中不难发现,所有的数据都加了双引号,即被识别为字符串。此时,程序发生了隐式强制(implicit coercion),我们没有要求它这么做,但它就这样发生了。字符串的结果是不能直接进行加减乘除等数学运算的,所以建立矩阵的时候一定要注意保持数据格式的统一。为什么强制转换成字符串而不是数值型呢?同学们可以考虑一下这个问题。

    思考题:

    1. 某一个给定的矩阵中的值有几种类型?
    2. 有三位同学,英语、数学、体育的分数分别为A:86、69、98;B:71、55、100;C:60、62、90。如果建立该矩阵?
  • 第二章 R语言的向量(vector)

    前面已经学过,R语言可以通过数字和运算符计算出想要的结果。但是,当我们需要对更多的数据进行计算时,比如要计算某个班级里学生的平均成绩,每次计算都输入所有班级同学的得分,然后再除以班级人数,显然看起来会很繁琐。

    例子:

    计算班级平均分,分数如下:

    张三(95),李四(88),王二(79),这五(59),那六(92),(31),(66),(92),(73),(94),(0),(55)。

    # 平均分计算

    (95+88+79+59+92+31+66+92+73+94+0+55)/12
    [1] 68.66667

    班级人数少,计算起来还算容易,如果班级有上百人,或者人事处需要统计整个学校教师的收入情况,找出收入最高和最低的人,同时计算工资总数和平均数。那么,每次计算都输入一长串的公式显然是难以承受的。基于此,“向量”的概念被提出。该“向量”并非数学中的向量,在数学中,向量表示的是有大小有方向的量,可以用带箭头的线段来表示,线段的长度表示大小,箭头表示方向;编程中的向量一般表示一维数据的集合,它可以包含数字、字符、逻辑值甚至是三者混排,这与数学中的向量含义不同。回到上面的例子,利用向量来计算班级的平均分:

    # 利用向量进行平均分计算

    scores <- c(95,88,79,59,92,31,66,92,73,94,0,55) # 将一组数输入向量,用c()函数。

    sum(scores)/length(scores) # sum()求和函数,length()求元素个数函数。
    [1] 68.66667

    mean(scores) # mean()求平均值函数。
    [1] 68.66667

    prod(scores) # 求乘积

    [1] 0

    max(scores) # max()最大值函数
    [1] 95

    min(scores) # min()最小值函数
    [1] 0

    median(scores) # median()中位数函数,如果是偶数,计算中间两个数的均值。
    [1] 76

    quantile(scores) # quantile()求四分位数函数。
    0% 25% 50% 75% 100%
    0    58    76     92      95

    summary(scores) # summary()总结函数,不同类型的元素结果不同。
    Min. 1st Qu. Median Mean 3rd Qu. Max.
    0.00    58.00      76.00 68.67      92.00 95.00

    str(scores) # str()紧凑显示该对象的R语言内部结构。
    num [1:12] 95 88 79 59 92 31 66 92 73 94 …

    细心的同学可能会发现一个问题,向量中的考试分数并不知道是来自哪位同学的,换句话说就是不知道谁得了多少分,这对理解数据显然是不利的。R语言的设计者当然也意识到了这个问题,因此,向量是可以添加“名字”的,用到names()函数。一定要注意,给数据添加名字的顺序要和原始数据一致。

    names(scores) # 直接使用names()函数,结果得到未定义NULL。
    NULL

    names(scores) <- c("张三","李四","王二","这五","那六") # 给向量加名字
    scores   # 查看scores向量
    张三 李四 王二 这五 那六 <NA> <NA> <NA> <NA> <NA> <NA> <NA>
    95     88    79    59     92       31      66      92        73      94         0       55

    (a <- c("张三"=95,"李四"=88,"王二"=79,"这五"=92)) # 直接带名字赋值向量,引号要改成英文状态,最外层加括号直接显示结果
    张三 李四 王二 这五
    95     88    79     92

    a["张三"] # 查看张三的分数
    张三
    95

    向量还可以进行增减和排序等操作。

    length(scores) # 查看scores向量有多少个元素
    [1] 12

    scores[13] <- 77 # 增加第13个元素为77

    scores[11] <- 20 # 将第11个元素改成20

    scores <- scores[-12] # 去掉第12个元素

    scores[1:3] <- c(20,20,20) # 将前3个元素改成20

    scores[c(4,6,10)] # 查看第4、6、10号元素

    scores[-c(4,6,10)] # 查看除了4、6、10号元素外的其他元素

    scores[c(4,6,10)] <- c(40,60,80) # 将第4、6、10个元素改成40,60,80

    scores[1:13] <- 100 # 1到13个元素改成100

    sort(scores) # 升序排列
    [1] 0 31 55 59 66 73 79 88 92 92 94 95

    sort(scores,decreasing = TRUE) # 降序排列
    [1] 95 94 92 92 88 79 73 66 59 55 31 0

    <p value="<amp-fit-text layout="fixed-height" min-font-size="6" max-font-size="72" height="80">向量子集的提取同样非常有用,比如,我们要提取高于或等于九十分一个或多个界限的分数有哪几个?向量子集的提取同样非常有用,比如,我们要提取高于或等于九十分一个或多个界限的分数有哪几个?

    scores[scores>=90]
    [1] 95 92 92 94

    scores[scores>=60]
    [1] 95 88 79 92 66 92 73 94

    scores[scores>=60&scores<85]
    [1] 79 66 73

    我相信,一定有“好事儿”的同学想验证一下,不大于60分的人和小于等于60分的子集提取方法,结果是否一样。在本例中,因为数据较少,结果一目了然,但在实际工作中,会处理大量数据,很难用肉眼分辨两组数据是否一样,这时候就用到了一个函数identical(),如果两个向量的顺序和值都相同,则得到TRUE,否则得到FALSE。

    scores[scores<60]
    [1] 59 31 0 55

    scores[!scores>=60]
    [1] 59 31 0 55

    identical(scores[!scores>=60],scores[scores<60])
    [1] TRUE

    好了,熟练掌握上面的内容,基本上本章已经可以达标了。下面看看简单的思考题。

    思考题:

    1. 结合前面学习的知识,计算scores的加、减、乘、除、取余等运算操作。
    2. 已知scores[1:5]<-100,那么scores+c(1:5)应该等于多少?
    3. 尝试提取scores的0号元素,或第200号元素,看看会发生什么?
    4. 假设一个变量为a<-c(1,0,0,1),请给这a向量的4个值添加名称(”张三”,”李四”,”王二”,”这五”)。
    5. 求88,64,96,99,100,59,87的四分位数。
    6. 将88,64,96,99,100,59,87按照降序排列。
    7. 提取子集,要求分数大于等于90且小于60。
  • 第一章 R语言的变量

    变量应该算是编程语言中应用范围最广的了,任何一个语言都离不开变量。变量,即一个容器,你将一些东西存放进去,例如:你有一个盒子,这个盒子你取名叫a,然后把6这个数字放进去,那么,不论谁拿到这个盒子,都能看见里面有一个6,当你将7放进去,同时把6取出来以后,任何人都能看到这个盒子里面有7,这就是最初的变量思想。在R语言中,变量可以存储任何东西,可以存储数值、字母、表达式、数组、数据框等等,有些概念还没有讲过,不必纠结,只要知道变量可以存储很多东西就可以了。

    下面学习如何操作变量,我们设置一个变量a,然后让a变量的值为15。

    a <- 15   # R语言的默认赋值时“箭头”赋值,箭头可以有方向。

    15 -> a   # 该结果与上面的结果一样。

    a = 15   # 该结果也与上面的结果一样。

    a   # 查看变量内容,只需要输入变量名称即可。

    当然,我们还可以将字符放入变量中。

    b <- “Hello World!”   # 字符串我们用英文状态下的双引号引起来,告诉程序这是字符串。

    b   # 查看变量b内容。

    ls()   # 是list的缩写,用于查看当前内存中的所有变量。

    rm(a)   # 当变量不再使用时,可以移除变量,用rm()函数。

    rm(a,b)   # 移除变量a和b,多个变量同时移除,用英文逗号隔开。

    rm(list=ls())   # 移除所有变量。

    在实际应用中,最好不要用单个字母来做变量名。变量名称需要易于理解,这样程序阅读或修改起来才更加容易。程序不是写一次就结束了,很多时候,程序需要根据情况不断地进行修改。

    我比较习惯的命名规则为,rowNo,moneyTotal,minAlleleFrequency等。当然还有其它比较好的命名规则,如有需要请自行百度。要说明的是,不要怕变量名长,人类理解比机器理解要重要的多,随遇到满屏幕的单字母变量都会头疼,读起来会很慢。

    另外,变量名称需要以字母开头,可以有下划线_或百分号%,其他符号是不允许的。

    函数实际上是实现某些功能的代码块,R语言本身内置了很多函数,方便我们使用。rm是Remove的缩写,移除变量。

  • QTL IciMapping基本信息

    QTL IciMapping是中国农业科学院作物科学研究所开发的一款整合型的QTL作图工具。

    软件集成8大功能

    (1)BIN,冗余标记去除;

    (2)MAP,连锁图谱构建;

    (3)CMP:多图谱共有标记分析;

    (4)SDL,分离失真基因座图谱构建;

    (5)BIP,加、显性和双基因上位效应作图;

    (6)MET,执行G×E,多环境需要多个输入文件;

    (7)CSL,染色体片段置换系的加、显、上位性作图;

    (8)NAM,NAM群体的QTL作图。

    其中,前4项功能只需要分子标记信息即可进行,后4项功能既需要分子标记信息也需要表型数据。

    群体类型

    群体类型不同,等位基因及基因型的理论频率不同,QTL IciMapping将群体分为20个类型+一个NAM群体,如图所示:

    理论频率如下表:

    Population no.Full nameGenotypeAllele
    AAABBBAB
    1P1BC1F10.50.500.750.25
    2P2BC1F100.50.50.250.75
    3F1DH0.500.50.50.5
    4F1RIL0.500.50.50.5
    5P1BC1RIL0.7500.250.750.25
    6P2BC1RIL0.2500.750.250.75
    7F20.250.50.250.50.5
    8F30.3750.250.3750.50.5
    9P1BC2F10.750.2500.8750.125
    10P2BC2F100.250.750.1250.875
    11P1BC2RIL0.87500.1250.8750.125
    12P2BC2RIL0.12500.8750.1250.875
    13P1BC1F20.6250.250.1250.750.25
    14P2BC1F20.1250.250.6250.250.75
    15P1BC2F20.81250.1250.06250.8750.125
    16P2BC2F20.06250.1250.81250.1250.875
    17P1BC1DH0.7500.250.750.25
    18P2BC1DH0.2500.750.250.75
    19P1BC2DH0.87500.1250.8750.125
    20P2BC2DH0.12500.8750.1250.875

    AA和BB是两个亲本贡献的基因型。

    等位基因编码表

    GenotypeAAABBBMissingAB + AAAB + BB
    Encoding options210− 112, D10, R
    AHBXAH, HABH, HB
    AAABBBXXAX, XABX, XB
    BA*A*, *AB*, *B
    **A_, _AB_, _B
    Encoding by number210− 11210
    Encoding by single letterAHBXDR
    Encoding by double lettersAAABBBXXAXXB

    比较推荐使用数字编码规则,即亲本1=2,亲本2=0,杂合=1,缺失=-1。在孟德尔遗传条件下,无法区分杂合和纯和显性的情况下,使用12和10,SNP标记由于可以确定和某一个亲本一致,因此用不到这两项。

    输出文件

    MTP在遗传群体中,不同标记和分离失真的卡方检验的频率
    SUM构建组合连锁图谱的概要
    LOD组合连锁关系(针对独立继承)的成对标记LOD值测试的下三角矩阵
    REC标记成对组合重组率估计估计的下三角矩阵
    DIS从组合重组率计算标记成对遗传距离(cM)的下三角矩阵
    SDLSDL功能的输入文件,用于分离失真基因座作图
    BIPBIL功能的输入文件,可在添加表型文件后进行加性和上位性作图
    METMET功能的输入文件,添加多环境数据后,计算QTL与环境互作

    名词解释

    染色体片段置换系(CSS,chromosome segment substitution),也叫做渐渗系(introgression lines),通常需要经过反复回交(有时使用分子标记来辅助选择),突出目标片段,而使非有效基因座上的基因替换为已知背景。在理想状态下,每个片段中包含一个QTL,去除背景,很容易验证是否片段中携带QTL。然而,CSS群体的构建需要很长时间,而且工作量巨大。在低世代的CSS中,有些片段含有多个QTL。在高强度的选择下,基因和标记的频率不遵循孟德尔遗传定律。因此,CSS的QTL作图方法采用基于逐步回归的似然比检测(stepwise regression-based likelihood ratio test,RSTEP-LRT)。

    NAM(nested association mapping)群体,是巢式关联作图群体,由一个共同亲本和多个亲本产生的若干RIL家系组成的多重交叉组配设计群体。对NAM群体的QTL方法叫联合复合区间作图群体( joint inclusive composite interval mapping,JICIM)。

  • 序章2——R语言简单的数学计算

    作为一门统计学语言,计算是其最基本的功能。在R语言中,可以直接运用数字进行运算。包括加、减、乘、除、幂、取整、取余等等。计算顺序与人类规定数学的计算方式完全一致,总体上从左到右进行计算。优先级方面,括号具有最高的优先级,然后是幂运算,之后是乘除法,最后加减。

    下面是示例代码,其中的#符号是R语言的注释符,每一行在#后面的所有内容都会被R语言忽略掉,换句话说就是不执行。注释在任何一个计算机语言中的作用都是一样的,就是给人解释语句,用于自己理解代码或与人分享代码时,让人清晰每一条语句或某一区块语句的作用。当然,注释还有其他作用,但由于本课程要求尽量轻薄,不予介绍。

    # 常规计算示例代码
    1+1 # 加法
    1-2 # 减法
    5*5 # 乘法
    5/3 # 除法
    2^10 # 幂运算
    5 %/% 3 # 整除,返回最大能整除的数
    5 %% 3 # 取余,返回余数
    1+6/2 # 复合运算
    (1+6)/2 # 括号在运算中的作用

    思考题:

    1. 计算2500*1987^2/2000+64789,思考为什么会得到这样的结果。如有疑问,请自行学习科学计数法。
  • 序章1——R语言环境的安装

    作为全世界最好的R语言入门课程,我们会由浅入深,逐渐带领大家熟悉R语言的语法和思路,同时也希望菜鸟们能够跟随本课程的步伐逐渐起飞。

    首先,要学习R语言,必不可少的是R语言的运行环境(或叫R语言解释器)。本章介绍R语言的安装,由于比较简单,有基础的同学可自行安装,直接学习下一章。

    1 R语言的安装

    1. 首先进入R语言官方的中国镜像站(https://mirrors.tuna.tsinghua.edu.cn/CRAN/),根据需要选择你自己电脑或服务器所使用的系统,这里以windows为例。
      R1.png
    2. 点击“install R for the first time”。
      R1-1.png
    3. 点击“Download R 3.5.0 for Windows (62 megabytes, 32/64 bit)”,版本号可能会有不同。
      R1-2.png
    4. 下载完成后直接安装即可,一路next直至安装完毕,安装后打开程序,见到如下界面说明安装成功。
      R1-3.png

    2 RStudio的安装

    工欲善其事必先利其器,光有R语言还不够,还需要有更加称手的装备,当然,这种装备不是必需的。

    RStudio是世界上最棒的R语言高亮代码编辑器和脚本运行器,我们将这样的编辑器叫做整合开发环境(integrated development environment, IDE)。它包含命令行窗口,可直接执行高亮语法的编辑器窗口,图像、文件等控制窗口和环境变量及历史显示窗口等。本课程所有截图全部基于RStudio。

    RStudio的安装由于不是必需,因此不做介绍,请童鞋们自行安装。RStudio安装完毕后会自动与R语言的最新版本关联。

    3 作业

    安装Rstudio。