我有一个非常大的数据,我想要做的是检查一个列表是否有一个字符串的多个值: 请考虑这个数据框:
df1 <- structure(list(id = 1:3,
book_id = c("[\"19167120\",\"book\", \"237494310\",\"195166798\",\"book\",\"book.a\"]",
"[\"19167120\",\"237494310\",\"story\",\"book\",\"19167120\"]", "[]")),
.Names = c("id", "book_id"),
class = "data.frame",
row.names = c(NA, -3L))
是:
id book_id
1 1 ["19167120","book", "237494310","195166798","book","book.a"]
2 2 ["19167120","237494310","story","book","19167120"]
3 3 []
我要做的是检查book_id中是否有任何列表值具有多个字符串值,例如:字符串值"19167120"
对于第二行是重复的。
并为每个单元格提取它们,然后从每个单元格中删除它们
输出:两个独立的数据帧:
id book_id duplicate
1: 1 ["19167120", "book", "237494310", "195166798", "book", "book.a"] "book"
2: 2 ["19167120", "237494310", "story", "book", "19167120"] "19167120"
3: 3 [] 0
id book_id
1: 1 ["19167120", "book", "237494310", "195166798", "book.a"]
2: 2 ["19167120", "237494310", "story", "book"]
3: 3 []
我知道我应该使用anyduplicated()
和unique()
来获得我的答案,但我解决了这些问题,我无法解决问题。
编辑:Gregor的第一个建议是这样的,但我很感激,如果有人能帮助我得到输出,我先解释一下,
id book_id
1: 1 "19167120"
2: 1 "237494310"
3: 1 "195166798"
4: 2 "19167120"
5: 2 "237494310"
6: 2 "19167120"
> unique(df1)
id book_id
1: 1 "19167120"
2: 1 "237494310"
3: 1 "195166798"
4: 2 "19167120"
5: 2 "237494310"
> duplicated(df1)
[1] FALSE FALSE FALSE FALSE FALSE TRUE
答案 0 :(得分:3)
您可以尝试stringi
library(stringi)
library(data.table)
x <- stri_extract_all_regex(df1$book_id, "\\d+", omit = TRUE)
dupes <- vapply(x, function(a) {
paste(a[duplicated(a)], collapse = ", ")
}, "")
dt2 <- data.table(df1, dupes)
doBookId <- function(x) {
u <-stri_unique(x)
st <- if(length(u)) toString(shQuote(u, "cmd")) else character(1L)
stri_c("[", st, "]")
}
dt2[, book_id := vapply(x, doBookId, "")][]
# id book_id dupes
# 1: 1 ["19167120", "237494310", "195166798"]
# 2: 2 ["19167120", "237494310"] 19167120
# 3: 3 []
更新:鉴于您的更新,我认为我们只需要进行一些调整。主要是从stri_extract_all_regex
切换到stri_extract_all_words
x <- stri_extract_all_words(df1$book_id)
dupes <- vapply(x, function(a) toString(a[duplicated(a)]), "")
dt2 <- data.table(df1, dupes)
dt2
# id book_id dupes
# 1: 1 ["19167120","book", "237494310","195166798","book","book.a"] book
# 2: 2 ["19167120","237494310","story","book","19167120"] 19167120
# 3: 3 []
doBookId <- function(x) {
st <- if(length(x) >= 1L && !is.na(x))
toString(shQuote(unique(x), "cmd"))
else ""
stri_c("[", st, "]")
}
dt3 <- dt2[, dupes := NULL]
dt3[, book_id := vapply(x, doBookId, "")][]
# id book_id
# 1: 1 ["19167120", "book", "237494310", "195166798", "book.a"]
# 2: 2 ["19167120", "237494310", "story", "book"]
# 3: 3 []
答案 1 :(得分:3)
这是一种替代方法,与开始使用&#34; long&#34;数据集并从那里开始。
这是您的长数据集。
library(splitstackshape)
x <- cSplit(df1, "book_id", ",", "long")[, book_id := gsub(
"[][]", "", book_id)]
在这里,我们添加一个&#34; duped&#34;具有重复值的列:
x[, duped := paste(unique(book_id[duplicated(book_id)],
collapse = ", ")), by = id]
现在我们可以轻松创建您想要的第一个输出:
dupedX <- x[, list(book_id = sprintf("[%s]", paste(book_id, collapse = ", ")),
duped = paste(unique(duped), collapse = ", ")), by = id]
dupedX
# id book_id duped
# 1: 1 ["19167120", "237494310", "195166798"] NA
# 2: 2 ["19167120", "237494310", "19167120"] "19167120"
# 3: 3 [] NA
你的第二个:
uniqueX <- x[, list(book_id = sprintf(
"[%s]", paste(unique(book_id), collapse = ", "))), by = id]
uniqueX
# id book_id
# 1: 1 ["19167120", "237494310", "195166798"]
# 2: 2 ["19167120", "237494310"]
# 3: 3 []