写点什么

R 语言之基本包

作者:timerring
  • 2023-08-24
    山东
  • 本文字数:4540 字

    阅读完需:约 15 分钟

文章和代码已经归档至【Github 仓库:https://github.com/timerring/dive-into-AI 】或者公众号【AIShareLab】回复 R 语言 也可获取。

用 R 基本包

在实际的数据分析中,分析者往往需要花费大量的精力在数据的准备上,将数据转换为分析所需要的形式。遗憾的是,大多数统计学教材很少涉及这一重要问题。整理数据是统计学的任务之一。我们开始关注 R 中最常用的数据格式——数据框的基本操作。我们将首先使用基本包处理数据框。


先加载 epiDisplay 包里的一个小型数据集 Familydata


library(epiDisplay)data("Familydata")
复制代码

1.查看数据框里的内容

如果数据框较小,比如本例(只有 6 个变量,11 条记录),只需输入数据框名即可查看其全部内容,这等价于调用函数 print( ) 显示对象的内容。


# 输入数据框名即可查看其全部内容,这等价于调用函数 print( ) 显示对象的内容。Familydata# 用函数 `head( )` 只显示其前几行head(Familydata)# 用函数 `tail( )` 显示其最后几行tail(Familydata)# 可以加参数指定到底几行tail(Familydata,7) # 显示尾7行
# 列出所有变量名(列名)names(Familydata)
复制代码



另一个可以用来方便地探索数据框结构的函数是 str( )


str(Familydata)
# ==============显示结果=============# 首先给出了对象的类型(这里是数据框“data.frame”)、观测数和变量的个数;'data.frame': 11 obs. of 6 variables:# 接着给出了数据框中每个变量的变量名和类型,以及变量的前几个取值 $ code : chr "K" "J" "A" "I" ... $ age : int 6 16 80 18 69 72 46 42 58 47 ... $ ht : int 120 172 163 158 153 148 160 163 170 155 ... $ wt : int 22 52 71 51 51 60 50 55 67 53 ... $ money: int 5 50 100 200 300 500 500 600 2000 2000 ... # 对于因子型变量还给出了因子的水平; $ sex : Factor w/ 2 levels "F","M": 1 2 2 1 1 1 1 1 2 1 ... # 最后给出了数据框的一些属性: # 数据标签(“datalabel”) - attr(*, "datalabel")= chr "Anthropometric and financial data of a hypothetical family" - # 数据建立时间(“time.stamp”) - attr(*, "time.stamp")= chr "23 Nov 2006 17:15" - attr(*, "formats")= chr [1:6] "%9s" "%8.0g" "%8.0g" "%8.0g" ... - attr(*, "types")= int [1:6] 128 98 105 98 105 108 # 变量标签(“var.labels”) - attr(*, "val.labels")= chr [1:6] "" "" "" "" ... - attr(*, "var.labels")= chr [1:6] "" "Age(yr)" "Ht(cm.)" "Wt(kg.)" ... # 版本号(“version”) - attr(*, "version")= int 7 - attr(*, "label.table")=List of 6 ..$ sex1: Named num [1:2] 1 2 .. ..- attr(*, "names")= chr [1:2] "F" "M" ..$ : NULL ..$ : NULL ..$ : NULL ..$ : NULL ..$ : NULL
复制代码


这些属性可以增强用户对数据集的理解。要想显示数据框属性的全部信息,可以使用 attributes( ) 函数,该函数的输出是一个列表。


attributes(Familydata)# ================== 输出 ======================$names'code''age''ht''wt''money''sex'$row.names1234567891011$class'data.frame'$datalabel'Anthropometric and financial data of a hypothetical family'$time.stamp'23 Nov 2006 17:15'$formats'%9s''%8.0g''%8.0g''%8.0g''%8.0g''%8.0g'$types1289810598105108$val.labels'''''''''''sex1'$var.labels'''Age(yr)''Ht(cm.)''Wt(kg.)''Pocket money(B.)'''$version7$label.table$sex1F1M2[[2]]NULL[[3]]NULL[[4]]NULL[[5]]NULL[[6]]NULL
复制代码


