dataframe第二列 r语言_R语言笔记(五):数据转换(dplyr)

89e736c3ebe2155425359272f78d3a01.png

数据处理主要内容包括:

  • 1. 特殊值处理
    • 1.1 缺失值
    • 1.2 离群值
    • 1.3 日期
  • 2. 数据转换(base vs. dplyr)
    • 2.1 筛选(subset vs. filter/select/rename)
    • 2.2 排序(order vs. arrange)
    • 2.3 转换(transform vs. mutate/transmute)
    • 2.4 分组与概括(group_by/summarise)
  • 3. 数据框重塑(base vs. dplyr)
    • 3.1 数据框的合并(rbind/cbind vs. bind_rows/bind_cols)
    • 3.2 数据框的关联(merge vs. *_ join)
    • 3.3 数据框的长宽转换(reshape2 包)

本文我们学习数据转换的有关内容,笔记(四)相关链接:

Sub-woo:R语言笔记(四):数据处理(上)​zhuanlan.zhihu.com
2bc9353efc83c5420cacbc55132dcd2d.png
Sub-woo:R语言笔记(四):数据处理(下)​zhuanlan.zhihu.com
88004a27efd08bbf12145842769e89cc.png

有出错或补充的地方请大神们不吝赐教,作者会持续更新!


2. 数据转换

在这一部分我们会分别介绍 R 语言在处理数据转换时会用到的 base 包与 dplyr 包中的函数。

2.1 筛选(subset/filter/select)

  • R 语言基本包(base)中用于筛选数据子集的函数是 subset() 。
subset(x, subset, select, drop = FALSE, ...)
x:向量(vector),矩阵(matrix)或数据框(dataframe)
subset:目标行符合的条件
select:目标列的序数

举几个例子:

set.seed(100)
x <- sample(0:50, 10)
y <- matrix(sample(0:50, 12), nrow = 3, ncol = 4)
z <- data.frame(a = sample(0:50, 5), b = sample(0:50, 5))
x
# [1]  9 37 47 24 13 43 22 21  5  3
y
#      [,1] [,2] [,3] [,4]
# [1,]    5   48   11   45
# [2,]   33   42   34   24
# [3,]    6   17    7    1
z
#    a  b
# 1 50 20
# 2  3 26
# 3 49 38
# 4 47 15
# 5 31 10

subset(x, x >= 25) # 返回 x 中大于 25 的元素
# [1] 37 47 43
subset(y, y[, 2] >= 25 & y[, 3] <= 25, select = c(1, 3))
# 筛选出 y 的第二列大于 25 且第三列小于 25 的行(即第一行),并返回目标行的第 1 和第 3 列数据
#      [,1] [,2]
# [1,]    5   11
subset(z, a <= 25 | b <= 25, select = a)
# 筛选出 a 列小于 25 或 b 列小于 25 的行(第 1,2,4,5 行),并返回目标行的 a 列数据
#    a
# 1 50
# 2  3
# 4 47
# 5 31
  • dplyr 包中用于筛选数据子集的函数有 filter(), slice(), select() 。
filter(.data, ...)
slice(.data, ...)
select(.data, ...)
rename(.data, ...)

四种函数都只用于 dataframe 结构的筛选,其中 filter() 与 slice() 用于筛选行,其中 filter() 多根据条件进行筛选,slice() 多根据行序数进行筛选;select() 与 rename() 用于筛选列,我们来看看 R 给出的 example。

【注】filter() 函数用法与 subset() 用法基本相似,区别在于 subset() 可以处理向量和矩阵,并且能够通过 select 参数直接筛选列,因此我们接下来主要介绍其他三种函数。

首先是 slice() 函数,用法比较简单,主要根据行序数进行筛选。

library(dplyr)
slice(z, 1:3) # 返回 z 的第 1 到第 3 行数据
#    a  b
# 1 50 20
# 2  3 26
# 3 49 38
slice(z, n()) # 返回 z 的最后一行数据
#    a  b
# 1 31 10
slice(z, 3: n()) # 返回 z 的第 3 行到最后一行数据
#    a  b
# 1 49 38
# 2 47 15
# 3 31 10

select() 函数用法较多,但都十分简单,作者直接将 dplyr 包的 examples 复制过来了=。=

另附参考资料:【R语言】必学包之dplyr包

