如何检查R中数据帧列的每个单元格(列表)是否唯一?

时间:2014-12-30 01:03:44

标签: r dataframe

我有一个非常大的数据,我想要做的是检查一个列表是否有一个字符串的多个值:  请考虑这个数据框:

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

2 个答案:

答案 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                                     []