查找重复的所有索引并将其写入新列

时间:2017-08-14 17:05:48

标签: r duplicates

我有一个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

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

最有效的方法是什么? 我知道有重复的功能,但我不确定如何将它与我想要的结果相结合。

非常感谢!

3 个答案:

答案 0 :(得分:3)

这是实现这一目标的一种方式。我确定有一个data.table one liner。

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

答案 1 :(得分:2)

以下是data.table的一个选项。按&#39;字符串&#39;分组后,获取序列(seq_len(.N))和行索引(.I),然后dcast到&#39;宽&#39;格式化并加入原始数据集on&#39;字符串&#39;

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带有&#39;字符串&#39;的行序列,填充list元素NA的长度更短,{ {1}}使用原始数据集(使用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")

答案 2 :(得分:1)

这是一个使用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 )