iris <- as_tibble(iris) # so it prints a little nicer
select(iris, starts_with("Petal"))
# 返回列名以 "Petal" 开头的列
select(iris, ends_with("Width"))
# 返回列名以 "Width" 结尾的列

select(iris, contains("etal"))
# 返回变量名包含 "etal" 的列
select(iris, -contains("etal"))
# 返回变量名不包含 "etal" 的列

select(iris, Species, everything())
# 将 Species 变量作为第一列,并返回所有列
select(iris, -Sepal.Length, Sepal.Length)
# 将 Sepal.Length 变量作为最后一列,并返回所有列

df <- as.data.frame(matrix(runif(100), nrow = 10))
df <- tbl_df(df[c(3, 4, 7, 1, 9, 8, 5, 2, 6, 10)])
# 将各个列重新排序为 V3, V4, V7, ...
select(df, V4: V6)
# 返回第 V4 到第 V6 列(分别为第 4,7,1,9,8,5,2,6 列)

select(iris, -starts_with("Petal"))
# 返回不含以 "Petal" 开头的列(删除以 "Petal" 开头的列)
starwars %>% group_by(gender) %>% select(group_cols())

select(mtcars, mtcars$cyl)
# 返回 mtcars 数据集中名为 cyl 的列
select(mtcars, mtcars$mpg : mtcars$disp)
# 返回名为 mpg 到名为 disp 的列

vars <- c("Sepal.Length", "Sepal.Width")
select(iris, one_of(vars))
# 对于筛选字符串中的列名对应的列,需要使用 one_of()

rename() 函数主要为变量重命名,select() 也可以实现,区别在于 rename() 会返回所有列。

select(iris, petal_length = Petal.Length)
# 返回 Petal.Length 变量并重命名为 petal_length
rename(iris, petal_length = Petal.Length)
# 返回所有列,并将 Petal.Length 重命名为 petal_length

select(iris, obs = starts_with("S"))
# 返回以 "S" 开头的列,并重命名为 obs
# 当列数大于 1 时,重命名自动调整为 obs1, obs2, ...

2.2 排序(order/arrange)

根据变量名对变量进行排序,可以通过:手动进行排序;使用基本包中的 order() 排序;使用 dplyr 包中的 arrange() 排序。

order(..., na.last = TRUE, decreasing = FALSE,
      method = c("auto", "shell", "radix"))
# 只能对向量进行排序,返回的是排序的索引值
# na.last 为 TRUE,排序时将 NA 放在最末;为 FALSE,放在第一位;为 NA,则移除
# decreasing 为 TRUE,降序排序;否则升序排序

arrange(.data, 变量1, desc(变量2))
# 只能对数据框进行操作
# 变量1升序,变量2降序联合排序

以 iris 数据集为例:

dat <- iris
names(dat) # 获取原始数据的变量名排序
# [1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width"  "Species"
dat_manual <- dat[, c(3, 4, 1, 2, 5)]
# 观察后进行手动调整

order(names(dat)) # 升序返回索引值
# [1] 3 4 1 2 5
dat_order <- dat[, order(names(dat))]
# 使用 order() 对变量名进行升序排列
dat_order <- dat[, order(names(dat), decreasing = T)]
# 使用 order() 对变量名进行降序排列
dat_order <- dat[order(dat$Petal.Width, dat$Petal.Length), ]
# 使用 order() 对 Petal.Width 和 Petal.Length 联合升序排序

library(dplyr)
dat_arrange <- arrange(dat, dat$Petal.Width, dat$Petal.Length)
# 使用 arrange() 对 Petal.Width 和 Petal.Length 联合升序排序
dat_arrange <- arrange(dat, dat$Petal.Width, desc(dat$Petal.Length))
# 使用 arrange() 对 Petal.Width 升序,对 Petal.Length 降序联合排序

2.3 转换(transform/mutate/transmute)

基本包中的 transform() 函数可以为数据框添加新的变量,也可以对已有的变量进行编辑/删除。dplyr 包提供了两个添加新变量的函数,mutate() 和 transmute() 。

transform(.data, new_variable = NULL, ...)
mutate(.data, new_variable = NULL, ...)
transmute(.data, new_variable = NULL, ...)

