首页 > 其他分享 >R语言之 dplyr 包

R语言之 dplyr 包

时间:2023-08-25 10:06:50浏览次数:38  
标签:bwt 函数 dplyr birthwt 189 数据 变量 语言

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

这个包以一种统一的规范更高效地处理数据框。dplyr 包里处理数据框的所有函数的第一个参数都是数据框名。

下面以 MASS 包里的 birthwt 数据集为例,介绍 dplyr 包里常用函数的用法。该数据集来自一项关于新生儿低体重危险因素的病例对照研究。首先加载该数据集并查看其相关信息。

library(dplyr)
data(birthwt, package = "MASS")
# ??birthwt

数据集 birthwt 里一共包含 189 个研究对象、10 个变量。其中结果变量 bwt 是新生儿的体重(单位:g),变量 low 是将 bwt 的取值以 2500g 为分点转换成的一个二分类变量。其余 8 个变量均为预测变量,包括孕妇的年龄(age)、种族(race)、吸烟状况(smoke)、高血压史(ht)等。

1.使用 filter( ) 和 slice( ) 筛选行

函数 filter() 可以基于观测值筛选数据框的一个子集。第一个参数是数据框名,第二个参数以及随后的参数是用来筛选数据框的表达式。

例如,筛选数据框里年龄大于 35 岁的对象的所有记录:

filter(birthwt, age > 35)

函数 filter ( ) 里可以用逗号分隔多个条件。使用下面的命令将会选择选择年龄大于 35 岁,并且出生体重小于 2500g 或者大于 4000g 的所有记录,因为记录较多,这里只显示了前 10 行。

head(filter(birthwt, age > 35, bwt < 2500 | bwt > 4000),10)

函数 slice( ) 可以按照行号选择指定的行。例如,下面的命令选择数据集里面的第 2 行到第 5 行。

slice(birthwt, 2:5)

2.使用 arrange( ) 排列行

有时候我们想要将数据框的记录按照某个变量进行排序,函数 arrange() 可以实现这个功能。下面的命令将数据框按照变量 bwt 的值从小到大进行排序后显示:

arrange(birthwt, bwt) # 默认升序

R语言之 dplyr 包_加载

在上面的输出中,第 6 行和第 7 行的变量 bwt 的值都是 1588,在这种情况下如果还想将数据框按照第二个变量排序,只需要在函数 arrange( ) 里加上第二个变量即可。例如,下面的命令将数据框按照变量 bwt 的值从小到大排序,在 bwt 取值相等的情况下再按照第二个变量 age 的值从小到大排序。

arrange(birthwt, bwt, age)

如果想把数据框按照某个变量的值从大到小进行排序,可以借助函数 desc( ) 实现。

arrange(birthwt, desc(bwt))
# 等价于
arrange(birthwt, - bwt)

3. 使用 select( ) 选择列

函数 select( ) 用于选择数据框中的列(变量)。

# 下面的命令选择数据框里面的 bwt、age、race 和 smoke 这 4 个变量组成新的数据框。
select(birthwt, bwt, age, race, smoke)

请注意,MASS 包里有一个同名函数 select( ),如果同时加载了 dplyr 包和 MASS 包,R 会默认使用较后加载的包里的函数。为了避免混淆,我们可以使用符号 :: 特别指明使用某一个包里的函数,例如 dplyr::select( )。之后我们将会对函数 select( ) 作进一步介绍。

4.使用 mutate( ) 添加新变量

函数 mutate( ) 用于在数据框中创建新的变量。下面的命令将数据集 birthwt 里的变量 lwt(单位:lb)乘以系数 0.4536 后生成新的变量 lwt.kg(1lb ≈ 0.4536kg)。

# 当然如果想要用新变量替换原来的变量,只需把新变量命名为原来的变量名:
mutate(birthwt, lwt.kg = lwt*0.4536)

5.使用 summarise( ) 计算统计量

函数 summarise( ) 可以用于计算数据框中某个变量的指定统计量。

例如,计算变量 bwt 的样本均值和样本标准差:

summarise(birthwt, Mean.bwt = mean(bwt), Sd.bwt = sd(bwt))

R语言之 dplyr 包_数据_02

6. 使用 group\_by( ) 拆分数据框

函数 group_by( ) 可以将数据框按照某一个或某几个分类变量拆分成多个数据框。例如:

group_by(birthwt, race)
str(group_by(birthwt, race))

