【R语言数据科学】:(九)数据清洗技巧之数据表连接大全

R语言数据分析

  • 🌸个人主页:JoJo的数据分析历险记
  • 📝个人介绍:小编大四统计在读,目前保研到统计学top3高校继续攻读统计研究生
  • 💌如果文章对你有帮助,欢迎关注、点赞、收藏、订阅专栏

本系列主要介绍R语言在数据分析领域的应用包括:
R语言编程基础、R语言可视化、R语言进行数据操作、R语言建模、R语言机器学习算法实现、R语言统计理论方法实现。
本系列会完成下去,请大家多多关注点赞支持,一起学习~
参考资料:
Data Analysis and Prediction Algorithms with R

💮9.数据清洗之表连接

有时候我们要分析的数据可能不是来自一个数据集,此时需要我们对不同表按照某一关键字进行连接
假设我们想探索美国各州的人口规模与选举人票之间的关系。我们的人口规模如下表所示:

library(tidyverse)
library(dslabs)
head(murders)
A data.frame: 6 × 5
stateabbregionpopulationtotal
<chr><chr><fct><dbl><dbl>
1Alabama ALSouth 4779736 135
2Alaska AKWest 710231 19
3Arizona AZWest 6392017 232
4Arkansas ARSouth 2915918 93
5CaliforniaCAWest 372539561257
6Colorado COWest 5029196 65

选票数据如下

head(results_us_election_2016)
A data.frame: 6 × 5
stateelectoral_votesclintontrumpothers
<chr><int><dbl><dbl><dbl>
1California 5561.731.66.7
2Texas 3843.252.24.5
3Florida 2947.849.03.2
4New York 2959.036.54.5
5Illinois 2055.838.85.4
6Pennsylvania2047.948.63.6

直接将这两个表拼接在一起是不对的,因为他们的顺序不一致,因此我们需要考虑按照state连接两个表

🏵️9.1 joins()函数

left()函数是根据某个关键字列来将多个表进行合并。和sql中的语法基本类似,大家如果想了解sql语法可以看我的专栏。
一般的做法是,首先确定一个或多个用于匹配两个表的列,然后返回一个包含组合数据的新表。

下面,我们使用left_join连接两个表,并且去除others的列,并将electoral_votes重命名

tab <- right_join(murders, results_us_election_2016, by = "state") %>%
    select(-others) %>% rename(ev=electoral_votes)
head(tab)
A data.frame: 6 × 8
stateabbregionpopulationtotalevclintontrump
<chr><chr><fct><dbl><dbl><int><dbl><dbl>
1Alabama ALSouth 4779736 135 934.462.1
2Alaska AKWest 710231 19 336.651.3
3Arizona AZWest 6392017 2321145.148.7
4Arkansas ARSouth 2915918 93 633.760.6
5CaliforniaCAWest 3725395612575561.731.6
6Colorado COWest 5029196 65 948.243.3

现在我们成功的将两个表连接在一起了,下面我们简单绘制一下人口和选票之间的关系

tab %>% ggplot(aes(population/10^6, ev, label = abb)) +
  geom_point() +
  geom_text_repel() + 
  scale_x_continuous(trans = "log2") +
  scale_y_continuous(trans = "log2") +
  geom_smooth(method = "lm", se = FALSE)
`geom_smooth()` using formula 'y ~ x'

Warning message:
"ggrepel: 15 unlabeled data points (too many overlaps). Consider increasing max.overlaps"

png

从结果来看,可以看出人口越多,选票越多,平均而言每十万人有2选票,但是在人口较少的州,这个比例稍高

实际上,并不总是一个表中的每一行在另一个表中都有一个匹配的行。因此,我们有不同的连接方法,为例举例说明,
下面我们先创建tab1和tab2

tab_1 <- slice(murders, 1:6) %>% select(state, population)
tab_1
A data.frame: 6 × 2
statepopulation
<chr><dbl>
Alabama 4779736
Alaska 710231
Arizona 6392017
Arkansas 2915918
California37253956
Colorado 5029196
tab_2 <- results_us_election_2016 %>% 
  filter(state%in%c("Alabama", "Alaska", "Arizona", 
                    "California", "Connecticut", "Delaware")) %>% 
  select(state, electoral_votes) %>% rename(ev = electoral_votes)
