根据匹配列删除df中的重复行
我的df
有一个link
列(类型列表),指定记录是否在df
(即它是否有重复项)内匹配。根据匹配列删除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)
}
我可以以更简单的方式做到这一点,避免循环?
使用:
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
说明:
- 首先由unlisting列表创建一个新的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)
这是很棒的东西,对'data.table'解决方案的解释确实有帮助。 –
由于删除行x
取决于所有行的值link
1:x-1
矢量化很难。我建议循环一次遍历所有行并保存冗余行的(布尔)索引。你在想,只有你的实现有点摇摇欲坠。
df <- data.frame(id=1:7,link=I(list(c(2,3),c(1,3),c(1,2),NA,NA,7,6)))
keep <- rep(TRUE, nrow(df))
for (i in 1:nrow(df)) {
idx <- df$link[[i]]
idx_larger_than_me <- idx[idx > i]
print(idx_larger_than_me)
keep[idx_larger_than_me] <- FALSE
}
df2 <- df[keep,]
谢谢彼得,这正是我打算做的。尽管这是一个功能性的答案,但我没有接受它,因为我希望能避免循环。 –
如果
第一匹配的行
您对于意思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
注:
- 首先
unnest
使link
s为单独的行(为同一id
) - 的
is.na(link)
保持有没有链接 - 的
link > id
将继续行为其link
比id
更大的所有行。当匹配顺序为id
时,这将保持第一个匹配,因为链接的行将大于id。 -
!duplicated(link)
将删除链接中的重复项。 - 然后,
nest
。
为什么不包含最后一行,即'7 6'? – akrun
'id == 6'行中'link'的值是'7'。这告诉你'6'和'7'实际上是相同的记录,我只想保留匹配记录的第一次出现(即只保留'id == 6'并放弃'id == 7') 。 –