在每列中拆分多个列的字符串

时间:2015-08-13 21:48:27

标签: r strsplit

我有这个表(data1)有四列

SNP rs6576700 rs17054099 rs7730126
sample1 G-G T-T G-G

我需要将列2-4分成两列,因此新输出有7列。像这样:

SNP rs6576700 rs6576700 rs17054099 rs17054099 rs7730126 rs7730126
sample1 G G T T C C

使用以下功能,我可以分割所有列,但输出不是我需要的。

split <- function(x){
    x <- as.character(x)
    strsplit(as.character(x), split="-")
  }

data2=apply(data1[,-1], 2, split)

data2
$rs17054099
$rs17054099[[1]]
[1] "T" "T"


$rs7730126
$rs7730126[[1]]
[1] "G" "G"


$rs6576700
$rs6576700[[1]]
[1] "C" "C"

在Stack Overflow中我找到了一个方法来将strsplit的输出转换为数据帧,但是rs数是行而不是列(我在这个线程strsplit by row and distribute results by column in data.frame中得到了与其他方法类似的输出)

> n <- max(sapply(data2, length))
> l <- lapply(data2, function(X) c(X, rep(NA, n - length(X))))
> data.frame(t(do.call(cbind, l)))
           t.do.call.cbind..l..
rs17054099                 T, T
rs7730126                  G, G
rs2061700                  C, C

如果我不使用transpose函数(...(t(do.call ...)),则输出是一个我无法写入文件的列表。

我想在R中使用解决方案使其成为管道的一部分。

我忘了说我需要将它应用到一百万列。

2 个答案:

答案 0 :(得分:7)

使用splitstackshape::cSplit功能可以直接进行。只需在splitCols参数中指定列索引,在sep参数中指定分隔符,就完成了。它甚至会为您的新列名编号,以便您能够区分它们。我已指定type.convert = FALSE,因此T值不会变为TRUE。默认方向为wide,因此您无需指定它。

library(splitstackshape)
cSplit(data1, 2:4, sep = "-", type.convert = FALSE)
#        SNP rs6576700_1 rs6576700_2 rs17054099_1 rs17054099_2 rs7730126_1 rs7730126_2
# 1: sample1           G           G            T            T           G           G

以下是使用devel version of data.table on GHtstrsplit函数提供的链接的解决方案。在这里,我们将首先通过转租列名来定义索引,然后我们将使用paste对它们进行编号。这是一种更麻烦的方法,但它的优点是它将更新原始数据而不是创建整个数据的副本

library(data.table) ## V1.9.5+
indx <- names(data1)[2:4]
setDT(data1)[, paste0(rep(indx, each = 2), 1:2) := sapply(.SD, tstrsplit, "-"), .SDcols = indx]
data1
#        SNP rs6576700 rs17054099 rs7730126 rs65767001 rs65767002 rs170540991 rs170540992 rs77301261 rs77301262
# 1: sample1       G-G        T-T       G-G          G          G           T           T          G          G

答案 1 :(得分:2)

在这里,您要使用行而不是列:

df <- rbind(c("SNP", "rs6576700", "rs17054099", "rs7730126"),
c("sample1", "G-G", "T-T", "G-G"),
c("sample2", "C-C", "T-T", "G-C"))

t(apply(df[-1,], 1, function(col) unlist(strsplit(col, "-"))))
#    [,1]      [,2] [,3] [,4] [,5] [,6] [,7]
#[1,] "sample1" "G"  "G"  "T"  "T"  "G"  "G" 
#[2,] "sample2" "C"  "C"  "T"  "T"  "G"  "C"