ITPub博客

首页 > > > 【R语言】:高级数据管理(2)

【R语言】:高级数据管理(2)

作者:浪花小雨滴 时间:2020-06-17 10:33:20 0 删除 编辑
数学和统计函数
字符处理函数
循环和条件执行
自编函数
数据整合与重塑

控制流

在正常情况下,R语言程序是从上至下执行的。当需要重复执行某些语句或满足某种条件下执行另外的语句,可以使用控制流结构,即条件和循环。

理解R语言控制流的语法示例,需牢记以下概念:

  • 语句(statement)是一条单独的R语句或一组复合语句(包含在{}中的一组R语句,使用分号分割,即{expr});
  • 条件(cond)是一条最终被解析为逻辑值(真-TRUE、假-FALSE)的表达式;
  • 表达式(expr)是一条数值或字符串的求值语句;
  • 序列(seq)是一个数值或字符串序列。


一、重复和循环

循环结构重复地执行一个或一系列语句,直到某个条件不再为真,跳出或终止循环。循环结构包括for循环和while循环。

1、for结构

for循环重复执行一个语句,直到变量的值不再包含在序列seq中(即条件不为真)。

#for循环语法
for(var in seq) statement
#或者
for(var in seq) {expr}

#举例,将Great输出10次
for(i in 1:10) print("Great")

2、while结构

while循环重复执行一个语句,直到条件不再为真。

#while循环语法
while(cond) statement
#或者
while(cond) {expr}

#举例,将Great输出10次
i <- 10
#包含在{}中的R语句不止一个,即一组语句,每个语句中间用分号分割
while(i>0) {print("Great"); i <- i-1}

*注:如果while循环后面的条件语句无法改变,即如果条件语句不能为FALSE,则while循环将永远循环下去!这将造成程序崩溃、卡死。

所以在使用while循环的时候,切记要进行某种设定,使程序能够在循环N次之后改变条件语句,避免导致死循环。

在处理大数据集中的行和列时,R中的循环可能比较低效耗时,应该尽量使用R中内建的数值或字符处理函数和apply()族函数。

二、条件执行

在条件执行结构中,一条或一组语句仅在满足指定条件时执行。条件执行结构包括if-else、ifelse和switch。

1、if-else结构

在条件为真时执行一条(组)语句,当条件为假时执行另外的语句。

#if-else语法
if(cond) statement
if(cond) statement1 else statement2

#举例
#如果grade是字符型向量,则会被转换为因子
if (is.character(grade)) grade <- as.factor(grade)
#如果grade不是因子,则会被转换为因子;如果是一个因子,则会输出一段文字内容
if (!is.factor(grade)) grade <- as.factor(grade) else print("Grade already is a factor")

2、ifelse结构

ifelse结构是if-else结构比较紧凑的版本,并且使用时输入和输出必须均为向量,或者是二元的程序。

#ifelse语法。若cond为TRUE,执行statement1;若为FALSE,执行statement2
ifelse(cond, statement1, statement2)

3、switch结构

switch根据一个表达式的值选择语句执行。

#switch语法,其中后面的...表示与expr的各种可能输出值绑定的语句
switch(expr, ...)

#举例如下,可以很容易理解switch
feelings <- c("sad", "afraid")
for (i in feelings)
    print(
      switch(i,
             happy  = "I am glad you are happy",
             afraid = "There is nothing to fear",
             sad    = "Cheer up",
             angry  = "Calm down now"
    )
  )
[1] "Cheer up"
[1] "There is nothing to fear"

用户自编函数

支持用户自行添加函数是R语言的最大优点之一,并且R语言中的许多函数也是基于已有函数构成的。一个自编函数的结构大致如下:

myfunction <- function(arg1, arg2, ...){
    statements
    return(object)
}

自编函数中的对象只在函数内部使用(大括号{}的作用),返回对象的数据类型是任意的,从标量到列表均可。

假如某个用户编写了一个函数:用来计算数据对象的集中趋势和散布情况。该函数需要实现可以选择性地给出参数统计量(均值和标准差)和非参数统计量(中位数和绝对中位差);函数的运行结果是一个包含名称的列表;用户可以选择是否自动输出结果;除非另外指定,否则该函数的默认是计算参数统计量并且不输出结果。具体详见以下代码:

