通过多个OR语句加入R

时间:2019-05-13 11:22:03

标签: r dplyr

我有两个数据帧-testidx-我的目标是使用merge()或类似的函数进行条件连接。

例如,test的ID具有多个可能的键(有些还包含NA值)。您不会为两个单独的ids找到相同的键,这些键将始终是唯一的。

> test
   id keyA keyB keyC
1 foo   NA    2   10
2 bar    1   NA    6
3 baz    7   NA    4
4  li    8    3   NA
5 qux    9   NA   NA

我的目标是加入idx,其中密钥匹配,例如:

> idx
  key value
1   2    NA
2  10    NA
3   7    NA
4   4    NA
5   9    NA

联接应输出:

> idx
  key value
1   2   foo
2  10   foo
3   7   bar
4   4   bar
5   9   quz

我了解如何在一个或多个列上使用merge,但不确定在涉及OR语句时如何使用它(在这种情况下,匹配项将在keyA或keyB或keyC)

在R中如何执行此联接?

数据:

dput(test)
structure(list(id = c("foo", "bar", "baz", "li", "qux"), keyA = c(NA, 
1, 7, 8, 9), keyB = c(2, NA, NA, 3, NA), keyC = c(10, 6, 4, NA, 
NA)), row.names = c(NA, -5L), class = "data.frame")

dput(idx)
structure(list(key = c(2, 10, 7, 4, 9), value = c(NA, NA, NA, 
NA, NA)), row.names = c(NA, -5L), class = "data.frame")

4 个答案:

答案 0 :(得分:2)

我们可以gather test转换为长格式,然后left_join

library(dplyr)
library(tidyr)

idx %>%
  left_join(test %>%
             gather(key, value, -id, na.rm = TRUE), by = c("key" = "value")) %>%
   select(key, id)

#  key  id
#1   2 foo
#2  10 foo
#3   7 baz
#4   4 baz
#5   9 qux

或者就像@David Arenburg提到的那样使用data.table

library(data.table)
melt(setDT(test), "id")[setDT(idx), on = .(value = key), .(key, id)]

答案 1 :(得分:2)

我不知道这是否是您要寻找的解决方案,但是您可以使用reshape2包中的melt函数通过融合测试data.frame来实现。

test <- structure(list(id = c("foo", "bar", "baz", "li", "qux"), keyA = c(NA, 
1, 7, 8, 9), keyB = c(2, NA, NA, 3, NA), keyC = c(10, 6, 4, NA, 
NA)), row.names = c(NA, -5L), class = "data.frame")

library(reshape2)
melted_test <- melt(test)

melted_test
Using id as id variables
    id variable value
1  foo     keyA    NA
2  bar     keyA     1
3  baz     keyA     7
4   li     keyA     8
5  qux     keyA     9
6  foo     keyB     2
7  bar     keyB    NA
8  baz     keyB    NA
9   li     keyB     3
10 qux     keyB    NA
11 foo     keyC    10
12 bar     keyC     6
13 baz     keyC     4
14  li     keyC    NA
15 qux     keyC    NA

然后,您只需要将idx和melted_test合并一次,并只保留所需的列即可。

答案 2 :(得分:2)

一种dplyr解决方案可以是先到达left_join,然后到达coalesce

library(dplyr)

test <- data.frame(id = c("foo", "bar", "baz", "li", "qux"), keyA = c(NA, 1, 7, 8, 9), keyB = c(2, NA, NA, 3, NA), keyC = c(10, 6, 4, NA, NA))

idx <- data.frame(key = c(2, 10, 7, 4, 9), value = c(NA, NA, NA, NA, NA))

idx <- left_join(idx, test[,c("keyA", "id")], by = c("key" = "keyA")) %>%
  left_join(test[,c("keyB", "id")], by = c("key" = "keyB")) %>%
  left_join(test[,c("keyC", "id")], by = c("key" = "keyC")) %>%
  mutate(value = coalesce(id.x,id.y,id)) %>%
  select(key, value)

答案 3 :(得分:1)

另一种方法:

library(tidyverse)

nest(test, -id) %>%
  rowwise() %>%
  mutate(key = list(idx$key[idx$key %in% data])) %>%
  unnest(key, .drop = T) %>%
  select(key, value = 'id')

# # A tibble: 5 x 2
# key value
#   <int> <chr>
# 1     2 foo  
# 2    10 foo  
# 3     7 baz  
# 4     4 baz  
# 5     9 qux