Ins*_*nds 1 r duplicates dataframe
我df有一个link列(类型列表),指定记录是否匹配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
Run Code Online (Sandbox Code Playgroud)
我想要子集df以仅保留具有链接记录的那些行的第一个匹配行(即,关于按ID的顺序).我想要:
id link
1 1 2, 3
2 4 NA
3 5 NA
4 6 7
Run Code Online (Sandbox Code Playgroud)
我已经尝试了一个循环来存储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)
}
Run Code Online (Sandbox Code Playgroud)
我能以更简单的方式做到这一点并避免循环吗?
使用:
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]
Run Code Online (Sandbox Code Playgroud)
得到:
id link
1: 1 2, 3
2: 4 NA
3: 5 NA
4: 6 7
Run Code Online (Sandbox Code Playgroud)
说明:
df$link创建新的data.frame/data.table ,然后创建一个新的data.frame/data.table.或使用dplyr/ tidyr组合:
library(dplyr)
library(tidyr)
df %>%
unnest(link) %>%
group_by(id) %>%
filter(!any(id > link) | is.na(link)) %>%
summarise(link = toString(link))
Run Code Online (Sandbox Code Playgroud)
这给出了类似的结果:
# A tibble: 4 × 2
id link
<int> <chr>
1 1 2, 3
2 4 NA
3 5 NA
4 6 7
Run Code Online (Sandbox Code Playgroud)
或者使用基数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)
Run Code Online (Sandbox Code Playgroud)