#mystats(): a user-written function 用户自编函数,for summary statistics
#对于统计对象x,以if函数为核心来自编函数。
#当参数(parametric)为真(TRUE),计算统计量的均值(mean)和标准差(sd)
#当参数为假(FALSE),计算统计量的中位数(median)和绝对中位差(mad)
#绝对中位差的含义是原始数据减去中位数后得到的新数据取绝对值后,再确定的中位数
#如果需要输出结果,利用函数cat()将字符串、数字以及换行符(\n)一并输出

mystats <- function(x, parametric=TRUE, print=FALSE) {
  if (parametric) {
    center <- mean(x); spread <- sd(x) 
  } else {
    center <- median(x); spread <- mad(x) 
  }
  if (print & parametric) {
    cat("Mean=", center, "\n", "SD=", spread, "\n")
  } else if (print & !parametric) {
    cat("Median=", center, "\n", "MAD=", spread, "\n")
  }
  result <- list(center=center, spread=spread)
  return(result)
}
*注:R语言中的函数cat()是一个输出函数,主要功能是把多个参数连接起来再输出(具有函数paste()的功能)。
注意使用函数cat()时要自己加上换行符"\n",把各项转换成字符串,中间以空格连接起来,然后显示。如果要使用自定义的分隔符,可以用sep=参数。下图代码就是将sep参数设置为空值使各项元素直接连接。
函数cat()还可以指定一个参数file=给一个文件名,可以把结果写到指定的文件中。
cat("i = ", 1, "\n", file="d:/Desktop/result.txt")

接下来看一下这个自编函数的实际应用。为了方便以后结果重现,需要先指定种子,然后生成一组服从正态分布,大小为500的随机样本。

#Trying it out 试一试

#指定种子1234
set.seed(1234)
#生成服从正态分布,大小为500的随机样本
x <- rnorm(500) 

#执行下面语句,函数将计算出样本的均值和标准差并且没有输出结果
y <- mystats(x)
#手动输入y$center查看均值
y$center
[1] 0.001838821
#手动输入y$spread查看标准差
y$spread
[1] 1.034814

#执行下面语句,函数将计算出样本的中位数和绝对中位差,并且输出结果
y <- mystats(x, parametric=FALSE, print=TRUE)
Median= -0.02070734 
 MAD= 1.000984 

下面是一个使用了switch结构的用户自编函数,该函数能够让用户选择输出当天日期的格式。其中参数(这里为type=)指定的值(这里为"long")为自编函数的默认值,即如果不指定参数type,将以long作为默认的日期格式。

#Another switch example 编写函数mydate
mydate <- function(type="long") {
    switch(type,
    long =  format(Sys.time(), "%A %B %d %Y"), 
    short = format(Sys.time(), "%m-%d-%y"),
    cat(type, "is not a recognized type\n"))
}

函数编写完成后,测试一下函数功能

mydate("long")
[1] "星期一 七月 10 2017"
mydate("short")
[1] "07-10-17"
mydate()
[1] "星期一 七月 10 2017"
mydate("medium")
medium is not a recognized type
自编函数中的最后一条语句利用函数cat()处理错误的参数输入,当用户输入错误参数将输出一句错误提示“XXX is not a recognized type”。此外,R语言中还有一些函数可以帮助自编函数添加错误捕获和纠正功能:比如利用函数warning()可以生成一条错误提示信息,利用函数message()可以生成一条诊断信息,利用函数stop()停止当前表达式的执行并提示错误。 更多关于调试程序的内容,请阅读Duncan Murdoch整理的“Debugging in R”。

整合与重构

R语言中提供了许多整合(aggregate)和重塑(reshape)数据的强大方法,

  • 整合数据:将多组观测替换为这些数据的描述统计量。
  • 重塑数据:通过修改数据的结构(行和列)来决定数据的组织方式。

接下来,以在【R语言】:基本数据管理(2)中用到过的R语言系统自带数据框mtcars为例,详细介绍说明。

一、转置

R语言中对数据集的转置与数学里矩阵的转置含义相同——反转行和列,方法很简单,用函数 t() 即可对一个矩阵或数据框进行转置。

#取数据框mtcars的前五行和前四列组成一个新数据框
cars <- mtcars[1:5, 1:4]
cars
                   mpg cyl disp  hp
Mazda RX4         21.0   6  160 110
Mazda RX4 Wag     21.0   6  160 110
Datsun 710        22.8   4  108  93
Hornet 4 Drive    21.4   6  258 110
Hornet Sportabout 18.7   8  360 175

#对数据框cars进行转置
t(cars)
     Mazda RX4 Mazda RX4 Wag Datsun 710 Hornet 4 Drive Hornet Sportabout
