数据分析中的"国道"—连接

 No one konws everything, and you don't have to.”   --free傻孩子
"R数据分析"专题·第2篇
  编辑 | free傻孩子
  4445字 | 7分钟阅读
本期推送内容:
本期为大家推荐的是dplyr中常用的功能—连接。连接包括两类:合并连接和筛选连接。若上一期(“用R为数据分析插上翅膀”)推荐的五个函数是数据分析中的“翅膀”,那么本期推荐的几个函数则是连接不同数据的“国道”。这些函数包括:inner_join, left_join, right_join, full_join and semi_join。前四个为合并连接,最后一个则为筛选连接。
01

前沿介绍

有时候我们需要/关注的数据不是在一个数据表格中,而是在不同的表格中。例如在高通量测序数据分析时经常是OTU测序的reads在一个表格,而分类信息在另一个表格;或者我们已知道了经纬度数据,但是需要的年平均温度、年降雨量等数据在WorldClim数据库中。此时如何根据已有的样方名、经纬度等“键”信息找到需要的数据呢?

熟悉excel的朋友们大概对VLOOKUP函数不陌生,该函数就能够实现部分类似于连接的功能。但是VLOOKUP无法处理更大的数据,也没办法直接处理存在两个“键”以上情况的数据。

什么是“键”?键就是连接两个数据的关键列,如"样方"所在的列,如"经度" 和“纬度”等。由此可见键的特点一般是unique的,所以判断某一列是否能作为键,首先需要判断的是该列是否在不同表格中均存在,其次是判断该列是否unique。

02

内连接—inner_join

该函数的作用是通过“键”,保留两个表格中共有的部分。
代码如下:
1)先构建两个数据框:df1 和 df2
library(tidyverse)
# if you have not installed this packages,
#you can use the following code :" install.packages("tidyverse") "

df1 <- tibble(
  names = paste0("Sample", 1:12),
  A = (2:13),
  B = rnorm(12),
  C = A*2,
  lat = c(10,20,30,40,50,60,70,80,90,100,110,120),
  long = c(-5,0,5,10,15,20,25,30,35,40,45,50)
)
df2 <- tibble(
  names = paste0("Sample", 1:6),
  group1 = rep(c("treat1","treat2"),each= 3),
  lat = c(20,40,80,90,100,120),
  long = c(0,10,30,35,40,50),
  MAT = c(22,23,25,28,30,35)
)
df2

数据形式如下:

我们的目的是使用df1中的样方名在df2中挑选对应的数据:
代码如下:
df1 %>%
  inner_join(df2, by = "names")

结果如下:

由以上数据可见:内连接是通过“键”(也就是数据中的names)保留两个数据df1和df2中共同存在的部分。
03

外连接—左,右和全连接

有时候我们并不是找两个表格中共同存在的部分,而是在表格中找到对应“键”的其它信息。

这时候我们可能需要用到外连接,外连接包括左连接(left_join),右连接(right_join)和全连接(full_join)。

目的1:在df2找到所有df1的names对应的数据

代码如下:

df1 %>%
  left_join(df2, by = "names")

注意:左连接不会丢弃df1数据中,对应的键在df2中没有数据的部分,而是会通过NA自动补全。

目的2:在df1中找到所有对应df2 的names对应的数据。

代码如下:

df1 %>%
  right_join(df2, by = "names")

注意:相似于左连接,右连接也会自动补齐df2的键(也就是names)在df1数据中不存在的数据。只是本次所使用的数据只是自己随便编辑的数据,df1中包含了所有df2的键所对应的数据。

目的3:找到df1中的经(long)度和纬度(lat)在df2中对应的年平均温度。注意:经纬度和温度均为我随便写的数据。

df1 %>%
  left_join(df2, by = c("lat","long"))

相比于内连接(inner_join)来说,外连接不会造成原来数据信息的丢弃。因此,我更加推荐外连接。

对于全连接(full_join),感兴趣的朋友可以自己试一下,我自己不怎么用。

04

筛选连接

无论是内连接还是外连接,都会保留两个数据中的部分数据,但是有时候我只想根据键,在另一个表格中筛选一些信息,而不想保留键所在的数据框中的其它数据,此时如何做呢?

此时需要用到筛选连接:

目的:在df1数据中,筛选df2的names对应的数据,但是不保留df2已经包含的数据。

df1 %>%
  semi_join(df2, by = "names")
(0)

相关推荐