2016-06-22 3 views
0

из одной таблицы данных (давайте вызов А) содержит идентификационные номера:Эффективно соединения двух таблиц данных с условием

ID 
3 
5 
12 
8 
... 

и другую таблицу (назовем его B) содержит нижнюю границу и верхнюю границу и имя для этого идентификатора.

ID_lower ID_upper  Name 
1   4   James 
5   7   Arthur 
8   11  Jacob 
12   13  Sarah 

так на основе таблицы B, учитывая ID из таблицы А, мы можем найти совпадающее имя, находя имя на строке в таблице В, что

ID_lower <= ID <= ID upper 

и я хочу создать таблица ID и имя, так что в приведенном выше примере, было бы

ID   Name 
3   James 
5   Arthur 
12   Sarah 
8   Jacob 
...   ... 

я использовал для цикла, так что для каждой строки а, я искать строки в B таким образом, что идентификатор между ID_lower и ID_upper для этой строки и присоединился к имени оттуда. Однако этот метод был немного медленным. Есть ли быстрый способ сделать это в R?

ответ

1

Вы можете сделать справочную таблицу с вашей второй data.frame (B):

lu <- do.call(rbind, 
       apply(B,1,function(x) 
        data.frame(ID=c(x[1]:x[2]),Name=x[3], row.names = NULL))) 

тогда вы запрашиваете его с первого data.frame (A):

A$Name <- lu[A$ID,"Name"] 
1

Вы можете попробовать это data.table решение:

data.table::setDT(B)[, .(Name, ID = Map(`:`, ID_lower, ID_upper))] 
        [, .(ID = unlist(ID)), .(Name)][ID %in% A$ID] 

    Name ID 
1: James 3 
2: Arthur 5 
3: Sarah 12 
4: Jacob 8 
+0

Psidom, вы можете быть заинтересованы в более прямом решении с использованием не следу присоединяюсь я только что отправил. Приветствия. – Arun

+1

@Arun Я ищу это все это утро. Но, похоже, это не помогает. Спасибо за демонстрацию и ссылку. – Psidom

1

Я считаю findInterval() на ID_lower может быть идеальным подходом здесь:

A[,Name:=B[findInterval(ID,ID_lower),Name]]; 
A; 
## ID Name 
## 1: 3 James 
## 2: 5 Arthur 
## 3: 12 Sarah 
## 4: 8 Jacob 

Это будет правильно, только если (1) B отсортирован по ID_lower и (2) все значения в A$ID покрыты диапазонами в B.

2

Используя новый non-equi присоединяется к функции в текущей разрабатываемой версии data.table, это просто:

require(data.table) # v1.9.7+ 
dt2[dt1, .(ID, Name), on=.(ID_lower <= ID, ID_upper >= ID)] 

Смотрите инструкции по установке для разви версии here.


где

dt1=fread('ID 
      3 
      5 
      12 
      8') 
dt2 = fread('ID_lower ID_upper  Name 
        1   4  James 
        5   7 Arthur 
        8  11  Jacob 
        12  13  Sarah') 
Смежные вопросы