Самостоятельное присоединение в R - PullRequest
1 голос
/ 22 сентября 2019

Вот пример тиббла:

test <- tibble(a = c("dd1","dd2","dd3","dd4","dd5"), 
               name = c("a", "b", "c", "d", "e"), 
               b = c("dd3","dd4","dd1","dd5","dd2"))

И я хочу добавить новый столбец b_name в качестве самостоятельного соединения для тестирования с использованием:

dplyr::inner_join(test, test, by = c("a" = "b"))

Моя таблица слишком большая(2,7 млн ​​строк с 4 столбцами), и я получаю следующую ошибку:

Ошибка: std :: bad_alloc

Посоветуйте, пожалуйста, как это сделать правильно / передовой опыт.

Моя конечная цель - получить следующую структуру:

   a     name  b     b_name
   dd1   a     dd3   c
   dd2   b     dd4   d
   dd3   c     dd1   a
   dd4   d     dd5   e
   dd5   e     dd2   b 

Ответы [ 3 ]

1 голос
/ 22 сентября 2019

Вот еще одно простое решение с использованием функции match из base и mutate из dplyr пакета:

library(dplyr)

new_test <- test %>% 
  mutate(b_name = name[match(test$b,test$a)])

Однако будьте осторожны с очень длинными таблицами, так как match может небыть лучшей реализацией.

1 голос
/ 22 сентября 2019

Другой вариант - fmatch из fastmatch

library(fastmatch)
test$b_name <- with(test, name[fmatch(b, a)])
test$b_name
#[1] "c" "d" "a" "e" "b"

Согласно ?fmatch описанию

fmatch - более быстрая версия встроенногоФункция match ().

1 голос
/ 22 сентября 2019

Для этого количества строк, я думаю, data.table, вероятно, даст вам гораздо большую скорость.Итак, вот решение data.table:

library(data.table)
setDT(test)

Подход № 1: самостоятельное соединение:

test[test, on = c(a = "b")]
# test[test, on = .(a == b)] ## identical

Подход № 2: использование data.table :: merge:

merge(test, test, by.x = "a", by.y = "b")
...