根据匹配列删除df中的重复行

时间:2016-09-28 18:03:27

标签: r dataframe duplicates

我的dflink列(类型列表),用于指定记录是否在df内匹配(即,如果它有重复项)。

df <- data.frame(id=1:7,link=I(list(c(2,3),c(1,3),c(1,2),NA,NA,7,6)))

  id link
1  1 2, 3
2  2 1, 3
3  3 1, 2
4  4   NA
5  5   NA
6  6    7
7  7    6

我想将df子集仅保留具有链接记录的那些行的第一个匹配行(即,相对于id的顺序)。我想要:

  id link
1  1 2, 3
2  4   NA
3  5   NA
4  6    7

我尝试过循环来存储要从id df中移除的行的to_remove值。它现在不太有效,我觉得我正在过度思考这个问题。

to_remove <- character(0)
for (n in 1:nrow(df)) {
  links <- df$link[[n]]
  if (all(is.na(links))) next # skip if no links available
  add <- ifelse(links %in% to_remove, NA,links)
  add <- add[!is.na(add)]
  if (length(add > 0)) to_remove <- c(to_remove,add)
}

我能以更简单的方式做到这一点并避免循环吗?

3 个答案:

答案 0 :(得分:5)

使用:

library(data.table)
DT <- data.table(id = rep(df$id, lengths(df$link)), link = unlist(df$link))
DT[DT[, .I[!any(id > link) | is.na(link)], by = id]$V1][, .(link = toString(link)), by = id]

给出:

   id link
1:  1 2, 3
2:  4   NA
3:  5   NA
4:  6    7

解释

  • 首先通过取消列出df$link单元格中的列表来创建新的data.frame / data.table并创建一个新的data.frame / data.table。
  • 然后创建一个满足条件的索引并选择此子集。
  • 最后,将链接列中的值转换回每个ID的列表。

或使用dplyr / tidyr组合:

library(dplyr)
library(tidyr)
df %>% 
  unnest(link) %>% 
  group_by(id) %>% 
  filter(!any(id > link) | is.na(link)) %>% 
  summarise(link = toString(link))

给出了类似的结果:

# A tibble: 4 × 2
     id  link
  <int> <chr>
1     1  2, 3
2     4    NA
3     5    NA
4     6     7

或使用基础R:

dfn <- data.frame(id = rep(df$id, lengths(df$link)), link = unlist(df$link))
dfn <- dfn[!dfn$id %in% unique(dfn$id[which(dfn$id > dfn$link)]),]
aggregate(link ~ id, dfn, toString, na.action = na.pass)

答案 1 :(得分:1)

由于删除行x取决于所有行link的{​​{1}}值,因此矢量化很难。我建议循环遍历所有行并保存冗余行的(布尔)索引。你正在考虑的只是你的实施有点摇摇晃晃。

1:x-1

答案 2 :(得分:1)

如果通过

  

第一个匹配的行

你的意思是关于id的订单,那么以下内容应该有效:

library(dplyr)
library(tidyr)
result <- df %>% unnest(link) %>% 
                 filter(is.na(link) | link > id & !duplicated(link)) %>%
                 group_by(id) %>% 
                 nest(link, .key=link)
print(result)
### A tibble: 4 x 3
##     id             link
##  <int>           <list>
##1     1 <tibble [2 x 1]>
##2     4 <tibble [1 x 1]>
##3     5 <tibble [1 x 1]>
##4     6 <tibble [1 x 1]>
print(result$link)
##[[1]]
### A tibble: 2 x 1
##   link
##  <dbl>
##1     2
##2     3
##
##[[2]]
### A tibble: 1 x 1
##   link
##  <dbl>
##1    NA
##
##[[3]]
### A tibble: 1 x 1
##   link
##  <dbl>
##1    NA
##
##[[4]]
### A tibble: 1 x 1
##   link
##  <dbl>
##1     7

注意:

  1. 首先unnest,以便link位于不同的行中(对于相同的id
  2. is.na(link)保留所有没有链接的行
  3. link > id将保留link大于id的行。当匹配顺序为id时,这将保持第一个匹配,因为链接的行将大于id。
  4. !duplicated(link)将删除链接中的重复项。
  5. 然后,nest