Объединяется в R с несколькими операторами OR - PullRequest
3 голосов
/ 13 мая 2019

У меня есть два кадра данных - test и idx - моя цель - использовать merge() или аналогичную функцию для создания условного соединения.

Например, test имеет идентификаторы с несколькими возможными ключами (и значениями 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 ]

2 голосов
/ 13 мая 2019

Я не знаю, является ли это решение, которое вы ищете, но вы можете сделать это, растопив тестовый файл data.frame, используя функцию melt из пакета reshape2.

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 голосов
/ 13 мая 2019

A 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)
2 голосов
/ 13 мая 2019

Мы можем 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 голос
/ 13 мая 2019

Еще один способ сделать это:

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 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...