【发布时间】:2020-01-09 15:52:47
【问题描述】:
我有一个如下所示的数据框:
SNP1 01010101000000100000010010001010011001010101
SNP2 01010010101000100000000000000001100001001000
SNP3 01010101000000000000000000000100011111111111
...但实际上包含约 800 万行,每个二进制向量的长度为 1000。
我需要选择这些二进制向量中的特定位置(跨所有行)。我发现这样做的肮脏方法是删除行名,将每个数字转换为一列,然后创建一个包含我感兴趣的位置的对象。
以下内容适用于示例数据,但对于我的真实数据来说效率不是很高(它已经运行了很长时间)。有什么想法可以让它更快吗?
library(data.table)
library(stringr)
setwd("test/")
DATADIR="datadir/"
OUTPUTDIR="outputdir/"
dir.create(OUTPUTDIR, showWarnings = FALSE)
baseline<-read.table(paste0(DATADIR,"input.file"), colClasses = "character")
# Pass BP name to row name (so that I can split the binary vector into multiple columns)
row.names(baseline) <- baseline$V1
baseline$V1 <- NULL
# split cells containing the binary vectors into multiple columns - thank you @Onyambu for this!
baseline_new <- read.table(text = gsub('(.)','\\1 ',baseline$V2),fill=TRUE)
# select columns of interest
columns_to_keep <- c(1, 4, 8, 10)
baseline_new_ss <- baseline_new[, columns_to_keep]
# create new object containing a column with the original row names, then recreate binary vector based on subsetted binary positions.
baseline_final <- as.data.frame(row.names(baseline))
baseline_final$V2 <- as.character(interaction(baseline_new_ss,sep=""))
输出(仅选择位置 1、4、8 和 10)应如下所示:
SNP1 0110
SNP2 0100
SNP3 0110
我确信有一种不那么复杂的方法。
谢谢!!
【问题讨论】:
-
认为它是一个固定宽度的文件,有 1000 列,每列宽度为一,use one of these approaches to read it that way directly。你有
library(data.table)这是一个好主意,但你根本没有使用它。data.table::fread是在我的链接中读取固定宽度文件的最快选择之一,它将创建一个data.table对象,这对于后续操作也应该是最快的。但是您需要阅读 data.table vignette 的介绍以了解如何使用它。 -
也就是说,根据您的后续操作,您最好使用我链接中最快的固定宽度阅读器
iotools,并将其设为matrix而不是data.table。或者一个稀疏矩阵,如果这些矩阵是稀缺的(从你的例子来看,它们看起来很常见,所以坚持使用常规矩阵。) -
vroom::vroom_fwf()可能也值得一看。不确定它在 Gregor 链接的基准测试中的表现如何,但它是另一个(可能很快)选项。 Link for more info onvroom::vroom_fwf()
标签: r vector data.table binary-data