mpg         21            21       22.8           21.4              18.7
cyl          6             6        4.0            6.0               8.0
disp       160           160      108.0          258.0             360.0
hp         110           110       93.0          110.0             175.0

二、整合数据

使用一个或者多个by变量和一个预先定义好的函数FUN来折叠(collapse)数据,主要通过函数aggregate()来实现。

#x为待整合/折叠的数据对象
#by为一个由变量名组成的列表(list)
#FUN为用来计算描述性统计量的标量函数,计算新观测中的值
aggregate(x, by, FUN)

接下来,继续通过系统自带数据框mtcars为例具体演示函数的用法

#设置全局计算结果保留三位有效数字
options(digits=3)

#载入数据框mtcars
attach(mtcars)

#可以查看
mtcars
                     mpg cyl  disp  hp drat   wt qsec vs am gear carb
Mazda RX4           21.0   6 160.0 110 3.90 2.62 16.5  0  1    4    4
Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.88 17.0  0  1    4    4
Datsun 710          22.8   4 108.0  93 3.85 2.32 18.6  1  1    4    1
Hornet 4 Drive      21.4   6 258.0 110 3.08 3.21 19.4  1  0    3    1
Hornet Sportabout   18.7   8 360.0 175 3.15 3.44 17.0  0  0    3    2
Valiant             18.1   6 225.0 105 2.76 3.46 20.2  1  0    3    1
Duster 360          14.3   8 360.0 245 3.21 3.57 15.8  0  0    3    4
Merc 240D           24.4   4 146.7  62 3.69 3.19 20.0  1  0    4    2
Merc 230            22.8   4 140.8  95 3.92 3.15 22.9  1  0    4    2
Merc 280            19.2   6 167.6 123 3.92 3.44 18.3  1  0    4    4
Merc 280C           17.8   6 167.6 123 3.92 3.44 18.9  1  0    4    4
Merc 450SE          16.4   8 275.8 180 3.07 4.07 17.4  0  0    3    3
Merc 450SL          17.3   8 275.8 180 3.07 3.73 17.6  0  0    3    3
Merc 450SLC         15.2   8 275.8 180 3.07 3.78 18.0  0  0    3    3
Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.25 18.0  0  0    3    4
Lincoln Continental 10.4   8 460.0 215 3.00 5.42 17.8  0  0    3    4
Chrysler Imperial   14.7   8 440.0 230 3.23 5.34 17.4  0  0    3    4
Fiat 128            32.4   4  78.7  66 4.08 2.20 19.5  1  1    4    1
Honda Civic         30.4   4  75.7  52 4.93 1.61 18.5  1  1    4    2
Toyota Corolla      33.9   4  71.1  65 4.22 1.83 19.9  1  1    4    1
Toyota Corona       21.5   4 120.1  97 3.70 2.46 20.0  1  0    3    1
Dodge Challenger    15.5   8 318.0 150 2.76 3.52 16.9  0  0    3    2
AMC Javelin         15.2   8 304.0 150 3.15 3.44 17.3  0  0    3    2
Camaro Z28          13.3   8 350.0 245 3.73 3.84 15.4  0  0    3    4
Pontiac Firebird    19.2   8 400.0 175 3.08 3.85 17.1  0  0    3    2
Fiat X1-9           27.3   4  79.0  66 4.08 1.94 18.9  1  1    4    1
Porsche 914-2       26.0   4 120.3  91 4.43 2.14 16.7  0  1    5    2
Lotus Europa        30.4   4  95.1 113 3.77 1.51 16.9  1  1    5    2
Ford Pantera L      15.8   8 351.0 264 4.22 3.17 14.5  0  1    5    4
Ferrari Dino        19.7   6 145.0 175 3.62 2.77 15.5  0  1    5    6
Maserati Bora       15.0   8 301.0 335 3.54 3.57 14.6  0  1    5    8
Volvo 142E          21.4   4 121.0 109 4.11 2.78 18.6  1  1    4    2

#待整合/折叠的数据对象为mtcars
#根据气缸数cyl和档位gear折叠数据对象mtcars,两个变量组成列表
#对数据框mtcars中的其他数值型变量取均值(mean),na.rm表示删除空值
aggdata <- aggregate(mtcars, by=list(cyl,gear), FUN=mean, na.rm=TRUE)

#查看经过折叠之后的数据
aggdata
  Group.1 Group.2  mpg cyl disp  hp drat   wt qsec  vs   am gear carb
