美文网首页R for statisticsR语言
【R语言实战】Chapter5 高级数据管理

【R语言实战】Chapter5 高级数据管理

作者: 巩翔宇Ibrahimovic | 来源:发表于2021-02-14 15:09 被阅读0次

    写在前面
    前面的初级数据管理只能让你了解一下R在处理各种不同类型数据时发挥的便捷性,平时的科研工作中遇到最多的还是高级数据管理。包括各种需求的组合以及控制流的使用等。

    5.1 一个数据处理难题

    要讨论数值和字符处理函数,让我们首先考虑一个数据处理问题。一组学生参加了数学、科 学和英语考试。为了给所有学生确定一个单一的成绩衡量指标,需要将这些科目的成绩组合起来。 另外,你还想将前20%的学生评定为A,接下来20%的学生评定为B,依次类推。后,你希望按 字母顺序对学生排序。数据如表5-1所示。


    image.png

    5.2 数值和字符处理函数

    本小节介绍数据处理的基石函数,包括数值(数学,统计和概率)函数和字符处理函数。

    5.2.1 数字函数

    image.png
    image.png

    5.2.2 统计函数

    image.png
    image.png

    数据的标准化
    默认情况下,函数scale()对矩阵或数据框的指定列进行均值为0,标准差为1的标准化。

    > newdata <- scale(mydata)
    

    5.2.3 概率函数

    image.png

    正态分布函数


    image.png

    1.设定随机数种子

    在每次生成伪随机数的时候,函数都会使用一个不同的种子,因此也会产生不同的结果。你可以通过函数set.seed()显式指定这个种子,让结果可以重现(reproducible),也就是别人可以重复你的代码。下面的代码给出了一个示例。这里的函数runif()用来生成0到1区间上服从均匀分布的伪随机数。

    > runif(5) 
    [1] 0.8725344 0.3962501 0.6826534 0.3667821 0.9255909 
    > runif(5) 
    [1] 0.4273903 0.2641101 0.3550058 0.3233044 0.6584988 
    > set.seed(1234) 
    > runif(5) 
    [1] 0.1137034 0.6222994 0.6092747 0.6233794 0.8609154 
    > set.seed(1234) 
    > runif(5) 
    [1] 0.1137034 0.6222994 0.6092747 0.6233794 0.8609154 
    

    2. 生成多元正态数据

    在模拟研究和蒙特卡洛方法中,你经常需要获取来自给定均值向量和协方差阵的多元正态分 布的数据。MASS包中的mvrnorm()函数可以让这个问题变得很容易。其调用格式为:

    mvrnorm(n, mean, sigma)
    

    其中n是你想要的样本大小,mean为均值向量,而sigma是方差-协方差矩阵(或相关矩阵)。


    image.png

    5.2.4 字符处理函数

    image.png
    image.png

    函数grep()、sub()和strsplit()能够搜索某个文本字符串(fixed=TRUE)或 某个正则表达式(fixed=FALSE,默认值为FALSE)。
    正则表达式举例:

    ^[hc]?at 
    

    可以匹配任意以0个或1个h或c开头,后接at的字符串。

    5.2.5 其他实用函数

    image.png

    5.2.6 将函数应用于矩阵和数据框

    > a <- 5 > sqrt(a)  
    [1] 2.236068 
    > b <- c(1.243, 5.654, 2.99) 
    > round(b) #将b舍入为指定位的小数
    [1] 1 6 3 
    > c <- matrix(runif(12), nrow=3) 
    > c       
          [,1]  [,2]  [,3]  [,4] 
    [1,] 0.4205 0.355 0.699 0.323 
    [2,] 0.0270 0.601 0.181 0.926
    [3,] 0.6682 0.319 0.599 0.215 
    > log(c)        
         [,1]   [,2]   [,3]   [,4] 
    [1,] -0.866 -1.036 -0.358 -1.130 
    [2,] -3.614 -0.508 -1.711 -0.077 
    [3,] -0.403 -1.144 -0.513 -1.538 
    > mean(c) 
    [1] 0.444
    

    上述代码框的最后一行代码,函数mean()求的是矩阵中全部12个元素的均值,如果想求的是各行或各列的均值,应该用apply()函数,她可以将将一个任意函数“应用”到矩阵、数组、数据框的任何维 度上。apply()函数的使用格式为:

    apply(x, MARGIN, FUN, ...) 
    

    x为数据对象,MARGIN是维度的下标,FUN是由你指定的函数,而...则包括了任何想传 递给FUN的参数。在矩阵或数据框中,MARGIN=1表示行,MARGIN=2表示列。
    apply()可把函数应用到数组的某个维度上,而lapply()sapply()则可将函数 应用到列表(list)上.

    5.3 数据处理难题的一套解决方案

    5.1节中提出的问题是:将学生的各科考试成绩组合为单一的成绩衡量指标,基于相对名次 (前20%、下20%、等等)给出从A到F的评分,根据学生姓氏和名字的首字母对花名册进行排序。
    步骤1:

    options(digits=2)限定了输出小数点后数字的 位数,并且让输出更容易阅读。

    > options(digits=2) 
    > Student <- c("John Davis", "Angela Williams", "Bullwinkle Moose", "David Jones", "Janice Markhammer", "Cheryl Cushing",  "Reuven Ytzrhak", "Greg Knox", "Joel England", "Mary Rayburn") 
    > Math <- c(502, 600, 412, 358, 495, 512, 410, 625, 573, 522) 
    > Science <- c(95, 99, 80, 82, 75, 85, 80, 95, 89, 86) 
    > English <- c(25, 22, 18, 15, 20, 28, 15, 30, 27, 18) 
    > roster <- data.frame(Student, Math, Science, English,stringsAsFactors=FALSE) 
    

    步骤2 由于数学、科学和英语考试的分值不同(均值和标准差相去甚远),在组合之前需 要先让它们变得可以比较。一种方法是将变量进行标准化,这样每科考试的成绩就都是用单位 标准差来表示,而不是以原始的尺度来表示了。这个过程可以使用scale()函数来实现:

    > z <- scale(roster[,2:4]) 
    

    步骤3 然后,可以通过函数mean()来计算各行的均值以获得综合得分,并使用函数 cbind()将其添加到花名册中:

    > score <- apply(z, 1, mean) 
    > roster <- cbind(roster, score) 
    

    步骤4 函数quantile()给出了学生综合得分的百分位数。可以看到,成绩为A的分界点为 0.74,B的分界点为0.44,等等。

    > y <- quantile(score, c(.8,.6,.4,.2))
    > y    
    80%   60%   40%   20%  
    0.74  0.44 -0.36 -0.89  
    

    步骤5 通过使用逻辑运算符,你可以将学生的百分位数排名重编码为一个新的类别型成绩 变量。下面在数据框roster中创建了变量grade。

    > roster$grade[score >= y[1]] <- "A" 
    > roster$grade[score < y[1] & score >= y[2]] <- "B" 
    > roster$grade[score < y[2] & score >= y[3]] <- "C" 
    > roster$grade[score < y[3] & score >= y[4]] <- "D" 
    > roster$grade[score < y[4]] <- "F" 
    

    步骤6 你将使用函数strsplit()以空格为界把学生姓名拆分为姓氏和名字。把 strsplit()应用到一个字符串组成的向量上会返回一个列表:

    > name <- strsplit((roster$Student), " ") 
    

    步骤7 你可以使用函数sapply()提取列表中每个成分的第一个元素,放入一个储存名字 的向量Firstname,并提取每个成分的第二个元素,放入一个储存姓氏的向量Lastname。"[" 是一个可以提取某个对象的一部分的函数——在这里它是用来提取列表name各成分中的第一 个或第二个元素的。你将使用cbind()把它们添加到花名册中。由于已经不再需要student变 量,可以将其丢弃(在下标中使用–1)。

    > Lastname <- sapply(name, "[", 2) 
    > Firstname <- sapply(name, "[", 1) 
    > roster <- cbind(Firstname,Lastname, roster[,-1]) 
    

    步骤8 后,可以使用函数order()依姓氏和名字对数据集进行排序:

    > roster <- roster[order(Lastname,Firstname),] 
    > roster 
        Firstname   Lastname Math Science English score grade
    6      Cheryl    Cushing  512      85      28  0.35     C
    1        John      Davis  502      95      25  0.56     B
    9        Joel    England  573      89      27  0.70     B
    4       David      Jones  358      82      15 -1.16     F
    8        Greg       Knox  625      95      30  1.34     A
    5      Janice Markhammer  495      75      20 -0.63     D
    3  Bullwinkle      Moose  412      80      18 -0.86     D
    10       Mary    Rayburn  522      86      18 -0.18     C
    2      Angela   Williams  600      99      22  0.92     A
    7      Reuven    Ytzrhak  410      80      15 -1.05     F
    

    5.4 控制流

    在正常情况下,R程序中的语句是从上至下顺序执行的。但有时你可能希望重复执行某些语 句,仅在满足特定条件的情况下执行另外的语句。这就是控制流结构发挥作用的地方了。
    R拥有一般现代编程语言中都有的标准控制结构。首先你将看到用于条件执行的结构,接下 来是用于循环执行的结构。
    为了理解贯穿本节的语法示例,请牢记以下概念:
    语句(statement)是一条单独的R语句或一组复合语句(包含在花括号{ }中的一组R 语句,使用分号分隔);
    条件(cond)是一条终被解析为真(TRUE)或假(FALSE)的表达式;
    表达式(expr)是一条数值或字符串的求值语句;
    序列(seq)是一个数值或字符串序列。
    在讨论过控制流的构造后,我们将学习如何编写函数。

    5.4.1 重复和循环

    循环结构重复地执行一个或一系列语句,直到某个条件不为真为止。循环结构包括for和 while结构。
    1. for结构
    for循环重复地执行一个语句,直到某个变量的值不再包含在序列seq中为止。语法为:
    for (var in seq) statement
    在下例中:

    for (i in 1:10)  print("Hello") 
    

    单词Hello被输出了10次。
    2. while结构
    while循环重复地执行一个语句,直到条件不为真为止。语法为:
    while (cond) statement
    作为第二个例子,代码:

    i <- 10 while (i > 0) {print("Hello"); i <- i - 1} 
    

    又将单词Hello输出了10次。请确保括号内while的条件语句能够改变,即让它在某个时刻不再为 真——否则循环将永不停止!
    在上例中,语句:
    i <- i – 1 在每步循环中为对象i减去1,这样在十次循环过后,它就不再大于0了。反之,如果在每步循环 都加1的话,R将不停地打招呼。这也是while循环可能较其他循环结构更危险的原因。 在处理大数据集中的行和列时,R中的循环可能比较低效费时。只要可能,好联用R中的 内建数值/字符处理函数和apply族函数。

    5.4.2 条件执行

    在条件执行结构中,一条或一组语句仅在满足一个指定条件时执行。条件执行结构包括 if-else、ifelse和switch。
    1. if-else结构
    控制结构if-else在某个给定条件为真时执行语句。也可以同时在条件为假时执行另外的语 句。语法为:

    if (cond) statement if (cond) statement1 else statement2 
    

    示例如下:

    if (is.character(grade)) grade <- as.factor(grade)  
    if (!is.factor(grade)) grade <- as.factor(grade) else print("Grade already     is a factor") 
    

    在第一个实例中,如果grade是一个字符向量,它就会被转换为一个因子。在第二个实例中, 两个语句择其一执行。如果grade不是一个因子(注意符号!),它就会被转换为一个因子。如果 它是一个因子,就会输出一段信息。
    2. ifelse结构
    ifelse结构是if-else结构比较紧凑的向量化版本,其语法为:

    ifelse(cond, statement1, statement2) 
    

    若cond为TRUE,则执行第一个语句;若cond为FALSE,则执行第二个语句。示例如下:

    ifelse(score > 0.5, print("Passed"), print("Failed")) 
    outcome <- ifelse (score > 0.5, "Passed", "Failed") 
    

    在程序的行为是二元时,或者希望结构的输入和输出均为向量时,请使用ifelse。

    相关文章

      网友评论

        本文标题:【R语言实战】Chapter5 高级数据管理

        本文链接:https://www.haomeiwen.com/subject/ehjyxltx.html