我有一个包含2列的数据框。第2列包含由;
分隔的基因,例如A;B
,A;B;C;D
。这些基因的数量可以从2到许多不等。我想将基因分成2对,然后放入新的行中。重要的是,我希望所有这些基因的所有可能组合(最初在一起)用于创建新行。当然,如果只有2个基因开头,则无需执行任何操作。另外,我想为新创建的行保留第1列中的值(文本)。
我没有尝试任何事情,因为我不知道如何解决该问题。
下面给出了示例输入和我想要的输出。
任何有关如何解决此问题的帮助或建议,将不胜感激。我确实对tidyverse有一些(有限的)经验。
谢谢您的宝贵时间。
input = data.frame(col1 = c("example1", "example2"), col2 = c("A;B", "A;B;C;D"))
output = data.frame(col1 = c("example1",
"example2",
"example2",
"example2",
"example2",
"example2"), col2 = c("A;B",
"A;B",
"A;C",
"A;D",
"B;C",
"B;D",
"C;D"))
答案 0 :(得分:2)
首先创建一个辅助函数(从您的input
起,我已经stringsAsFactors = FALSE
;如果您不愿意,只需在辅助函数中添加as.character()
)
char_comb <- function(aString) {
str_split(aString, pattern = ';') %>%
unlist() %>%
combn(2, paste0, collapse = ";")
}
NB-通过最少的示例运行来演示辅助功能:char_comb(aString = "A;B;C;D")
然后:
map2(.x = input[['col1']],
.y = input[['col2']], .f = function(idx, cell) {
if(nchar(cell) > 3) {
res <- char_comb(cell)
tibble(col1 = idx, col2 = res)
} else {
tibble(col1 = idx, col2 = cell)
}
}) %>%
bind_rows()
Result:
col1 col2
<chr> <chr>
1 example1 A;B
2 example2 A;B
3 example2 A;C
4 example2 A;D
5 example2 B;C
6 example2 B;D
7 example2 C;D
p.s。我的解决方案还包括“ A; B”。排除它们是微不足道的。
从评论看来,@ ip2018担心执行时间。 将两个解决方案都包装在一个函数中...
microbenchmark("pasqui" = res_fn(col1 = input[['col1']], col2 = input[['col2']]),
"H 1" = h1_res()
)
基准测试结果
Unit: milliseconds
expr min lq mean median uq max neval cld
pasqui 1.137418 1.198085 1.403278 1.297016 1.611183 2.310684 100 a
H 1 9.140376 9.811799 12.126555 10.730754 13.036842 45.186844 100 b
答案 1 :(得分:2)
这是一种tidyverse
的方法:
library(tidyverse)
input %>%
filter(grepl(";", col2)) %>%
mutate(x = str_split(col2, ";") %>% map(~combn(., 2, paste0, collapse = ";"))) %>%
unnest() %>%
select(-col2)
# A tibble: 7 x 2
# Groups: col1 [2]
col1 x
<fct> <chr>
1 example1 A;B
2 example2 A;B
3 example2 A;C
4 example2 A;D
5 example2 B;C
6 example2 B;D
7 example2 C;D
答案 2 :(得分:0)
这是另一个计算for循环中所有内容的解决方案,不确定在处理时间方面如何与pasqui的答案进行比较。
col1<-c()
col2<-c()
for(i in 1:nrow(input)){
name<-input$col1[i]
splt<-unlist(strsplit(input$col2[i],";"))
#Generate Matrix of Pair-Wise Combinations
combs<-sapply(splt, function(x) sapply(splt, function(y) paste(x,y, sep=";") ))
#Limit to Unique Combinations
uni_combinations<-combs[lower.tri(combs)]
#Save vector of names
n<-length(uni_combinations)
col1<-c(col1,rep(name,n))
# Save vector of gene combinations
col2<-c(col2, uni_combinations)
}
# Put results in data.frame()
result<-data.frame(col1=col1, col2 = col2)
result