在R中查找数据框中基于两列的重复行。

56

我在R中有一个数据框,它看起来像这样:

| RIC    | Date                | Open   |
|--------|---------------------|--------|
| S1A.PA | 2011-06-30 20:00:00 | 23.7   |
| ABC.PA | 2011-07-03 20:00:00 | 24.31  |
| EFG.PA | 2011-07-04 20:00:00 | 24.495 |
| S1A.PA | 2011-07-05 20:00:00 | 24.23  |

我想知道是否存在关于RIC和日期组合的重复项。在R中有没有相应的函数?

7个回答

81

你可以尝试将这两列直接传递给duplicated函数:

duplicated(dat[,1:2])
假设你的数据框被称为dat。要获取更多信息,可以在控制台键入?duplicated,以查看duplicated函数的帮助文件。这将提供以下句子:
确定向量或数据框中哪些元素是具有较小下标的元素的重复项,并返回一个逻辑向量,指示哪些元素(行)是重复的。
因此,duplicated返回一个逻辑向量,我们可以使用它来提取dat的子集:
ind <- duplicated(dat[,1:2])
dat[ind,]

或者你可以跳过单独的分配步骤,直接使用:

dat[duplicated(dat[,1:2]),]

如何检索重复的行?我不知道重复函数的结果是如何索引的。 - user802231
@user802231 - 经过编辑以回答您的进一步问题。 - joran
1
我尝试了,但结果似乎不正确。我得到的如下所示:(每行前面的数字是行名) RIC 日期107515 7541.T 2011-06-30 20:00:00 107516 7541.T 2011-07-03 20:00:00 107517 7541.T 2011-07-04 20:00:00 107518 7541.T 2011-07-05 20:00:00 107519 7541.T 2011-07-06 20:00:00 107520 7541.T 2011-07-07 20:00:00 107521 7541.T 2011-07-10 20:00:00 107522 7541.T 2011-07-11 20:00:00 107523 7541.T 2011-07-12 20:00:00 107524 7541.T 2011-07-13 20:00:00 107525 7541.T 2011-07-14 20:00:00 107526 7541.T 2011-07-18 20:00:00 - user802231
@user802231 有什么问题吗? - joran
小心使用这个解决方案!!它只会针对列1和2的完全相同组合返回TRUE,而不是如果数字被倒置。换句话说:如果列1和列2的值分别为A,B,则只有当存在另一个A,B时才会将其标记为重复项,但如果存在B,A则不会。 - rvrvrv

28

dplyr对这种事情做起来要舒服得多:

library(dplyr)
yourDataFrame %>%
    distinct(RIC, Date, .keep_all = TRUE)

( ".keep_all是可选的。如果不使用它,它将仅返回经过去重的2列。当使用它时,它将返回整个经过去重的数据框)


2
如果您只想知道是否存在重复值,您会如何处理? - erocoar
7
虽然这是一种通用的有用技巧,但它并没有回答原帖发布者提出的问题,即如何识别重复观测。 - shrgm

22

这里有一个 dplyr 的选项,可以基于两个(或更多)列标记重复项。在本例中,是根据 ricdate 列进行标记:

df <- data_frame(ric = c('S1A.PA', 'ABC.PA', 'EFG.PA', 'S1A.PA', 'ABC.PA', 'EFG.PA'),
                 date = c('2011-06-30 20:00:00', '2011-07-03 20:00:00', '2011-07-04 20:00:00', '2011-07-05 20:00:00', '2011-07-03 20:00:00', '2011-07-04 20:00:00'),
                 open = c(23.7, 24.31, 24.495, 24.23, 24.31, 24.495))

df %>% 
  group_by(ric, date) %>% 
  mutate(dupe = n()>1)
# A tibble: 6 x 4
# Groups:   ric, date [4]
  ric    date                 open dupe 
  <chr>  <chr>               <dbl> <lgl>
1 S1A.PA 2011-06-30 20:00:00  23.7 FALSE
2 ABC.PA 2011-07-03 20:00:00  24.3 TRUE 
3 EFG.PA 2011-07-04 20:00:00  24.5 TRUE 
4 S1A.PA 2011-07-05 20:00:00  24.2 FALSE
5 ABC.PA 2011-07-03 20:00:00  24.3 TRUE 
6 EFG.PA 2011-07-04 20:00:00  24.5 TRUE 

10
使用 dplyr 是获取所需信息的简便方法。
library(dplyr)

yourDF %>% 
  group_by(RIC, Date) %>% 
  mutate(num_dups = n(), 
         dup_id = row_number()) %>% 
  ungroup() %>% 
  mutate(is_duplicated = dup_id > 1)
# A tibble: 6 × 6
  RIC    Date                 open num_dups dup_id is_duplicated
  <chr>  <chr>               <dbl>    <int>  <int> <lgl>        
1 S1A.PA 2011-06-30 20:00:00  23.7        1      1 FALSE        
2 ABC.PA 2011-07-03 20:00:00  24.3        2      1 FALSE        
3 EFG.PA 2011-07-04 20:00:00  24.5        2      1 FALSE        
4 S1A.PA 2011-07-05 20:00:00  24.2        1      1 FALSE        
5 ABC.PA 2011-07-03 20:00:00  24.3        2      2 TRUE         
6 EFG.PA 2011-07-04 20:00:00  24.5        2      2 TRUE  

使用这个:
- `num_dups` 告诉你这个特定组合重复了多少次 - `dup_id` 告诉你这个特定行是第几个重复的(例如第一、第二或第三等) - `is_duplicated` 提供了一个简单的条件,你可以在以后过滤掉所有重复的行(例如 `filter(!is_duplicated)`),不过你也可以使用 `dup_id`(例如 `filter(dup_id == 1)`)

4
如果您想根据数据框中的DateState列的值删除重复记录,请使用以下方法:dataset
#Indexes of the duplicate rows that will be removed: 
duplicate_indexes <- which(duplicated(dataset[c('Date', 'State')]),) 
duplicate_indexes 

#new_uniq will contain unique dataset without the duplicates. 
new_uniq <- dataset[!duplicated(dataset[c('Date', 'State')]),] 
View(new_uniq) 

2

我觉得你需要的是一种方法,能够以与原始数据相同的格式返回重复行的数据框。也许有更优雅的方法,但这个方法有效:

dup <- data.frame(as.numeric(duplicated(df$var))) #creates df with binary var for duplicated rows
colnames(dup) <- c("dup") #renames column for simplicity
df2 <- cbind(df, dup) #bind to original df
df3 <- subset(df2, dup == 1) #subsets df using binary var for duplicated`

0
发现了一个非常精妙的想法由Steve Lianouglou发布,它能够很好地解决这个问题,并且具有索引重复项的巨大优势:
如果您生成一个'散列'列,将要检查重复项的两个列连接起来,那么您可以使用dplyr::n()和seq将每个重复出现的位置标记为索引,如下所示。
dat %>% mutate(hash = str_c(RIC, Date)) %>%
  group_by(hash) %>% 
  mutate(duplication_id = seq(n()) %>%
 ungroup ()

你的列duplication_id告诉你在索引之上的表中有多少个相同的行(两列具有相同的行值)。我使用这个来删除重复的Id。


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