2016-01-28 3 views
2

У меня есть два кадра данных в RR - Получить Общие столбцы без использования Присоединяется или Объединить

df1 = data.frame(Cust = c(1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4), ItemId = c(1, 2, 3, 4, 2, 3, 2, 5, 1, 2, 5, 6, 2)) 
df2 = data.frame(ItemId1 = c(1, 3, 2, 3, 2, 1, 2, 3, 4, 6, 5, 3, 2, 4), ItemId2 = c(3, 1, 2, 3, 4, 1, 6, 4, 2, 4, 3, 1, 3, 5)) 
> df1 
    Cust ItemId 
1  1  1 
2  1  2 
3  1  3 
4  1  4 
5  2  2 
6  2  3 
7  2  2 
8  2  5 
9  3  1 
10 3  2 
11 3  5 
12 4  6 
13 4  2 

> df2 
    ItemId1 ItemId2 
1  1  3 
2  3  1 
3  2  2 
4  3  3 
5  2  4 
6  1  1 
7  2  6 
8  3  4 
9  4  2 
10  6  4 
11  5  3 
12  3  1 
13  2  3 
14  4  5 

Все, что мне нужно, это следующий вывод, который является менее дорогостоящим, чем присоединяется к/слиянию (потому что в реальное время я имеет дело с миллиардами записей)

> output 
    ItemId1 ItemId2 Cust 
1  1  3 1 
2  3  1 1 
3  2  2 1, 2, 3, 4 
4  3  3 1, 2 
5  2  4 1 
6  1  1 1, 3 
7  2  6 4 
8  3  4 1 
9  4  2 1 
10  6  4 NA 
11  5  3 2 
12  3  1 1 
13  2  3 1, 2 
14  4  5 NA 

Что происходит, если ItemId1, ItemId2 из df2 комбинации присутствует в ItemId из df1 мы должны вернуть Cust значения (даже если они несколько). Если они присутствуют, мы должны вернуть NA.

i.e. Возьмите первый ряд в качестве примера: ItemId1 = 1, ItemId2 = 3. Только Customer = 1 имеет ItemId = c (1,3) в df1. Аналогично следующие строки.

Мы можем сделать это, используя Joins/Merge, которые являются дорогостоящими операциями. Но они приводят к ошибке памяти.

+0

Если вы работаете с миллиардами записей, это ваши данные уже в SQL? 'dplyr' имеет приятные утилиты для взаимодействия между ними. – alistaire

+0

Нет, мои данные находятся в извлеченном csv. –

+0

По-прежнему непонятно, как вы получаете идентификатор клиента в выводе –

ответ

2

Это может занять больше времени, но не займет много памяти. Преобразуйте для петель с использованием применяются, если это возможно:

library(plyr) 
df1 = data.frame(Cust = c(1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4), ItemId = c(1, 2, 3, 4, 2, 3, 2, 5, 1, 2, 5, 6, 2)) 
df2 = data.frame(ItemId1 = c(1, 3, 2, 3, 2, 1, 2, 3, 4, 6, 5, 3, 2, 4), ItemId2 = c(3, 1, 2, 3, 4, 1, 6, 4, 2, 4, 3, 1, 3, 5)) 
temp2 = ddply(df1[,c("Cust","ItemId")], .(Cust), summarize, ItemId = toString(unique(ItemId))) 
temp3 = ddply(df1[,c("ItemId","Cust")], .(ItemId), summarize, Cust = toString(unique(Cust))) 
dfout = cbind(df2[0,],data.frame(Cust = df1[0,1])) 
for(i in 1:nrow(df2)){ 
    a = df2[i,1] 
    b = df2[i,2] 
    if(a == b){ 
     dfout = rbind(dfout,data.frame(ItemId1 = a,ItemId2 = a,Cust = temp3$Cust[temp3$ItemId == a])) 
    }else{ 
     cusli = c() 
     for(j in 1:nrow(temp2)){ 

      if(length(grep(a,temp2$ItemId[j]))>0 & length(grep(b,temp2$ItemId[j]))>0){ 
       cusli = c(cusli,temp2$Cust[j]) 
      } 
     } 
     dfout = rbind(dfout,data.frame(ItemId1 = a,ItemId2 = b,Cust = paste(cusli,collapse = ", "))) 
    } 
} 
dfout$Cust[dfout$Cust == "",] = NA 
+0

Это работает, но непрактично для данных соответствующего размера, даже переведенных на '* apply'. – alistaire