在只有选定列的数据框中唯一


73

我有一个包含100列以上的数据框,我将通过仅比较两列来查找唯一行。我希望这是一个简单的,但我不能让它有工作uniqueduplicated自己。

在下面,我只想使用id和id2唯一:

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 2012年

1
我不喜欢包含“ x”还是“ y”。我将更新问题。
2012年

Answers:


126

好的,如果选择非重复列中的哪个值都没有关系,这应该很简单:

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通话中,我只是只传递那些dat我不想重复的列。此代码将自动始终选择任何不明确的值中的第一个。(在这种情况下,x。)


@Ferroao,根据此网站,在SQL dofactory.com/sql/select-distinct
3pitt 17-10-18

23

以下是几个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()))可能会提供更多灵活性。你总是可以使用arrange()之前distinct()太。
sbha

@sbha当要分组的列中有平局时,是否有一种方法可以为具有特定列值的行指定首选项?对于问题中的示例,somevalue == x当行在idid2列中重复时,总是返回with 。
罗坎

14

使用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")])返回向量,而不是数据帧,因此您无法参考其row.names
Sashko Lykhenko,

@SashkoLykhenko,您是否错过了最后一个逗号?
加里·冯

我将其复制粘贴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")]

2
这看起来与加里·冯(Gary Feng)的答案相同,只是您不包括somevalue结果。
格雷戈尔·托马斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.