删除重复条目,同时保留唯一信息

时间:2015-08-29 17:14:15

标签: r duplicates unique

我有一个包含多行的数据集,这是一个联系人详细信息的数据库。有些条目重复多次,但包含不同的信息。例如:

> example
     Title             Name              Email         Phone      
[1,] "Chair"           "Oswald Gruber"   "abc@abc.com" "+33 12345"
[2,] "Respondent"      "Oswald Gruber"   NA            "+44 54321"
[3,] "Comm.mngr"       "Kaspar Villiger" "qwe@rty.com" "+1 123456"
[4,] "Investment mngr" "Markus Urben"    "jkl@jkl.com" NA         
[5,] "Responsible"     "Markus Urben"    "jkl@jkl.com" "+1 33333"

所以我想要的是让每个人只提到一次,但不会丢失信息。因此,如果我在此示例中合并了两个第一行,我想保留电子邮件地址和两个电话号码,但只保留一种标题。

如果有人建议任何解决方案,我将不胜感激。

4 个答案:

答案 0 :(得分:2)

一个data.table解决方案:

library(data.table)
mrg <- function(x) paste(unique(x[!is.na(x)]),collapse=", ")
setDT(example)[,list(Title=head(Title,1), Email=mrg(Email), Phone=mrg(Phone)), by="Name"]

#               Name           Title       Email                Phone
# 1:   Oswald Gruber           Chair abc@abc.com +33 12345, +44 54321
# 2: Kaspar Villiger       Comm.mngr qwe@rty.com            +1 123456
# 3:    Markus Urben Investment mngr jkl@jkl.com             +1 33333

这将返回自然顺序中的第一个标题,这可能是也可能不是您想要的。它还可以正确整合电子邮件并删除NAs。

答案 1 :(得分:1)

假设您的“示例”对象是data.frame(也可以使用矩阵)。 对于那些您希望保留所有信息的列,您可以这样做(未经测试用于编码拼写错误):

result <- aggregate(example[,c("Phone","Email")], by = list(Name = example[,"Name"]), FUN = paste, sep = ", ")

因此,电话号码和电子邮件地址将作为字符串元素粘贴到单个列中,值由逗号分隔。 或者,

result <- aggregate(example[,c("Phone","Email")], by = list(Name = example[,"Name"]), FUN = c)

将提供2列,其中包含length =特定Name的条目数的向量列表。

对于要保留一个值的列,您必须指定所需的值。如果它始终是第一个值,那将是

result2 <- aggregate(example[,"title"], by = list(Name = example[,"Name"]), function(x) x[1])

然后你可以

merged <- merge(results, result2)

答案 2 :(得分:1)

您可以按Name进行分组,并将每列转换为列表。

library(dplyr)
dat %>% group_by(Name) %>%
  summarise_each(funs(list)) -> res

所以,看起来像是

data.frame(res)
#              Name                        Title                    Email
# 1 Kaspar Villiger                    Comm.mngr              qwe@rty.com
# 2    Markus Urben Investment mngr, Responsible jkl@jkl.com, jkl@jkl.com
# 3   Oswald Gruber            Chair, Respondent          abc@abc.com, NA
#                  Phone
# 1            +1 123456
# 2         NA, +1 33333
# 3 +33 12345, +44 54321

我不知道您想要进一步修改,但您可以轻松删除NA值/重复项,并选择只保留一个标题,稍微更改一下代码。例如,要删除NA /重复项,可以使用funs(list(unique(na.omit(.))))

答案 3 :(得分:-2)

我将其拆分为关系数据库。这假设名称可以作为识别人的唯一键。

library(dplyr)

test = 
  data_frame(
    Title = c("Chair", "Respondent", "Comm.mngr", "Investment mngr", "Responsible"),
    Name = c("Oswald Gruber", "Oswald Gruber", "Kaspar Villiger", "Markus Urben", "Markus Urben"),
    Email = c("abc@abc.com", NA, "qwe@rty.com", "jkl@jkl.com", "jkl@jkl.com"),
    Phone = c("+33 12345", "+44 54321", "+1 123456", NA, "+1 33333") )

Person__Title = 
  test %>%
  select(Name, Title) %>%
  distinct %>%
  filter(!is.na(Title))

Person__Phone =
  test %>%
  select(Name, Phone) %>%
  distinct %>%
  filter(!is.na(Phone))

Person__Email = 
  test %>%
  select(Name, Email) %>%
  distinct %>%
  filter(!is.na(Email))

Person = 
  test %>%
  select(Name) %>%
  distinct

然后,如果你想将它们合并在一起,你可以做到

make_list = function(vector)
  vector %>%
  unique %>%
  na.omit %>%
  paste(collapse = ", ")

merge = 
  Person %>%
  left_join(Person__Email) %>%
  left_join(Person__Phone) %>%
  left_join(Person__Title) %>%
  group_by(Name) %>%
  summarise_each(funs(make_list))

但我不推荐它。在同一个单元中拥有多条信息违背了良好数据设计的原则。