【问题标题】:Create ID for duplicated of different column为不同列的重复创建 ID
【发布时间】:2019-02-04 08:50:40
【问题描述】:

我在这个概念上尝试了很多,

我有一个包含 3 列名称的 data.frame CustnameEmailMobile_no

Custname    Email         Mobile_no
aaa        xyz@gmail.com    987
bbb        xyz@gmail.com    123
ccc        xyz0@gmail.com   987
ddd        abc@gmail.com    123
eee        xyz0@gmail.com   100

实际上这些客户属于同一组,因为手机号码和电子邮件在列中相同,但客户名称不同。

我想创建一个唯一的 ID,他们都具有相同的手机的电子邮件与电子邮件列匹配,并且相同的电子邮件的移动与手机号码列匹配。

我通过使用duplicatedpaste 函数进行了很多尝试。

作为补充说明,我不想要group_by 客户,实际上 987 来自两个不同的客户(aaa 和 CCC),但两个不同的客户有不同的电子邮件 xyz 和 xyz。在这封邮件中 xyz 与客户 eee 匹配,所以 (aaa ccc eee) 都是同一个组,就像 wise email 一样。

感谢您的帮助

【问题讨论】:

  • 当数据不在同一个组中时你能显示吗?不清楚。你需要df1 %>% group_by(Custname) %>% mutate(grp = n_distinct(paste(Email, Mobile_no)))
  • 如果你能分享预期的输出就好了。
  • 你尝试了什么? stackoverflow上有很多这样的问题。
  • @Akun,我不想要 group_by 客户,实际上 987 来自两个不同的客户(aaa 和 CCC)但是两个不同的客户有不同的电子邮件 xyz 和 xyz0 。在这封邮件 xyz0 匹配客户eee,所以(aaa ccc eee)都是同一组。就像明智的电子邮件

标签: python r partitioning


【解决方案1】:

实际上,您的问题是组件的图形分离。在您的情况下,图的顶点是人。根据属性信息,即电子邮件和电话号码,您可以建立边缘关系。

看起来像pasteduplicategroup_by 这样的简单方法无效,因为您可以有相当复杂的路径。正如您所解释的那样,人 D 和人 E 具有完全不同的联系人,实际上他们是通过人 C 连接的,因此应该具有相同的 ID。

或者换句话说,有人在网站上注册了电子邮件A 和移动B。然后他把手机丢了。并在手机C上注册。然后他忘记了密码并使用电子邮件D注册。最后,我们有电子邮件D 和移动C 的人。不知什么原因,他注册了不同的名字。

你可能有更复杂的关系路径。

下面的算法使用igraph 根据您的条件创建的邻接矩阵制作无向图。在它识别出未连接的组件后,将其提取并与初始data.frame 合并。由于您的示例中没有足够的数据,因此使用了模拟。

模拟输入:

   name tel    email
1   AAA 222 F@xy.com
2   BBB 555 C@xy.com
3   CCC 333 E@xy.com
4   DDD 666 D@xy.com
5   EEE 666 A@xy.com
6   FFF 111 F@xy.com
7   GGG 444 B@xy.com
8   HHH 666 A@xy.com
9   III 444 B@xy.com
10  JJJ 333 F@xy.com

代码

library(igraph)
set.seed(123)
n <- 10

# simulation
df <- data.frame(
  name = sapply(1:n, function(i) paste0(rep(LETTERS[i], 3), collapse = "")),
  tel = sample(1:6, n, replace = TRUE) * 111,
  email = paste0(sample(LETTERS[1:6], n, replace = TRUE), "@xy.com")
)

# adjacency matrix preparation
df1 <- expand.grid(df$name, df$name)
names(df1) <- c("name_x", "name_y")

df1 <- merge(df1, df, by.x = "name_x", by.y = "name")
df1 <- merge(df1, df, by.x = "name_y", by.y = "name")
df1$con <- ifelse(with(df1, tel.x == tel.y | email.x == email.y), 1, 0)

stats::reshape(df1[, c(1, 2, 7)], idvar = "name_x", timevar = "con", direction = "wide")
#v.names = , timevar = "numbers", direction = "wide")
library(igraph)


library(reshape2)
m <- dcast(df1[, c(1, 2, 7)], name_y ~ name_x)
rownames(m) <- m[, 1]
m[, 1] <- NULL
m <- as.matrix(m) 
diag(m) <- 0

# graph creation
g1 <- graph_from_adjacency_matrix(m, mode = "undirected")
gcmps <- groups(components(g1))

# groups extraction
ids <- unlist(mapply(function(x, y) paste0(x, "_", y), seq_along(gcmps), gcmps))
df_ids <- as.data.frame(t(sapply(ids, function(x) unlist(strsplit(x, "_")))))
names(df_ids) <- c("id", "name")

# data merging
result <- merge(df, df_ids)
result

输出:

   name tel    email
1   AAA 222 F@xy.com
2   BBB 555 C@xy.com
3   CCC 333 E@xy.com
4   DDD 666 D@xy.com
5   EEE 666 A@xy.com
6   FFF 111 F@xy.com
7   GGG 444 B@xy.com
8   HHH 666 A@xy.com
9   III 444 B@xy.com
10  JJJ 333 F@xy.com

关系图(只取名字的首字母)

【讨论】:

  • 百万感谢 Artem。它非常有用并且工作正常。现在您根据名称匹配创建一个 id,在我的数据集中名称不一样,可能是名称拼写不同。因此,请帮助创建没有名称且具有相同逻辑的 id。我的数据集只有四列,Code,Tele,Email,account number。
  • @Prabhu,我很高兴,实际上您在评论中提出了另一个问题。最好发布一个新问题。我建议你关注How to make a great reproducable example
猜你喜欢
  • 2020-05-25
  • 1970-01-01
  • 1970-01-01
  • 2020-01-19
  • 1970-01-01
  • 2020-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多