也可以修改和自定义这些属性。例如,从上面的输出可以看到,第一个变量和最后一个变量没有定义标签。现在为这两个变量添加标签:


attr(Familydata, "var.labels")[1] <- "Identification number"attr(Familydata, "var.labels")[6] <- "Gender"attributes(Familydata)$var.labels# 'Identification number''Age(yr)''Ht(cm.)''Wt(kg.)''Pocket money(B.)''Gender'
复制代码


给变量添加标签能帮助我们更好地理解变量的含义。此外,后面用到的 epiDisplay 包里有些函数的输出还能直接使用这些变量标签。

2.选取数据框的子集

与矩阵类似,我们可以用索引下标的方式选取数据框的子集。


# 选择数据框 Familydata 的第 3 列Familydata[, 3]# 也可以使用$变量名的方式Familydata$ht
# 要提取一个以上的变量,可以使用变量的索引号或名字。例如,只显示变量ht、wt 和 sex 的前 3 条记录,可以输入:Familydata[1:3, c(3, 4, 6)]# 等价于Familydata[1:3, c("ht", "wt", "sex")]
复制代码


下标中的索引还可以是一个条件语句。例如,要选择性别为女性的数据,可以输入:


Familydata[Familydata$sex == "F", ] # 注意逗号跟双等号
复制代码


另一种选择数据框的子集的方法是使用 subset( ) 函数。


subset(Familydata, sex == "F")# 若只选择女性中的变量 ht 和 wtsubset(Familydata, sex == "F", select = c(ht, wt))
复制代码


注意,该命令只是选择一个子集来显示,不会对原来的数据框产生任何影响。如果还要进一步使用该子集,需要把它存为一个新的对象。


在机器学习领域,经常需要从数据集里随机抽取一部分样本。例如,我们想把一个大的数据集随机分成两份,其中一份用于构建预测模型,另一份用于验证模型的预测精度。函数 sample( ) 可用于随机抽样,下面的命令从数据框 Familydata 里随机抽取一个大小为 3 的样本:


sample.rows <- sample(1:nrow(Familydata), size = 3, replace = FALSE)sample.rows# 5 4 1
复制代码


函数 sample( ) 中的第一个参数是一个由要从中抽样的元素组成的向量,在这里是从 1 到数据框中的总观测数;第二个参数 size 是要抽取的元素的数量;第三个参数 replace 用于设定是否放回抽样,默认为 FALSE(不放回抽样)。


函数 sample( ) 的返回值可用于选择数据框中的行。由于随机种子数的不同,每次运行得到的结果很可能不一样。

3.将数据框按照某个变量的值排序:order( )

有时我们想将数据框按照某个变量的值的大小进行排序显示,这可以借助函数 order( ) 实现。例如,将数据框 Familydata 以变量 age 的值从小到大显示,可以使用下面的命令:


# ,前表示条件 ,后表示显示的列Familydata[order(Familydata$age), ] # 默认升序# 降序写法Familydata[order(Familydata$age, decreasing = TRUE), ]# 等价于age取反结果Familydata[order(-Familydata$age), ]
复制代码

4.查找和删除重复数据:duplicated( )

原始数据集里经常会有重复的行。如果不是重复测量的数据,数据集的每一行应该是某一个对象的观测,而且数据集里通常有一个用于识别个体的变量(比如 id)。


数据集 Familydata 中的变量 code 就是个体识别号,下面检查该变量有无重复值:


duplicated(Familydata$code)# FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE# 函数 duplicated( ) 的返回值是逻辑值 TRUE 或 FALSE,这里全为 FASLE,表明变量 code 没有重复值。
复制代码


如果数据框的行数较多,逐一查看这些逻辑值会很麻烦。此时,可以将函数 any( ) 作用于函数 duplicated( ) 的输出结果:


any(duplicated(Familydata$code))# FALSE
复制代码


或者使用函数 table( ),还能得到重复值的个数:


table(duplicated(Familydata$code))# FALSE # 11
复制代码

删除重复行

为了阐明怎样删除重复的行,下面建立一个数据框 Familydata1,将原数据框 Familydata 的第 2 行添加在其第 12 行:


Familydata1 <- FamilydataFamilydata1[12, ] <- Familydata[2, ]Familydata1
复制代码


