【问题标题】:Find all indices of duplicates and write them in new columns查找所有重复项的索引并将它们写入新列
【发布时间】:2017-08-15 01:38:57
【问题描述】:

我有一个 data.frame,它只有一列,一个字符串向量。

这些字符串具有重复值。 我想在这个向量中找到重复的字符串,并将它们的位置索引写在一个新列中。

例如,假设我有:

DT<- data.frame(string=A,B,C,D,E,F,A,C,F,Z,A)

我想得到:

string match2 match2 match3 matchx....
A      1       7      11
B      2       NA     NA
C      3       8      NA
D      4       NA     NA
E      5       NA     NA
F      6       9      NA
A      1       7      11
C      3       8      NA
F      6       9      NA
Z      10      NA     NA
A      1       7      11

字符串比本例中的要长,我不知道我需要的最大列数。

最有效的方法是什么? 我知道有重复的功能,但我不完全确定如何将它结合到我想要在这里得到的结果。

非常感谢!

【问题讨论】:

    标签: r duplicates


    【解决方案1】:

    这是执行此操作的一种方法。我确信一个数据表会跟随一个班轮。

    DT<- data.frame(string=c("A","B","C","D","E","F","A","C","F","Z","A"))
    
    # find matches
    rbf <- sapply(DT$string, FUN = function(x, DT) which(DT %in% x), DT = DT$string)
    
    # fill in NAs to have a pretty matrix
    out <- sapply(rbf, FUN = function(x, mx) c(x, rep(NA, length.out = mx - length(x))), max(sapply(rbf, length)))
    
    # bind it to the original data
    cbind(DT, t(out))
    
       string  1  2  3
    1       A  1  7 11
    2       B  2 NA NA
    3       C  3  8 NA
    4       D  4 NA NA
    5       E  5 NA NA
    6       F  6  9 NA
    7       A  1  7 11
    8       C  3  8 NA
    9       F  6  9 NA
    10      Z 10 NA NA
    11      A  1  7 11
    

    【讨论】:

      【解决方案2】:

      这是data.table 的一个选项。按'string'分组后,得到序列(seq_len(.N))和行索引(.I),然后dcast为'wide'格式并与原始数据集on'string'连接

      library(data.table)
      dcast(setDT(DT)[, .(seq_len(.N),.I), string],string ~ paste0("match", V1))[DT, on = "string"]
      #     string match1 match2 match3
      # 1:      A      1      7     11
      # 2:      B      2     NA     NA
      # 3:      C      3      8     NA
      # 4:      D      4     NA     NA
      # 5:      E      5     NA     NA
      # 6:      F      6      9     NA
      # 7:      A      1      7     11
      # 8:      C      3      8     NA
      # 9:      F      6      9     NA
      #10:      Z     10     NA     NA
      #11:      A      1      7     11
      

      或者另一种选择是split 使用“字符串”的行序列,用NA 填充list 元素以获得更短的长度,以及merge 使用原始数据集(使用base R方法)

      lst <- split(seq_len(nrow(DT)), DT$string)
      merge(DT, do.call(rbind, lapply(lst, `length<-`, max(lengths(lst)))),
                     by.x = "string", by.y = "row.names")
      

      数据

      DT<- data.frame(string=c("A","B","C","D","E","F","A","C",
                    "F","Z","A"), stringsAsFactors=FALSE)
      

      【讨论】:

      • 谢谢大家!!所有答案都很棒,完全解决了我的问题。我把这个作为公认的,因为它是最短的,并且包括列的命名。
      【解决方案3】:

      这是一个使用tidyverse 工具的工具(不完全是单线;)):

      library( tidyverse )
      
      DT %>% group_by( string ) %>%
        do( idx = which(DT$string == unique(.$string)) ) %>% 
        ungroup %>% unnest %>% group_by( string ) %>%
        mutate( m = stringr::str_c( "match", 1:n() ) ) %>%
        spread( m, idx )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-11
        • 2023-03-15
        • 1970-01-01
        • 2013-10-01
        相关资源
        最近更新 更多