我有这个表(data1)有四列
SNP rs6576700 rs17054099 rs7730126
sample1 G-G T-T G-G
Run Code Online (Sandbox Code Playgroud)
我需要将列2-4分成两列,因此新输出有7列.像这样 :
SNP rs6576700 rs6576700 rs17054099 rs17054099 rs7730126 rs7730126
sample1 G G T T C C
Run Code Online (Sandbox Code Playgroud)
使用以下函数,我可以在当时拆分所有列,但输出不是我需要的.
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"
Run Code Online (Sandbox Code Playgroud)
在Stack Overflow中,我找到了一种方法,将strsplit的输出转换为数据帧,但是rs数是行而不是列(我在这个线程中使用其他方法获得了类似的输出strsplit by row,并在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
Run Code Online (Sandbox Code Playgroud)
如果我不使用transpose函数(...(t(do.call ...)),则输出是一个无法写入文件的列表.
我希望在R中有解决方案,使其成为管道的一部分.
我忘了说我需要将它应用到一百万列.
这是使用该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
Run Code Online (Sandbox Code Playgroud)
这是一个解决方案,根据提供的链接使用GHtstrsplit的开发版本data.table的功能.在这里,我们将首先通过转租列名来定义索引,然后我们将使用它们进行编号.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
Run Code Online (Sandbox Code Playgroud)