R - 具有多个条件的重复项列表

时间:2014-10-15 11:31:06

标签: r duplicates

我有一个如下数据数据框:

Data <- data.frame(
    'id' = sample(1:30, 100, replace=T),
    'first_name' = sample(c("John", "Alex", "Ben"), 100, replace =T),
    'last_name' = sample(c("Bailey", "Smith", "Jones"), 100, replace =T),
    'country' = sample(c("United Kingdom", "United States", "Canada"), 100, replace =T)
)

所以我知道我可以使用下面的方法来获取重复的first_names:

Data[duplicated(Data$first_name),]

但是,如何获得不同ID 的重复记录列表相同的名字,同一个昨晚和同一个国家

所以理想的结果如下:

country          id          first_name          last_name
United Kingdom   1            John                 Smith
United Kingdom   2            John                 Smith
United States    10           Alex                 Jones
United States    12           Alex                 Jones

5 个答案:

答案 0 :(得分:3)

以下是使用data.table的替代方法:

ans = unique(setDT(Data))
ans = ans[, list(id=id[.N > 1L]), by = list(first_name, last_name, country)]
setorder(ans, id)

首先,我们只得到整个data.table上的唯一行。

然后我们按照first_namelast_namecountry列进行分组,并仅保留id在该群组中多次出现的行。

最后,我们使用函数setorder按列ID重新排序ans


setorder通过引用重新排序data.table 的行。它类似于base的顺序函数,但由于a)基数排序/排序而快得多)和2)就地修改对象(没有副本)。

对于熟悉setkey的data.table用户,并问问题为什么不是setkey:在这种情况下,两者之间的结果是相同的。但setkey升序排序总是,而会设置其他属性sorted。这里的目标是重新排序行,而不是设置密钥(连接的要求)。因此,函数setorder在这里更有意义。

setorder也可以按升序和降序重新排序(尽管这里不相关)。

答案 1 :(得分:2)

可能有帮助:

Data <- unique(Data)
nm1 <- setdiff(names(Data), "id")
res <- do.call(rbind, 
         lapply(split(Data, as.character(interaction(Data[, nm1]))),function(x) {
                     x[duplicated(x[, nm1]) | duplicated(x[, nm1], fromLast = TRUE), ]
            }))

row.names(res) <- NULL

答案 2 :(得分:2)

我愿意:

dup <- subset(unique(Data),
              ave(id, country, first_name, last_name, FUN = length) > 1L)

其中unique删除相同的人(相同的ID /国家/第一/最后),ave计算共享国家/第一/最后一个人的数量。

然后,您可能会发现对数据进行排序以使重复项彼此相邻非常有用:

dup <- dup[with(dup, order(country, first_name, last_name, id)), ]

答案 3 :(得分:1)

dplyr可能性:

library(dplyr)
Data %>% 
  group_by(first_name, last_name, country) %>%
  mutate(n = n()) %>%
  filter(n > 1) %>%
  arrange(country, id)

答案 4 :(得分:0)

尝试:

> data.table(with(Data, table(id, paste(first_name, last_name, country))))[N>0][,.SD[.N>1],by=V1]
                            V1 id N
 1:         Alex Bailey Canada  2 2
 2:         Alex Bailey Canada 26 1
 3: Alex Bailey United Kingdom  7 1
 4: Alex Bailey United Kingdom  8 1
 5: Alex Bailey United Kingdom 16 1
 6: Alex Bailey United Kingdom 29 1
...