在每行的列值中搜索重复项/逐行比较列值

时间:2014-08-28 20:03:57

标签: r duplicates dataframe data.table dplyr

我有一个非常大的DF,结构看起来像这样:

route_1 route_2 route_3 route_4 route_grey_1 route_grey_2
A       B       NA      NA      NA           NA
A       B       C       NA      A            NA
A       B       C       D       A            D 
A       B       C       NA      C            NA
B       C       E       F       B            C

但是,A,B,C,D行之间会有所不同。 对于每一行,我试图找到route_grey_1和route_grey_2中未提及的route_1到route_4的两个值。 这将始终是2个值。 (如果route_n中只有两个值,则不会有route_grey_n值,如果route_n中有三个值,则route_grey_n中只有一个值,等等。)

所以上面的输入应该导致这个输出(添加两个新列:

route_1 route_2 route_3 route_4 route_grey_1 route_grey_2  result1 result2 
A       B       NA      NA      NA           NA            A       B  
A       B       C       NA      A            NA            B       C
A       B       C       D       A            D             B       C  
A       B       C       NA      C            NA            A       B
B       C       E       F       B            C             E       F

到目前为止,我想到的唯一解决方案是编写一个函数,遍历所有行并将一个接一个的route_n与route_grey_n进行比较。 首先,我认为可能有更好的解决方案,我希望循环非常慢。其次,我无法使我的循环工作,所以如果你认为这可能是唯一的解决方案,希望有人可以帮助我。

/ e:虽然大卫的答案适用于小型DF,但我的数据需要30分钟才会失败:

Error: cannot allocate vector of size 380 Kb
Error during wrapup: cannot allocate vector of size 438 Kb

我怀疑应该有使用dplyr或data.table包的解决方案。

/ e2:在玩了dplyr后,我设法找到了解决方案。它似乎工作,我的DF需要约30秒。然而,它非常hacky,可能不是一个非常好的。因此,我们非常感谢任何改进。这是我的代码:

df <- df %>% group_by(index) %>%
mutate( c_route1 = !route_1 %in% c(route_grey_1,route_grey_2),
c_route2 = !route_2 %in% c(route_grey_1,route_grey_2),
c_route3 = !route_3 %in% c(route_grey_1,route_grey_2),
c_route4 = !route_4 %in% c(route_grey_1,route_grey_2))

这会在df中创建具有逻辑的列,然后它变得丑陋(可能这部分可以做得更好,很想看到一些替代方案):

df$result1[df$c_route1] <- df$route_1[df$c_route1]
df$result1[!df$c_route1 & df$c_route2 ] <- df$route_2[ !df$c_route1 & df$c_route2 ]
df$result1[!df$c_route1 & !df$c_route2 ] <- df$route_3[ !df$c_route1 & !df$c_route2 ]
df$result2[df$c_route1 ] <- df$route_2[ df$c_route1 ]
df$result2[!df$c_route1 & df$c_route2  ] <- df$route_3[ !df$c_route1 & df$c_route2   ]
df$result2[!df$c_route1 & !df$c_route2  ] <- df$route_4[ !df$c_route1 & !df$c_route2  ]

1 个答案:

答案 0 :(得分:1)

尽管我试图避免apply,但这是我能想到的唯一解决方案

DF[c("result1", "result2")] <- t(apply(DF, 1, function(x) x[1:4][t(!(x[1:4] %in% x[5:6]))]))

#   route_1 route_2 route_3 route_4 route_grey_1 route_grey_2 result1 result2
# 1       A       B    <NA>    <NA>         <NA>         <NA>       A       B
# 2       A       B       C    <NA>            A         <NA>       B       C
# 3       A       B       C       D            A            D       B       C
# 4       A       B       C    <NA>            C         <NA>       A       B
# 5       B       C       E       F            B            C       E       F