tab_2
A data.frame: 6 × 2
stateev
<chr><int>
California 55
Arizona 11
Alabama 9
Connecticut 7
Alaska 3
Delaware 3

🌹9.1.1 左连接(left join)

假设我们想要一张像tab_1这样的表格,但将选举人票添加到我们现有州。此时tab_1作为第一个参数。我们指定要使用哪个列与by参数匹配。没能匹配到的会自动返回NA

left_join(tab_1,tab_2,by = 'state') 
A data.frame: 6 × 3
statepopulationev
<chr><dbl><int>
Alabama 4779736 9
Alaska 710231 3
Arizona 639201711
Arkansas 2915918NA
California3725395655
Colorado 5029196NA

可以看出ArkansasColorado的ev没有匹配到,所以返回NA,下面我们将tab_2传入第一个参数

left_join(tab_2,tab_1,by = 'state') 
A data.frame: 6 × 3
stateevpopulation
<chr><int><dbl>
California 5537253956
Arizona 11 6392017
Alabama 9 4779736
Connecticut 7 NA
Alaska 3 710231
Delaware 3 NA

可以看出结果返回了包含了tab_2的所有信息,其中Connecticut和Delaware的population返回NV

🥀9.1.2 右连接(right join)

右连接与左连接相反,返回第二个表的全部信息,匹配连接第一个表,下面我们来看一个案例

tab_2 %>% right_join(tab_1, by = "state")
A data.frame: 6 × 3
stateevpopulation
<chr><int><dbl>
California5537253956
Arizona 11 6392017
Alabama 9 4779736
Alaska 3 710231
Arkansas NA 2915918
Colorado NA 5029196

可以看出结果交换参数位置后使用右连接和直接使用左连接的结果一致。

可以这样理解:

  • 左连接是将第一个表的所有信息保存下来了,同时按照某一列匹配第二个表的信息并整合起来,没有匹配到的返回NA
  • 右连接是将第二个表的所有信息保存下来了,相当于是左连接交换参数

🌺9.1.3 内连接(inner join)

如果我们只希望得到两个表中都包含的信息,我们可以使用内连接,没有匹配到的行将不显示

inner_join(tab_1, tab_2, by = "state")
A data.frame: 4 × 3
statepopulationev
<chr><dbl><int>
Alabama 4779736 9
Alaska 710231 3
Arizona 639201711
California3725395655

🌻9.1.4 全连接(full join)

如果我们希望保留两个表的所有行,并且用NA来填充未匹配到的值,如下所示

full_join(tab_1, tab_2, by = "state")
A data.frame: 8 × 3
statepopulationev
<chr><dbl><int>
Alabama 4779736 9
Alaska 710231 3
Arizona 639201711
Arkansas 2915918NA
California 3725395655
Colorado 5029196NA
Connecticut NA 7
Delaware NA 3

🌼9.1.5 半连接(semi join)

这个方法在mysql中没有涉及到,它具体工作原理是匹配两个表都有的行,然后只显示第一个表的信息。
相当于先做内连接,再把第二个表的信息去除,具体如下:

semi_join(tab_1, tab_2, by = "state")
A data.frame: 4 × 2
statepopulation
<chr><dbl>
Alabama 4779736
Alaska 710231
Arizona 6392017
California37253956

🌷9.1.6 反连接(anti join)

函数anti_join与semi_join相反。它保留第一个表中没有匹配到第二个表中信息的元素,具体如下

anti_join(tab_1, tab_2, by = "state")
A data.frame: 2 × 2
statepopulation
<chr><dbl>
Arkansas2915918
Colorado5029196

img

🌱9.2 binding

另一个连接表的方法是使用binding,和join函数不同,binding函数不通过某个变量匹配,而是直接连接数据框,如果两个数据框纬度不同,则会报错

🌲9.2.1 按列连接

使用bind_cols,可以方便的连接不同列,例如

bind_cols (a=1:3,b=4:6)
A tibble: 3 × 2
ab
<int><int>
14
25
36

注意,有一个R函数cbind具有完全相同的功能。
主要区别是cbind可以创建不同类型的对象,而bind_cols总是生成一个数据框。

bind_cols也可以连接不同的数据框,如下所示