1       4       3 21.5   4  120  97 3.70 2.46 20.0 1.0 0.00    3 1.00
2       6       3 19.8   6  242 108 2.92 3.34 19.8 1.0 0.00    3 1.00
3       8       3 15.1   8  358 194 3.12 4.10 17.1 0.0 0.00    3 3.08
4       4       4 26.9   4  103  76 4.11 2.38 19.6 1.0 0.75    4 1.50
5       6       4 19.8   6  164 116 3.91 3.09 17.7 0.5 0.50    4 4.00
6       4       5 28.2   4  108 102 4.10 1.83 16.8 0.5 1.00    5 2.00
7       6       5 19.7   6  145 175 3.62 2.77 15.5 0.0 1.00    5 6.00
8       8       5 15.4   8  326 300 3.88 3.37 14.6 0.0 1.00    5 6.00

结果中,Group.1表示气缸数cyl(4、6、8),Group.2表示档位gear(3、4、5),第一行观测数据就是拥有4个气缸和3个档位的车型的mpg(每加仑汽油行驶英里数)均值为21.5。

*注1:使用函数aggregate()时,by后面必须是一个列表,即使只有一个变量。

*注2:可以列表中自定义变量名称,如下所示

aggdata_Group <- aggregate(mtcars, 
    by=list(cyl_Group=cyl, gear_Group=gear), 
    FUN=mean, na.rm=TRUE)

aggdata_Group
  cyl_Group gear_Group  mpg cyl disp  hp drat   wt qsec  vs   am gear carb
1         4          3 21.5   4  120  97 3.70 2.46 20.0 1.0 0.00    3 1.00
2         6          3 19.8   6  242 108 2.92 3.34 19.8 1.0 0.00    3 1.00
3         8          3 15.1   8  358 194 3.12 4.10 17.1 0.0 0.00    3 3.08
4         4          4 26.9   4  103  76 4.11 2.38 19.6 1.0 0.75    4 1.50
5         6          4 19.8   6  164 116 3.91 3.09 17.7 0.5 0.50    4 4.00
6         4          5 28.2   4  108 102 4.10 1.83 16.8 0.5 1.00    5 2.00
7         6          5 19.7   6  145 175 3.62 2.77 15.5 0.0 1.00    5 6.00
8         8          5 15.4   8  326 300 3.88 3.37 14.6 0.0 1.00    5 6.00

*注3:指定的函数FUN可以是任意(包括内建或自编)函数。

三、reshape包或reshape2包

reshape包或reshape2包是一套重构和整合数据集的“绝妙工具”,并且reshape2更强大(使用前需要先下载这两个包)。数据的重构和整合分为融合(melt)和重铸(cast)两个过程。

  • 融合:给每个观测值加上唯一的标识符,使每一行都是一个唯一的标识符和变量的组合
  • 重铸:对数据运用“任何函数”进行整合,将数据集变成任何需要的形状

接下来的代码,将处理下图的样例数据

上图的数据中,每一行的值组合在一起成为唯一标识符,后两列X1和X2称为测量(measurement)。比如,根据ID为1、Time为1以及属于变量X1,可以确定测量值为第一行中的5。

1、融合

融合可以让数据集的每个测量变量(即上图中最后两列X1和X2的全部8个值)独占一行,行中必须带有唯一确定该测量的标识符变量(即上图中的ID和Time)。

library(reshape2)
md <- melt(mydata, id=c("ID", "Time"))

运行代码后,可以得到融合之后的数据结构

*注:代码中只需要指定唯一确定每个测量的标识符变量(ID和Time)即可,而测量变量的名称可由程序自动创建。

拥有了融合之后的数据,就可以进行重铸了。

2、重铸

使用函数cast()读取融合之后的数据,函数调用格式如下:

#md是融合之后的数据
#formula表示想要的结果
#FUN表示数据整合函数,是可选参数,
newdata <- cast(md, formula, FUN)

formula的形式如下:

rowvar1 + rowvar2 + ... + ~ colvar1 + colvar2 + ...

rowvar1+rowvar2+…定义了要去掉的变量集合,以确定各行的内容;colvar1+colvar2+…定义了要去掉的变量集合,以确定各列的内容。具体请看下图的例子:

上图中右边三张小图的公式中没有指定某个整合函数FUN,所以数据仅被重塑了,并没有进行整合;而左边三张小图的公式中指定了函数mean作为整合函数,因此对数据同时进行了重塑和整合。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31537575/viewspace-3146315/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2018-05-16

  • 博文量
    4259
  • 访问量
    40013