# ============ 输出 =============
grouped_df [189 × 10] (S3: grouped_df/tbl_df/tbl/data.frame)
 $ low  : int [1:189] 0 0 0 0 0 0 0 0 0 0 ...
 $ age  : int [1:189] 19 33 20 21 18 21 22 17 29 26 ...
 $ lwt  : int [1:189] 182 155 105 108 107 124 118 103 123 113 ...
 $ race : int [1:189] 2 3 1 1 1 3 1 3 1 1 ...
 $ smoke: int [1:189] 0 0 1 1 1 0 0 0 1 1 ...
 $ ptl  : int [1:189] 0 0 0 0 0 0 0 0 0 0 ...
 $ ht   : int [1:189] 0 0 0 0 0 0 0 0 0 0 ...
 $ ui   : int [1:189] 1 0 0 1 1 0 0 0 0 0 ...
 $ ftv  : int [1:189] 0 3 1 2 0 0 1 1 1 0 ...
 $ bwt  : int [1:189] 2523 2551 2557 2594 2600 2622 2637 2637 2663 2665 ...
 - attr(*, "groups")= tibble [3 × 2] (S3: tbl_df/tbl/data.frame)
  ..$ race : int [1:3] 1 2 3
  ..$ .rows: list<int> [1:3] 
  .. ..$ : int [1:96] 3 4 5 7 9 10 15 16 18 20 ...
  .. ..$ : int [1:26] 1 17 29 30 31 33 35 41 43 70 ...
  .. ..$ : int [1:67] 2 6 8 11 12 13 14 19 21 24 ...
  .. ..@ ptype: int(0) 
  ..- attr(*, ".drop")= logi TRUE

函数 group\_by( ) 不会改变数据框的外观,而会改变它与其他 dplyr 动词函数的作用方式 。因此,上面的输出结果看上去和原来的数据框没有什么差别,但实质上是不同的。最本质的差别是多了一个分组属性(Groups),即上面的结果包含了 3 个数据框,分别对应于变量 race 的 3 个类别。

