在共享的公共列之间分配groupid

时间:2018-12-16 02:45:28

标签: r data.table

我有以下data.frame(实际上是数百万条记录)。

当电话号码与任何其他记录和任何电话号码位置匹配时,我希望能够分配一个组ID。

id <- c(1:5)
phone_1 <- c("444","", "333", "222", "")
phone_2 <- c("", "444", "111", "", "")
phone_3 <- c("222","", "", "", "111")
df <- data.frame(id, phone_1, phone_2, phone_3)

理想的输出如下:

print(df)
#   id phone_1 phone_2 phone_3  ID
# 1  1     444             222  1
# 2  2             444          1
# 3  3     333     111          2
# 4  4     222                  1
# 5  5                     111  2

理想情况下,我想使用data.table方法,因为速度很重要。

请注意,缺失值(""NA)应被视为无可比拟的(或以上所有都在同一组中)。

2 个答案:

答案 0 :(得分:5)

以下是找到图形组件的解决方案:

library(tidyr)
library(dplyr)
library(igraph)

df$id <- paste0("id-", df$id)

graph <- 
  df %>%
  gather(dummy, phone, -id) %>% 
  select(-dummy) %>% 
  filter(!is.na(phone) & phone != "") %>% 
  as.matrix() %>% 
  graph_from_edgelist(directed = FALSE)

plot(graph)

enter image description here

df$ID <- components(graph)$membership[df$id]

df

#     id phone_1 phone_2 phone_3 ID
# 1 id-1     444             222  1
# 2 id-2             444          1
# 3 id-3     333     111          2
# 4 id-4     222                  1
# 5 id-5                     111  2

答案 1 :(得分:2)

如果要使用@Aurèle进行计算,请遵循data.table解决方案:

library(data.table)
library(igraph)

dt <- data.table(id, phone_1, phone_2, phone_3)
graph <- graph_from_edgelist(as.matrix(melt(dt, "id", names(dt)[grepl("phone", names(dt))])
                                       [!is.na(value) & value != ""][, variable := NULL]),
                             directed = FALSE)

dt[, ID := components(graph)$membership[dt[, as.character(id)]]]

#    id phone_1 phone_2 phone_3 ID
# 1:  1     444             222  1
# 2:  2             444          1
# 3:  3     333     111          2
# 4:  4     222                  1
# 5:  5                     111  2