仅选定列上的数据框中唯一值

101

我有一个超过100列的数据框,我想通过仅比较其中两列来找到唯一的行。我希望这很容易,但我自己无法使用uniqueduplicated让它正常工作。

在下面的代码中,我只想使用idid2进行去重:

data.frame(id=c(1,1,3),id2=c(1,1,4),somevalue=c("x","y","z"))

id id2 somevalue
1   1         x
1   1         y
3   4         z

我想要获取以下内容之一:

id id2 somevalue
1   1         x
3   4         z

或者:

id id2 somevalue
1   1         y
3   4         z

我不在乎保留哪些唯一的行。


你的期望输出并没有明确定义。你如何选择包含 x 但不包含 y?这个决定需要针对每一行的每一列进行,而你并没有给出任何指示。 - joran
1
我不在意是否包含 'x' 或 'y'。我会更新问题。 - Ina
关于 data.table 的替代方案:在 data.table 中过滤重复/非唯一行 - Henrik
4个回答

146

如果选择非重复列中的任何值都没有关系,那么这应该很容易:

dat <- data.frame(id=c(1,1,3),id2=c(1,1,4),somevalue=c("x","y","z"))
> dat[!duplicated(dat[,c('id','id2')]),]
  id id2 somevalue
1  1   1         x
3  3   4         z

duplicated 函数中,我只传递了那些我不希望重复的列。这段代码将自动选择任何模糊值的第一个。(在本例中是 x。)


根据这个网站,SQL中不可能实现@Ferroao所说的功能。http://www.dofactory.com/sql/select-distinct - 3pitt
如果非重复列中的值很重要,并且我们想保留所有可能的组合,该怎么办? - SteveMcManaman

42

这里有几个dplyr选项,可以基于列id和id2保留非重复行:

library(dplyr)                                        
df %>% distinct(id, id2, .keep_all = TRUE)
df %>% group_by(id, id2) %>% filter(row_number() == 1)
df %>% group_by(id, id2) %>% slice(1)

4
我想没有理由考虑使用“distinct”的替代方案。 - Frank
1
@Frank 如果有日期或其他顺序字段,可以结合另外两个选项进行一些微调,以确保保留最近的观察结果 df %>% group_by(id, id2) %>% filter(date == max(date)) %>% slice(1) 而无需对数据进行排序。filter() 获取最新日期,slice() 确保仅返回一个观察结果(如果存在并列情况)。在其他情况下,类似 df %>% group_by(id, id2) %>% slice(max(row_number())) 的方法可能会提供更多的灵活性。您也可以在 distinct() 之前使用 arrange() - sbha
@sbha 是否有一种方法可以在分组列中出现重复时,指定具有特定列值的行的优先级?在问题示例中,当idid2列中存在重复行时,始终返回具有somevalue == x的行。 - Lorcán
如果非重复列中的值很重要,并且我们想保留所有可能的组合呢? - SteveMcManaman

15

使用unique()

dat <- data.frame(id=c(1,1,3),id2=c(1,1,4),somevalue=c("x","y","z"))    
dat[row.names(unique(dat[,c("id", "id2")])),]

unique(dat[,c("id", "id2")]) returns vector, not dataframe, so you cannot refer to its row.names - Sashko Lykhenko
@SashkoLykhenko,你漏掉了最后一个逗号吗? - Gary Feng
我复制粘贴了这个 row.names(unique(dat[,c("id", "id2")])),但是它返回了错误。最后一个逗号与外部的 dat[...,] 有关。 - Sashko Lykhenko

1

@Joran的代码进行了小更新。
使用下面的代码,您可以避免歧义并仅获取两列的唯一值:

dat <- data.frame(id=c(1,1,3), id2=c(1,1,4) ,somevalue=c("x","y","z"))    
dat[row.names(unique(dat[,c("id", "id2")])), c("id", "id2")]

3
除了你没有包括 somevalue 的结果外,这看起来和 Gary Feng 的答案完全一样。 - Gregor Thomas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接