我有一个很大的基因型data.table (26万行,1000列)。行是标记,列是主题。数据如下:
ID1 ID2 ID3 ID4
M1: CC CC TC CC
M2: GG GG GG GG
M3: TT TT TT TT
M4: TG TG TG TG
M5: TT TT TT TT
M6: TT TT TT TT我需要把每一种基因型分开,这样我才能在它自己的列中有这样的等位基因:
V1 V2 V3 V4 V5 V6 V7 V8
M1: C C C C T C C C
M2: G G G G G G G G
M3: T T T T T T T T
M4: T G T G T G T G
M5: T T T T T T T T
M6: T T T T T T T T我想出了两种解决方案,这两种解决方案都适用于数据的一个子集,但由于内存问题或data.table的某些内部错误,我无法理解,因此对整个数据集进行了分解。
strsplit,并将其存储到一个列表中,然后使用do.call将它们全部合并。我还使用foreach函数并行化了它。
ids <- colname(DT) gene.split <- function(i) { as.data.table(do.call(rbind,do.call idsi)),split =“”)} all.gene <- foreach(i=1:length(Id)) %dopar% gene.split(i) do.call(cbind,all.gene)在4个核心上,这是由于内存问题而崩溃的。
set函数:
out_names <-粘贴(“V”,1:(2*ncol(DT),sep="_") invar1 <- name(DT)(seq_along(Invar1)中的i){ set(DT,i=NULL,j=out_name2*i-1,value=do.call(rbind,str拆分(DT[[invar1i],split =“”))集合(DT,i=NULL,j=out_names2*i,value=do.call(rbind,str拆分(DT[invar1i]),split =“”),2)}}它可以在几个列上工作,但是如果我尝试使用整个数据集,则会得到以下错误:
集合中的错误(DT,i= NULL,j= out_names2 *i-1,value = do.call(rbind,:内部逻辑错误)。传递给赋值的DT没有分配足够的列槽。l=163,tl=163,添加1
我是不是走错路了?
发布于 2014-06-12 02:46:02
下面是一种使用data.table::set和substr的方法(而不是str拆分)
使用@jbaum示例数据l
# coerce to `data.table` without a copy
setDT(l)
# over allocate columns so that `data.table` can assign by reference
# this will stop the error you were seeing
alloc.col(l,3000)
out_names <- paste("V", 1:(2*ncol(l)), sep="_")
invar1 <- names(l)
for (i in seq_along(invar1)) {
set(l, i=NULL, j=out_names[2*i-1], value=substr(l[[invar1[i]]],1,1))
set(l, i=NULL, j=out_names[2*i], value=substr(l[[invar1[i]]],2,2))
}最后一步在我的Windows7 i7 2600机器上用了37秒,内存为8GB
在您的示例中,您运行了两次strsplit (并使用do.call(rbind....)) -->没有效率。
一些可能的分割方法的基准.
microbenchmark(substr(l[[invar1[1L]]],2,2), sapply(strsplit(l[[invar1[1L]]],''),`[`,2L),do.call(rbind, strsplit(l[[invar1[i]]], split = ""))[,2], times=5)
Unit: milliseconds
expr min lq median uq max neval
substr(l[[invar1[1L]]], 2, 2) 14.10669 14.35571 14.57485 15.78283 193.9125 5
sapply(strsplit(l[[invar1[1L]]], ""), `[`, 2L) 345.92969 1420.03907 1944.33873 3864.82876 5371.6130 5
do.call(rbind, strsplit(l[[invar1[i]]], split = ""))[, 2] 3318.70878 4131.38551 4155.06126 5269.92745 8414.4948 5发布于 2014-06-12 02:27:50
这里有一种相对较快的方法--花费了大约80秒(在虚拟数据创建之后) (Win 8.1 x64;i4770),但是消耗了13 GB的内存。
# Creating initial data
pairs <- c(outer(c('C', 'T', 'G', 'A'), c('C', 'T', 'G', 'A'), 'paste0'))
l <- replicate(1000, sample(pairs, 260000, replace=TRUE), simplify=FALSE)
system.time({
v <- do.call(paste0, l)
rm(l); gc()
out <- do.call(rbind, strsplit(v, ''))
rm(v); gc()
})
# user system elapsed
# 79.07 1.24 80.33
str(out)
# chr [1:260000, 1:2000] "A" "C" "C" "C" ...发布于 2014-06-12 02:11:40
下面是一种对数据帧x执行此操作的方法
do.call(cbind,
lapply(x,
function(i) do.call(rbind, strsplit(as.character(i), split=''))
)
)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] "C" "C" "C" "C" "T" "C" "C" "C"
[2,] "G" "G" "G" "G" "G" "G" "G" "G"
[3,] "T" "T" "T" "T" "T" "T" "T" "T"
[4,] "T" "G" "T" "G" "T" "G" "T" "G"
[5,] "T" "T" "T" "T" "T" "T" "T" "T"
[6,] "T" "T" "T" "T" "T" "T" "T" "T" 每一列被分割成字符,然后r-绑定在一起.这将给出列的列表,然后将这些列传递给cbind。
https://stackoverflow.com/questions/24174986
复制相似问题