你还可能注意到上面输出对象的格式(grouped_df [189 × 10] (S3: grouped_df/tbl_df/tbl/data.frame))。与 R/Rstudio 上不同,notebook 这里把它显示成了 A grouped_df: 189 × 10(而非 # A tibble: 189 x 10),实际它仍然包含 tibble(注意其中的 - attr(*, "groups")= tibble [3 × 2] (S3: tbl_df/tbl/data.frame))。另外,它没有显示 Groups 属性信息,实际应为 # Groups: race [3]

tibble 是 tidyverse 系列包(包括 dplyr 包)提供的一种类似数据框的格式。相对于传统的数据框,tibble 在很多方面具有优势,感兴趣的读者可以参阅函数 tibble( ) 的帮助文档。我们可以用函数 as_tibble( ) 将传统的数据框转换为 tibble,也可以用函数 as.data.frame( ) 将 tibble 转换成传统的数据框。

as_tibble(birthwt)

下面我们将会看到,把函数 group\_by( ) 和 summarise( ) 联合使用能方便地对变量进行分组统计。

7. 使用传递符 %>% 组合多个操作

我们经常需要对一个数据框做一系列的操作,后面一个操作的输入需要用前一个操作的输出结果。

# 第一步把数据框 birthwt 里面的变量 race 转换成因子并给各个水平添加标签,把新的数据框命名为 birthwt1
birthwt1 <- mutate(birthwt, 
                   race = factor(race, labels = c("white", "black", "other")))
# 第二步把数据框 birthwt1 按照变量 race 分组,把分组后的对象命名为 birthwt.group; 
birthwt.group <- group_by(birthwt1, race)
# 第三步对于分组对象 birthwt.group 计算各组中变量 bwt 的平均值。
summarise(birthwt.group, mean(bwt))

R语言之 dplyr 包_加载_03

这种方法的最大缺点是需要为每个中间结果建立一个变量。在很多情况下,比如在上面的示例中,这些中间变量其实是没有什么实际意义的。我们需要给这些中间变量命名,而且这些中间变量会保存在工作空间中占用内存。传递操作符 %>% 将该符号之前的对象传递给符号后面的函数并作为函数的第一个参数值。例如:

c(2, 4, 6, 8) %>% matrix(nrow = 2)

R语言之 dplyr 包_加载_04

因为 dplyr 包里面的函数第一个参数总是数据框,所以这些函数配合传递操作符处理数据框非常方便。下面用传递操作符改写上面的命令:

birthwt %>%
  mutate(race = factor(race, labels = c("white", "black", "other"))) %>%
  group_by(race) %>%
  summarise(mean(bwt))

R语言之 dplyr 包_加载_05

上述代码的重点在于动词函数,而不是函数中的参数。在阅读这一串代码组合时,可以将它们当成一系列的规定动作。

项目实战

epiDisplay 包里的数据集 Planning 来自 20 世纪 80 年代中期泰国的一项计划生育调查研究,请通过其帮助文件查看数据信息并整理该数据集。

library(epiDisplay)
data(Planning)
print(des(Planning))

names(Planning) <- tolower(names(Planning))   # 把变量名变为小写字母
summary(Planning)

table(duplicated(Planning$id))       # 查看是否有重复id;
# FALSE  TRUE 
#   250     1
which(duplicated(Planning$id))       # 找出重复id的行号;把 XXXXXX 替换成正确的代码
#   216
Planning$id # 验证下
Planning$id[216] <- 216  # 修正重复id;

library(dplyr)
Planning <- mutate(
  Planning,
  relig = ifelse(relig == 9, NA, relig),     # 将变量relig中的9变成NA
  ped = ifelse(ped == 0 | ped == 9, NA, ped), # 将变量ped中的0和9变成NA
  income = ifelse(income == 9, NA, income),   # 将变量income中的9变成NA
  am = ifelse(am == 99, NA, am),           # 将变量am中的99变成NA
  reason = ifelse(reason == 9, NA, reason),  # 将变量reason中的9变成NA
  bps = ifelse(bps == 0 | bps == 999, NA, bps), # 将变量bps中的0和999变成NA
  bpd = ifelse(bpd == 0 | bpd == 999, NA, bpd), # 将变量bpd中的0和999变成NA
  wt = ifelse(wt == 0 | wt > 99, NA, wt),    # 将变量wt中的0和大于99的值变成NA
  ht = ifelse(ht == 0 | ht > 300, NA, ht)    # 将变量ht中的0和大于300的值变成NA;
)

标签:bwt,函数,dplyr,birthwt,189,数据,变量,语言
From: https://blog.51cto.com/u_15736437/7226285

相关文章

  • QT实现多语言详细步骤
    1、设置.pro项目配置TRANSLATIONS+=Language_zh_CN.ts\Language_en_CN.tsLanguage_zh_CN代表中文,Language_en_CN代表英文2、设计相关界面,如果要翻译程序中的文本,需要将程序中的文本进行修改Qttr()和qsTr()标记待翻译字符串3、生成相关的.ts文件在项目目录下自动生成相关的.t......
  • Go语言中的切片nil
    这句话是关于Go语言中数据结构的空值检查方法。在Go语言中,有些数据类型(如切片、映射和通道)在其零值状态下并不是nil。对于这些类型,即使你分配了一个新的空结构(例如,一个没有元素的切片),它们的内部指针可能不为nil。举一个例子,当我们声明一个新的空切片时:vars[]ints的零......
  • Go语言数组的使用
    目录1.数组的使用1.1数组的定义方式1:1.2数组的定义方式2:1.3数组的定义方式3:1.4数组的定义方式4:1.5数组的遍历1:1.6数组的遍历2:1.7数组的遍历3:1.8数组的遍历4:1.数组的使用1.1数组的定义方式1:packagemainimport"fmt"funcmain(){ vararr[3]string arr[0]="A......
  • Go语言切片的使用
    目录2.切片的使用2.1切片的定义方式1:2.2切片的定义方式2:2.3切片的定义方式3:2.4切片的定义方式4:2.5切片的定义方式5:2.6切片的定义方式6:遍历方式和数组差不多2.切片的使用2.1切片的定义方式1:packagemainimport"fmt"funcmain(){ varslice[]string slice=appe......
  • Go语言字典(map)的使用
    目录3.字典(map)的使用3.1字典的初始化方式1:3.2字典的初始化方式2:3.3字典的初始化方式3:3.4字典的遍历1:3.5字典的遍历2:3.6判断字典中有无某个key3.7删除字典中的某个键值对3.字典(map)的使用3.1字典的初始化方式1:packagemainimport"fmt"funcmain(){ varscoreM......
  • Go语言数字字面量
    在Go语言中,数字字面量可以用以下方式表示:二进制(Binary):使用0b或0B前缀。例如:b:=0b1010//10indecimal注意:这是在Go1.13及更高版本中引入的。八进制(Octal):使用0前缀。例如:o:=0644//420indecimal,oftenusedforfilepermissions十进......
  • C语言经典100题之循环嵌套
    1,有 1、2、3、4 四个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?思路分析:首先来分析这道题目,三位数,无非就是i,j,k的三种不同组合,互不相同翻译成C语言就是i!=j,i!=k,j!=k。无重复我们可以使用枚举法枚举所有的三位数,然后判断是否满足互不相同的条件即可,利用三重循环......
  • 5.13 汇编语言:仿写For循环语句
    循环语句(for)是计算机编程中的一种基本控制结构,它允许程序按照指定的次数或范围重复执行一段代码块。for循环在处理需要进行迭代操作的情况下非常有用,它使得程序可以更加方便地控制循环的次数。一般来说,for循环由三个部分组成:初始化部分、条件表达式和更新部分,以及一个需要重复执行......
  • 5.14 汇编语言:仿写Switch选择结构
    选择结构,也称为switch语句,是计算机编程中的一种控制结构,用于根据表达式的值选择不同的执行路径。它允许程序根据表达式的值来决定执行哪个代码块,从而实现多分支选择逻辑。switch语句由一个表达式、多个case标签以及对应的代码块组成。程序会将表达式的值与每个case标签进行匹配,一......
  • Rust语言学习再理解
    利用ChatGPT辅助学习,对初学者懂其晦涩语法很方便usestd::iter::IntoIterator;structMyStruct{data:Vec<u32>}implMyStruct{//Thishasthesamenameas`std::iter::FromIterator::from_iter`fnfrom_iter(iter:implIntoIterator<Item=u32>)->Self......