tab_1 <- tab[, 1:3]
tab_2 <- tab[, 4:6]
tab_3 <- tab[, 7:8]
new_tab <- bind_cols(tab_1, tab_2, tab_3)
head(new_tab)
A data.frame: 6 × 8
stateabbregionpopulationtotalevclintontrump
<chr><chr><fct><dbl><dbl><int><dbl><dbl>
1Alabama ALSouth 4779736 135 934.462.1
2Alaska AKWest 710231 19 336.651.3
3Arizona AZWest 6392017 2321145.148.7
4Arkansas ARSouth 2915918 93 633.760.6
5CaliforniaCAWest 3725395612575561.731.6
6Colorado COWest 5029196 65 948.243.3

🌳9.2.2 按行连接

bind_rows()和bind_cols()函数类似,但是是按行连接

tab_1 <- tab[1:2,]
tab_2 <- tab[3:4,]
bind_rows(tab_1, tab_2)
A data.frame: 4 × 8
stateabbregionpopulationtotalevclintontrump
<chr><chr><fct><dbl><dbl><int><dbl><dbl>
Alabama ALSouth4779736135 934.462.1
Alaska AKWest 710231 19 336.651.3
Arizona AZWest 63920172321145.148.7
ArkansasARSouth2915918 93 633.760.6

同样的,R语言基础函数rbin()可以实现类似的功能

🌴9.3 集合运算符

另一组用于连接数据集方法是集合运算符。当运用在向量上面,则实现和它们字面意思一样,例如intersect、union、setdiff和setequal。
则这些函数可以用于数据帧,而不仅仅是向量。

🌵9.3.1 交集(intersect)

intersect(1:10, 6:15)
  1. 6
  2. 7
  3. 8
  4. 9
  5. 10
intersect(c("a","b","c"), c("b","c","d"))
  1. 'b'
  2. 'c'

当我们导入了dyply包,我们可以使用intersect应用在数据框上,其功能也是求交集

tab_1 <- tab[1:5,]
tab_2 <- tab[3:7,]
intersect(tab_1, tab_2)
A data.frame: 3 × 8
stateabbregionpopulationtotalevclintontrump
<chr><chr><fct><dbl><dbl><int><dbl><dbl>
Arizona AZWest 6392017 2321145.148.7
Arkansas ARSouth 2915918 93 633.760.6
CaliforniaCAWest 3725395612575561.731.6

🌾9.3.2 并集(Union)

union(1:10, 6:15)
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
union(c("a","b","c"), c("b","c","d"))
  1. 'a'
  2. 'b'
  3. 'c'
  4. 'd'
tab_1 <- tab[1:5,]
tab_2 <- tab[3:7,]
dplyr::union(tab_1, tab_2) 
A data.frame: 7 × 8
stateabbregionpopulationtotalevclintontrump
<chr><chr><fct><dbl><dbl><int><dbl><dbl>
Alabama ALSouth 4779736 135 934.462.1
Alaska AKWest 710231 19 336.651.3
Arizona AZWest 6392017 2321145.148.7
Arkansas ARSouth 2915918 93 633.760.6
California CAWest 3725395612575561.731.6
Colorado COWest 5029196 65 948.243.3
ConnecticutCTNortheast 3574097 97 754.640.9

🌿9.3.3 差集(setdiff)

返回第一个参数对第二个参数的差集,因此和上面两个方法不同,setdiff不是对称的,具体案例如下

setdiff(1:10, 6:15)


setdiff(6:15, 1:10)
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  1. 11
  2. 12
  3. 13
  4. 14
  5. 15
tab_1 <- tab[1:5,]
tab_2 <- tab[3:7,]
dplyr::setdiff(tab_1, tab_2)
A data.frame: 2 × 8
stateabbregionpopulationtotalevclintontrump
<chr><chr><fct><dbl><dbl><int><dbl><dbl>
AlabamaALSouth4779736135934.462.1
Alaska AKWest 710231 19336.651.3

☘️9.3.4 setequal

setequal判断两个集合是否相等,而不管顺序。例如

setequal(1:5, 1:6)

FALSE

setequal(1:5, 5:1)

TRUE

setequal(tab_1, tab_2)

FALSE

posted @   JOJO数据科学  阅读(313)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示