前言
这篇文章开始介绍一些对tibble数据的一些数据框之间的一些操作,其中包括数据框的直接连接,以特定观测的值进行连接,以及使用一个tibble数据集对另一个tibble的基于某一个观测的筛除,还有对数据的分组汇总的操作。
一、对数据框之间的一些操作
下面我将通过构建一些简单的tibble数据作为示范来介绍一下对tibble数据框之间的一些操作。创建两个数据框,一个为学生身高的数据框,一个为学生体重的数据框,这两个数据框是有交集但是不存在包含关系。
library(tidyverse)
library(dplyr)
#创建两个数据集,这两个数据集为身高体重的数据
h_table <-tibble(name = c("A","B","D"),sex = c(0,1,1),height = c(170,180,190))
w_table <- tibble(name = c("A","B","C"),sex = c(0,1,1),weight = c(50,65,70))
> h_table
# A tibble: 3 × 3
name sex height
<chr> <dbl> <dbl>
1 A 0 170
2 B 1 180
3 D 1 190
> w_table
# A tibble: 3 × 3
name sex weight
<chr> <dbl> <dbl>
1 A 0 50
2 B 1 65
3 C 1 70
1. 对两个数据框之间进行筛除
对两个数据框进行筛除的函数主要是anti_join
函数,使用将通过参数对函数提供两个数据框,并且指定特定的变量,以第一个数据框和指定变量列为基准,剔除两个数据框存在交集的观测(将观测剔除的条件是指定变量存在交集),输出的是第一个数据框当中不是交集的观测。
h_table |>
anti_join(w_table,by = "name")
# 将身高表格当中,与体重表格姓名相同的学生剔除
> h_table |>
+ anti_join(w_table,by = "name")
# A tibble: 1 × 3
name sex height
<chr> <dbl> <dbl>
1 D 1 190
下面以体重表格为基础再次执行anti_join
函数。
w_table |>
anti_join(h_table,by = "name")
# 剔除体重表格中与身高表格中姓名相同的观测
> w_table |>
+ anti_join(h_table,by = "name")
# A tibble: 1 × 3
name sex weight
<chr> <dbl> <dbl>
1 C 1 70
2.对两个数据框进行连接
主要使用的函数为inner_join
函数,该函数也是将传递进去的两个数据框进行以指定变量相连接的操作,最后输出的是连接后的表格。
h_table |>
inner_join(w_table,by = c("name","sex"))
# A tibble: 2 × 4
name sex height weight
<chr> <dbl> <dbl> <dbl>
1 A 0 170 50
2 B 1 180 65
这里输出的是两个表格中在姓名和性别同时具有交集的表格。如果我们在这里只指定一个变量,那么两个表格当中相同的变量将会被加上.x
或者.y
的后缀,来申明该同名的变量来自哪一个数据框。
h_table |>
inner_join(w_table,by = c("name"))
> h_table |>
+ inner_join(w_table,by = c("name"))
# A tibble: 2 × 5
name sex.x height sex.y weight
<chr> <dbl> <dbl> <dbl> <dbl>
1 A 0 170 0 50
2 B 1 180 1 65
3. 直接连接
函数bind_rows
和bind_cols
可以实现对数据集的直接连接。
bind_cols(h_table,w_table)
bind_rows(h_table,w_table)
> bind_cols(h_table,w_table)
New names:
• `name` -> `name...1`
• `sex` -> `sex...2`
• `name` -> `name...4`
• `sex` -> `sex...5`
# A tibble: 3 × 6
name...1 sex...2 height name...4 sex...5 weight
<chr> <dbl> <dbl> <chr> <dbl> <dbl>
1 A 0 170 A 0 50
2 B 1 180 B 1 65
3 D 1 190 C 1 70
> bind_rows(h_table,w_table)
# A tibble: 6 × 4
name sex height weight
<chr> <dbl> <dbl> <dbl>
1 A 0 170 NA
2 B 1 180 NA
3 D 1 190 NA
4 A 0 NA 50
5 B 1 NA 65
6 C 1 NA 70
在这两个函数下是直接将两个数据框连接,里面也有一些参数可以选择。
4.将两个表格的全部进行粘合
我们可以看到无论是anti_join
还是inner_join
我们都没有办法将两张表当中全部的信息表现在一个表内,这个时候要是只使用这两个函数将两个表缝合为一张表,并且确实的值由NA
表示,在数据观测交少,两个表的区别不大的时候可以采用以下的方法。
- 首先使用
inner_join
函数将两个表已经存在的交集合并。- 其次将合并的新表分别和使用
anti_join
函数排除的两张表连接(这个时候要使用mutate
函数生成另外一个表没有的变量,并且使用NA
填充)- 使用
bind_rows
函数将两个表纵向连接。
df_1 <- h_table |>
inner_join(w_table,by = c("name","sex"))#直接连接的表
df_2 <- h_table |>
anti_join(w_table,by = "name")|>
mutate(weight = NA)
df_3 <- w_table |>
anti_join(h_table,by = "name")|>
mutate(height = NA)
to_table <- df_1 |>#将三个表连接
bind_rows(df_2)|>
bind_rows(df_3)
这边在编写的时候也可以使用|>
方法顺着思路下去
to_table <-h_table |>
inner_join(w_table,by = c("name","sex")) |>
bind_rows(
h_table |>
anti_join(w_table,by = "name")|>
mutate(weight = NA)
) |>
bind_rows(
w_table |>
anti_join(h_table,by = "name")|>
mutate(height = NA)
)
to_table
# A tibble: 4 × 4
name sex height weight
<chr> <dbl> <dbl> <dbl>
1 A 0 170 50
2 B 1 180 65
3 D 1 190 NA
4 C 1 NA 70
|>
的熟练使用可以让我们的思路连贯起来。
6. 分组计算
在我们汇总得到总表之后我们也可以是使用group_by
和 summarize
函数进行分类汇总。
to_table |>
group_by(sex) |>
summarize(
avg_height = mean(height,na.rm = T),
avg_weight = mean(weight,na.rm = T)
)
# A tibble: 2 × 3
sex avg_height avg_weight
<dbl> <dbl> <dbl>
1 0 170 50
2 1 185 67.5
7. 后续对数据的补充
假设现在我得到了一张学生班级和学科成绩的数据,我想要从这个表中提取出学生班级的信息并且匹配到我的汇总表当中,这个时候我们可以使用select
将数据提取出来和distinct
函数将信息唯一化,再使用inner_join
函数进行匹配连接。(select
和distinc
函数的使用方法可以参考我另外一篇文章tidyverse包对tibble数据框的基本操作)
class_table <- tibble(
name = c("A","A","B","B","c","C","D","D"),
class = c("01","01","01","01","02","02","02","02"),
subject = c("E","M","E","M","E","M","E","M"),
score = c(100,99,50,80,70,80,70,100)
)
> class_table
# A tibble: 8 × 4
name class subject score
<chr> <chr> <chr> <dbl>
1 A 01 E 100
2 A 01 M 99
3 B 01 E 50
4 B 01 M 80
5 c 02 E 70
6 C 02 M 80
7 D 02 E 70
8 D 02 M 100
下面对该表的信息进行提取,再粘合。
to_table |>
inner_join(
class_table |>
select(name,class)|>
distinct(),
by = "name"
)
# A tibble: 4 × 5
name sex height weight class
<chr> <dbl> <dbl> <dbl> <chr>
1 A 0 170 50 01
2 B 1 180 65 01
3 D 1 190 NA 02
4 C 1 NA 70 02
这样我们就可以已身高体重表为基本往里面添加信息了。
总结
熟练地使用dplyr
可以让我们在重构数据和补充数据上得心应手。在这个例子上我们也可以对成绩汇总,取均值,以性别为分组,或者以班级为分组,也可以使用pivor_long
函数将class_table
拉长。