使用函数 which( ) 可以找出变量 code 的重复值所在的行:


which(duplicated(Familydata1$code))
复制代码


然后,删除重复的行:


# 将不重复的新建对象即可unique.code.data <- Familydata1[!duplicated(Familydata1$code), ]unique.code.data
复制代码


identical 查看对象是否完全一样


# 用identical查看两个对象是否完全一样identical(unique.code.data, Familydata)# TRUE
复制代码

5.在数据框中添加和删除变量

在处理数据框时,我们经常需要创建新的变量并把它添加到现有的数据框中。例如,建立一个新的变量 log10money,其值等于变量 money 以 10 为底的对数。最直接地,可以输入:


Familydata$log10money <- log10(Familydata$money)# 或者可以使用 `transform( )` 函数:Familydata <- transform(Familydata, log10money = log10(money))names(Familydata)# 'code''age''ht''wt''money''sex''log10money'
复制代码


与添加变量相反,如果想从数据框中删除一个变量,只需在方括号内下标号的前面添加一个减号。例如:


Familydata[, -7]
复制代码


请注意,该命令只显示所需的子集,对数据框本身不会产生影响。


但是赋一个空值(NULL)给数据框中的变量等同于删除该变量,并且是会永久删除数据框中的变量:


Familydata$log10money <- NULLcolnames(Familydata)
复制代码

6.把数据框添加到搜索路径

在前面查看和使用数据框中的变量时,我们需要在变量名前面加上数据框名和符号 $。这种方式有时候会显得比较烦琐,尤其是数据框和变量的名字都很长的时候。此时,函数 attach( ) 或者函数 with( ) 可以用来简化代码。


函数 attach( ) 可以将数据框添加到搜索路径中。输入以下命令:


attach(Familydata)
复制代码


然后用函数 search( ) 查看搜索路径中的所有对象:


search()#'.GlobalEnv''Familydata''package:epiDisplay''package:nnet''package:MASS''package:survival''package:foreign''package:repr''jupyter:irkernel''package:stats''package:graphics''package:grDevices''package:utils''package:datasets''package:methods''Autoloads''package:base'
复制代码


现在搜索路径中的第二个位置存放了数据框 Familydata。由于数据框已经在搜索路径中了,而变量 age 又在该数据框里,所以现在可以直接使用变量 age 了。


summary(age)#    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. #    6.00   30.00   47.00   45.73   63.50   80.00 
复制代码


把一个数据框放入搜索路径类似于使用函数 library( ) 加载一个包。调入搜索路径的数据框和加载的包都会被自动读入 R,并一直存放在内存中直至它们被移出(detach( ))。


使用函数 attach( ) 虽然会在输入代码时带来一些便利,但同时也会带来一些问题。例如,重复加载数据框可能会最终导致系统资源过度负荷。另外,如果全局环境中或多个数据框中有相同的变量名,容易使用户产生混淆。因此,有些 R 的使用者尽量避免使用函数 attach( ),而使用函数 with( )


datasets 包里的数据集 infert 为例:


with(infert, summary(age))#  Min. 1st Qu.  Median    Mean 3rd Qu.    Max. #  21.00   28.00   31.00   31.50   35.25   44.00 
复制代码


函数 with( ) 的局限性在于,对于多次使用数据框,我们必须重复使用函数 with( )。此外,赋值仅在此函数内部生效,例如:


with(infert, {  m <- mean(age)}  )m # ERROR:object 'm' not found
复制代码


选择哪一种数据处理方式取决于分析者的偏好。例如《R 语言医学数据分析实战》推荐的做法是:


  1. 在开启一个新的分析项目时,首先使用命令 rm(list = ls( )) 从 R 工作环境中清除所有对象;

  2. 在分析过程中用函数 detach( ) 将不再需要使用的数据框从搜索路径中移出;

  3. 不要定义与已经存在于搜索路径中的数据框同名的新对象;

发布于: 刚刚阅读数: 2
用户头像

timerring

关注

公众号【AIShareLab】 2022-07-14 加入

他日若遂凌云志

评论

发布
暂无评论
R语言之基本包_R 语言_timerring_InfoQ写作社区