【问题标题】:Joining/matching data frames in R在 R 中加入/匹配数据帧
【发布时间】:2018-11-15 09:46:48
【问题描述】:

我有两个数据框。

第一列有两列:x 是水深,y 是每个深度的温度。

第二个也有两列,x 也是水深,但与第一个表中的深度不同。第二列z 是盐度。

我想通过x 加入这两个表,方法是将z 添加到第一个表中。我已经学会了如何在 tidyr 中使用“键”来连接表,但这只有在键相同的情况下才有效。这两个表中的x 不一样。

我要做的是将表2中的深度x与表1中的深度匹配在10%以内(即匹配表2中的1.1x到表1中的1.0x)。

我该怎么做?

Table 1
| x | y  |
|---|----|
| 1 | 25 |
| 2 | 26 |
| 3 | 27 |

Table 2
| x    | z  |
|------|----|
| 1.1  | 30 |
| 2.05 | 35 |
| 3.8  | 34 |

我想要

Table 1
| x | y  | z  |
|---|----|----|
| 1 | 25 | 30 |
| 2 | 26 | 35 |
| 3 | 27 | NA |

前两个“x”值在 Table 2 中匹配(绝对差在 10% 以内)。第三个没有。

【问题讨论】:

  • 你见过fuzzyjoin 包吗?
  • 刚刚检查过。似乎是对的。谢谢!有这么多包要跟进!
  • @JianghuiDu 我认为fuzzyjoin 在这种情况下对你没有多大帮助。最好提供一个可重现的示例,以便提供适当的解决方案。
  • 我已经添加了示例。

标签: r join left-join fuzzy-comparison


【解决方案1】:

提供数据后编辑:

从@MKR 的帖子中获取数据定义:

library(fuzzyjoin)
fuzzy_left_join(Table_1, Table_2,match_fun = function(x,y)  y> x & y<=1.1*x )
# Joining by: "x"
#   x.x  y  x.y  z
# 1   1 25 1.10 30
# 2   2 26 2.05 35
# 3   3 27   NA NA

假数据的一般解释(第一个答案)

虚假数据

iris1 <- head(iris[1:2])
iris1
#   Sepal.Length Sepal.Width
# 1          5.1         3.5
# 2          4.9         3.0
# 3          4.7         3.2
# 4          4.6         3.1
# 5          5.0         3.6
# 6          5.4         3.9

iris2 <- head(iris[c(1,3)])
set.seed(1)

# add noise
iris2$Sepal.Length <- iris2$Sepal.Length + rnorm(6,sd=0.05)

# shuffle rows
iris2 <- iris2[sample(seq(nrow(iris2))),]

iris2
#   Sepal.Length Petal.Length
# 5     5.016475          1.4
# 2     4.909182          1.4
# 4     4.679764          1.5
# 6     5.358977          1.7
# 3     4.658219          1.3
# 1     5.068677          1.4

代码

library(fuzzyjoin)
fuzzy_left_join(iris1,iris2,match_fun= function(x,y) y>0.99*x & y<1.01*x )
# Joining by: "Sepal.Length"
# Sepal.Length.x Sepal.Width Sepal.Length.y Petal.Length
# 1            5.1         3.5       5.068677          1.4
# 2            4.9         3.0       4.909182          1.4
# 3            4.7         3.2       4.679764          1.5
# 4            4.7         3.2       4.658219          1.3
# 5            4.6         3.1             NA           NA
# 6            5.0         3.6       5.016475          1.4
# 7            5.4         3.9       5.358977          1.7

我们看到一些行匹配得非常好,让我们看看异常。第 4 行在iris2 中添加了太多噪音,因此它与第 3 行配对,第 3 行有 2 个匹配项。当我选择左连接时,仍然显示第 4 行,但 NAs 用于 iris2 的列。

据我了解:

  • 连接列将被扩展
  • 该函数将这些长列(此处为6*6==36 元素)作为参数
  • 我们应用向量化函数(例如 &lt;&amp; 在这种情况下)返回一个逻辑向量,该向量将过滤这些长列以构建输出 data.frame

distance_left_join 使用起来更直接,但它是绝对距离,而不是相对距离。

【讨论】:

  • 太棒了!那行得通!另一个相关的问题。如果我有多个键,例如 key1、key2、key3,该怎么办。我想完全匹配 key1 和 key2,但只在特定约束下匹配 key3 ?
  • 第一个请注意,我编辑了我的答案,认为输出没有改变,我使用 multi_match_fun 错误
  • match_fun 可以是函数列表,您应该明确提及 by 参数以确保安全,然后您可以提供将应用于每对的函数列表
  • 如果您只提供一个,它将用于所有对
【解决方案2】:

使用sqldf 的选项可以实现为:

library(sqldf)


sqldf("select T1.x, T1.y, A.z from Table_1 T1
left join (select Table_1.x, Table_1.y, Table_2.z from Table_1 
   left join Table_2 where round((100*abs(Table_1.x - Table_2.x)/Table_1.x),0) <= 10) A 
on T1.x = A.x")

#   x  y  z
# 1 1 25 30
# 2 2 26 35
# 3 3 27 NA

数据:

Table_1 <- read.table(text = 
"x  y  
1   25  
2   26  
3   27",
header = TRUE)


Table_2 <- read.table(text = 
"x  z  
1.1    30  
2.05   35  
3.8    34",
header = TRUE)

【讨论】:

  • 也许你应该解释一下它背后的逻辑,它不是很清楚,特别是因为 OP 有一些规则
  • 我认为你误会了我的意图。我根据x 的相对距离将Table 2 加入Table 1,而不仅仅是按顺序匹配它们。或者我很困惑,你是如何以及在哪里输入匹配标准的?
  • 我同意。我在理解问题时犯了一个错误。我正在纠正它。
  • 谢谢!很高兴尝试所有这些。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-15
  • 1970-01-01
  • 2012-08-20
  • 2018-12-25
  • 2018-02-07
  • 2021-09-15
相关资源
最近更新 更多