эффективный поиск данных из одного data.frame в другом data.frame по группам - PullRequest
0 голосов
/ 03 декабря 2018

Я ищу более быстрое решение для следующей проблемы.

Предположим, у меня есть следующие два набора данных.

df1 <- data.frame(Var1 = c(5011, 2484, 4031, 1143, 7412),
              Var2 = c(2161, 2161, 2161, 2161, 8595))
df2 <- data.frame(team=c("A","A", "B", "B", "B", "C", "C", "D", "D"),
              class=c("5011", "2161", "2484", "4031", "1143", "2161", "5011", "8595", "1143"),
              attribute=c("X1", "X2", "X1", "Z1", "Z2", "Y1", "X1", "Z1", "X2"),
              stringsAsFactors=FALSE)


> df1
  Var1 Var2
1 5011 2161
2 2484 2161
3 4031 2161
4 1143 2161
5 7412 8595

> df2
  team class attribute
1    A  5011        X1
2    A  2161        X2
3    B  2484        X1
4    B  4031        Z1
5    B  1143        Z2
6    C  2161        Y1
7    C  5011        X1
8    D  8595        Z1
9    D  1143        X2

Я хотел бы знать, какие команды в df2 встречаются в class, что соответствует строкам в df1.Меня не интересует порядок строк со строками.

Мой текущий код (вставленный ниже) работает, но безнадежно неэффективен.

Некоторые правила:

  • только команды A и C встречаются в классах, которые встречаются как строки в df1.
  • , команда B и команда D не встречаются вклассы, для которых любая парная комбинация образует строку в df1.Они исключаются из выходных данных.

Код:

    teams <- c()
    atts <- c()
    pxs <- unique(df2$team)

    for(j in pxs){
     subs <- subset(df2, team==j)
     for(i in 1:nrow(df1)){
      if(all(df1[i,] %in% subs$class)){
    teams <- rbind(teams, subs$team[i])
    atts <- rbind(atts, subs$attribute)
     } 
     }
    }

    output <- cbind(teams, atts)  

> output
     [,1] [,2] [,3]
[1,] "A"  "X1" "X2"
[2,] "C"  "Y1" "X1"

Исходные данные состоят из миллионов строк как df1, так и df2.

Как сделать это эффективнее?Возможно, с помощью подхода apply в сочетании с data.table?

1 Ответ

0 голосов
/ 05 декабря 2018

Не совсем уверен, что ваши правила пытаются достичь.

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

library(data.table)
setDT(df1)
setDT(df2)[, cls := as.integer(cls)]

#left join df1 with df2 using Var1
v1 <- df2[df1, on=.(cls=Var1)]

#left join df1 with df2 using Var2
v2 <- df2[df1, on=.(cls=Var2)]

#inner join the 2 previous results to ensure that the same team is picked 
#where classes already match in v1 and v2
v1[v2, on=.(team, cls=Var1, Var2=cls), nomatch=0L]

output:

   team  cls attribute Var2 i.attribute
1:    A 5011        X1 2161          X2
2:    C 5011        X1 2161          Y1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...