三者区别在于,mutate() 在 transform() 能添加新变量的基础上,可以同时使用刚添加的变量再创建其他变量;mutate() 返回添加新变量后的新数据框,而 transmute() 仅返回新创建的变量。接下来我们来看看它们是如何实现变量编辑的:

set.seed(100)
z <- data.frame(a = sample(0:50, 3), b = sample(0:50, 3))
z
#    a  b
# 1  9 50
# 2 37 24
# 3 47 13

z2 <- z
z2[, 3] <- z2[, 1] + z2[, 2]
# 手动创建新变量
z2[, 2] <- NULL
# 手动删除变量 b

transform(z, c = a + b) # 创建新变量 c
#    a  b  c
# 1  9 50 59
# 2 37 24 61
# 3 47 13 60
transform(z, b = NULL) # 删除变量 b
#    a
# 1  9
# 2 37
# 3 47
# transform(z, c = a + b, d = c + 1) 会报错因为对新变量的引用需要另外书写代码

mutate(z, c = a + b, d = c + 1) # 不会报错,mutate() 的优点
#    a  b  c  d
# 1  9 50 59 60
# 2 37 24 61 62
# 3 47 13 60 61

transmute(z, c = a + b, d = c + 1) # 只返回新变量
#    c  d
# 1 59 60
# 2 61 62
# 3 60 61

2.4 分组与概括(group_by/summarise)

group_by() 和 summarise() 都是 dplyr 包中的函数,处理对象都是数据框结构。

group_by(.data, add = FALSE, .drop = TRUE)
# 当 add = FALSE 时,再使用 group_by() 函数分组会覆盖原分组效果;add = TRUE,则会再原有分组基础上再分组
# 当 .drop = TRUE 时,分组后的空集会被移除;否则使用 group_by_drop_default(.tbl) 函数对空组填补缺失值

summarise(.data, ...)
# 使用指定的函数获取数据框的数值特征,返回一维向量

实际工作中,group_by() 常常配合其他函数使用,因此,接下来我们先来举例介绍 summarise() 用法和效果,再结合 group_by() 函数看看差异。

library(dplyr)
dat <- mtcars
summarise(dat, quantile(disp, 0.25)) # 返回四分之一分位数
#   quantile(disp, 0.25) n()
# 1              120.825  32
summarise(dat, Q1 = quantile(disp, 0.25), ME = median(disp), Q3 = quantile(disp, 0.75))
#        Q1    ME  Q3
# 1 120.825 196.3 326
# 可以返回多个数值特征,并且自定义变量名

接下来结合 group_by() :

dat <- group_by(dat, cyl)
summarise(dat, Q1 = quantile(disp, 0.25), ME = median(disp), Q3 = quantile(disp, 0.75))
#     cyl    Q1    ME    Q3
#   <dbl> <dbl> <dbl> <dbl>
# 1     4  78.8  108   121.
# 2     6 160    168.  196.
# 3     8 302.   350.  390 

cyl 变量表示的是气缸个数,取值为 4, 6 和 8,因此对该变量进行分类便将 dat 分为三个 group。再对其使用 summarise() 会对三个 group 分别计算其四分之一分位数、中位数、四分之三分位数。我们再试试对两个变量分组的效果:

dat <- group_by(dat, cyl, gear, add = TRUE)
summarise(dat, Q1 = quantile(disp, 0.25), ME = median(disp), Q3 = quantile(disp, 0.75))
#     cyl  gear    Q1    ME    Q3
#   <dbl> <dbl> <dbl> <dbl> <dbl>
# 1     4     3 120.  120.   120.
# 2     4     4  78.0  93.5  126.
# 3     4     5 101.  108.   114 
# 4     6     3 233.  242.   250.
# 5     6     4 160   164.   168.
# 6     6     5 145   145    145 
# 7     8     3 297.  355    410 
# 8     8     5 314.  326    338.

gear 表示的是 forward gears(前齿轮?)个数,取值为 3, 4 和 5;cyl 有三个取值,因此对两个变量进行分组,应该会有 3×3 = 9 个 group,但实际只有 8 个,是因为对八个气缸的车型没有 4 个 forward gears,该组为空集,不填补缺失值就会被 drop 掉。分组后再使用 summarise() 的结果十分清晰,cyl 作为第一分组依据,gear 作为第二分组依据,分别对各组计算四分之一数、中位数和四分之三分位数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值