我有以下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
)应被视为无可比拟的(或以上所有都在同一组中)。
答案 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)
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