我问了一个可能不太清楚的问题。所以我试着以一种可以理解的方式解释它。这是我的数据
我的数据看起来像这样
看起来像这样
# V1 V2 V3
#1 Q9UNZ5 Q9Y2W1
#2 Q9ULV4;Q6QEF8
#3 Q9UNZ5
#4 Q9H6F5
#5 Q9H2K0 Q9ULV4;Q6QEF8
#6 Q9GZZ1 Q9UKD2
#7 Q9H6F5 Q9GZZ1 Q9GZZ1
#8 Q9GZZ1 Q9NYF8
#9 Q9BWS9
我想在所有这些字符串中删除重复的字符串 例如,V1我们第一次拥有所有字符串,所以我们不会删除任何东西只是安排它们
Q9ULV4
Q6QEF8
Q9H6F5
Q9GZZ1
Q9BWS9
然后我们用第一列检查第二列字符串,然后删除重复的那些字符串并再次排列它们。对于第三列,我们检查第一列和第二列的字符串,如果相似,则我们删除然后排列它们。所以输出应该如下所示。
Q9ULV4 Q9UNZ5 Q9Y2W1
Q6QEF8 Q9H2K0 Q9UKD2
Q9H6F5 Q9NYF8
Q9GZZ1
Q9BWS9
这与我提出的任何问题都不相似;所以,如果仍然不清楚,请评论,我试着解释一下
答案 0 :(得分:5)
我会分两步来处理这个问题:
1)每列获取唯一元素并转换为列表:
l <- lapply(df, function(x) unique(unlist(strsplit(as.character(x), ";"))))
2)删除任何先前列中出现的重复项
for(i in seq_along(l)) {
l[[i]] <- setdiff(l[[i]], unlist(l[seq_len(i-1L)]))
}
我使用list
而不是data.frame
的原因是因为data.frame
要求所有列都具有相同的行数,这不是这里的情况(除非你用NA或空字符串填充它们。在这种情况下,list
结构是可行的方法。
答案 1 :(得分:4)
第一行将df
转换为列表L
。第二行创建一个长格式数据框long
,其中包含column1中的值和第2列中的df
列名称作为因子。需要将其作为一个因素,因为级别保留所有列名称,包括由于仅包含重复项而随后被删除的列名称。此外,它保留列名称的顺序。最后一行删除了生成long0
的重复项。没有包使用。
L <- lapply(df, function(x) unlist(strsplit(as.character(x), ";")))
long <- transform(stack(L), ind = factor(as.character(ind), levels = names(df)))
long0 <- subset(long, !duplicated(values))
现在我们考虑三种可能的输出形式:
1)长格式数据框
> long0
values ind
1 Q9ULV4 V1
2 Q6QEF8 V1
3 Q9H6F5 V1
4 Q9GZZ1 V1
5 Q9BWS9 V1
6 Q9UNZ5 V2
8 Q9H2K0 V2
11 Q9Y2W1 V3
15 Q9UKD2 V3
17 Q9NYF8 V3
2)列表
L0 <- unstack(long0)
,并提供:
> L0
$V1
[1] "Q9ULV4" "Q6QEF8" "Q9H6F5" "Q9GZZ1" "Q9BWS9"
$V2
[1] "Q9UNZ5" "Q9H2K0"
$V3
[1] "Q9Y2W1" "Q9UKD2" "Q9NYF8"
3)字符矩阵创建L0
版本,用NA
替换每个零长度组件,然后将每个组件的长度扩展为最大长度,重新变为矩阵同时通过sapply
。
lens <- lengths(L0)
m0 <- sapply(replace(L0, !lens, NA), "length<-", max(lens))
,并提供:
> m0
V1 V2 V3
[1,] "Q9ULV4" "Q9UNZ5" "Q9Y2W1"
[2,] "Q6QEF8" "Q9H2K0" "Q9UKD2"
[3,] "Q9H6F5" NA "Q9NYF8"
[4,] "Q9GZZ1" NA NA
[5,] "Q9BWS9" NA NA
更新:一些修复和澄清。
注1:可重复形式的输入df
为:
df <-
structure(list(V1 = c("", "Q9ULV4;Q6QEF8", "", "", "", "", "Q9H6F5",
"Q9GZZ1", "Q9BWS9"), V2 = c("Q9UNZ5", "", "", "Q9H6F5", "Q9H2K0",
"Q9GZZ1", "Q9GZZ1", "", ""), V3 = c("Q9Y2W1", "", "Q9UNZ5", "",
"Q9ULV4;Q6QEF8", "Q9UKD2", "Q9GZZ1", "Q9NYF8", "")), .Names = c("V1",
"V2", "V3"), row.names = c(NA, -9L), class = "data.frame")
注2:在R的最新开发版本中,&#34; R正在开发(不稳定)(2016-07-05 r70861)&#34;,{{1}顶部附近的行可以简化为long <-
,因为long <- stack(L)
会为该版本的R中的所有级别创建一个因子。
答案 2 :(得分:2)
我会以这种方式基于duplicate
函数在普通R中执行此操作:
lst <- lapply(df, function(x) unlist(strsplit(as.character(x), ";", fixed = TRUE)))
cols <- colnames(df)
seen_entries <- NULL
for (i in (1:ncol(df))) {
n_seen_before <- length(seen_entries)
seen_entries <- c(seen_entries, lst[[cols[i]]])
lst[[cols[i]]] <- lst[[cols[i]]][(!duplicated(seen_entries))[
(n_seen_before+1):length(seen_entries)]]
}
输出是:
> lst
$V1
[1] "Q9ULV4" "Q6QEF8" "Q9H6F5" "Q9GZZ1" "Q9BWS9"
$V2
[1] "Q9UNZ5" "Q9H2K0"
$V3
[1] "Q9Y2W1" "Q9UKD2" "Q9NYF8"
可能有更优雅的解决方案使用例如data.table
或类似的东西。
答案 3 :(得分:2)
我们可以尝试
lst <- lapply(df, function(x) unique(unlist(strsplit(as.character(x), ";"))))
lapply(seq_along(lst), function(i) {
v1 <- unlist(lst[seq(i)])
setdiff(lst[[i]], v1[duplicated(v1)])})
#[[1]]
#[1] "Q9ULV4" "Q6QEF8" "Q9H6F5" "Q9GZZ1" "Q9BWS9"
#[[2]]
#[1] "Q9UNZ5" "Q9H2K0"
#[[3]]
#[1] "Q9Y2W1" "Q9UKD2" "Q9NYF8"