R - 读取没有分隔符的二进制矩阵
R - Read binary matrix with no separator
我正在尝试读取 R 中的大型(~100mb)二进制矩阵。这就是明文的样子:
10001010
10010100
00101101
预期输出:
V1 V2 V3 V4 V5 V6 V7 V8
r1 1 0 0 0 1 0 1 0
r2 1 0 0 1 0 1 0 0
r3 0 0 1 0 1 1 0 1
我目前正在阅读每一行并将这些位分开。有没有更有效的方法来做到这一点?
一个 base R
选项(可能很慢)将是 scan
.txt
文件,split
分隔符 ""
的元素,将 list
元素转换为 numeric/integer
和 rbind
以创建 matrix
.
m1 <- do.call(rbind,lapply(strsplit(scan("inpfile.txt",
what=""), ""), as.numeric))
m1
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#[1,] 1 0 0 0 1 0 1 0
#[2,] 1 0 0 1 0 1 0 0
#[3,] 0 0 1 0 1 1 0 1
稍微快一点的版本是用fread
读取文件,然后用tstrsplit
library(data.table)
fread("inpfile.txt", colClasses="character")[, tstrsplit(V1, "")]
# V1 V2 V3 V4 V5 V6 V7 V8
#1: 1 0 0 0 1 0 1 0
#2: 1 0 0 1 0 1 0 0
#3: 0 0 1 0 1 1 0 1
我还会通过使用 awk
(如果 OP 使用 linux
)在每个字符之间创建 space 来更改分隔符,然后使用 fread
读取(我无法测试它,因为我在 windows
系统上。)
更快的选择可能还包括使用 library(iotools)
n <- nchar(scan(file, what="",n=1))
library(iotools)
input.file("inpfile.txt", formatter=dstrfw,
col_types=rep("integer",n), widths=rep(1,n))
# V1 V2 V3 V4 V5 V6 V7 V8
#1 1 0 0 0 1 0 1 0
#2 1 0 0 1 0 1 0 0
#3 0 0 1 0 1 1 0 1
基准
使用稍大的数据集,readr
和 iotools
之间的时间如下。
n <-100000
cat(gsub("([[:alnum:]]{8})", "\1\n", paste(sample(0:1,
n*8, TRUE), collapse="")),
file="dat2.txt")
library(readr)
tic <- Sys.time()
read_fwf("dat2.txt", fwf_widths(rep(1, 8)))
difftime(Sys.time(), tic)
#Time difference of 1.142145 secs
tic <- Sys.time()
input.file("dat2.txt", formatter=dstrfw,
col_types=rep("integer",8), widths=rep(1,8))
difftime(Sys.time(), tic)
#Time difference of 0.7440939 secs
library(LaF)
tic <- Sys.time()
laf <- laf_open_fwf("dat2.txt", column_widths = rep(1,
8), column_types=rep("integer", 8))
## further processing (larger in memory)
dat <- laf[,]
difftime(Sys.time(), tic)
#Time difference of 0.1285172 secs
到目前为止最有效的是@Tyler Rinker 发布的library(LaF)
,其次是library(iotools)
使用 readr 的固定宽度文件 reader:
在大文件上这可能会非常快
library(readr)
read_fwf("dat.txt", fwf_widths(rep(1, 8)))
## X1 X2 X3 X4 X5 X6 X7 X8
## (int) (int) (int) (int) (int) (int) (int) (int)
## 1 1 0 0 0 1 0 1 0
## 2 1 0 0 1 0 1 0 0
## 3 0 0 1 0 1 1 0 1
我想扩大规模和时间。在下面的过程中,读取与您讨论的文件相当的文件需要 readr ~7.5 秒。
n <-10000000
cat(gsub("([[:alnum:]]{8})", "\1\n", paste(sample(0:1, n*8, TRUE), collapse="")), file="dat2.txt")
file.size('dat2.txt') #100000000
tic <- Sys.time()
read_fwf("dat2.txt", fwf_widths(rep(1, 8)))
difftime(Sys.time(), tic)
## Time difference of 7.41096 secs
您可能还想考虑使用 LaF 包来读取固定宽度的大文件。类似于:
library(LaF)
cols <- 8
laf <- laf_open_fwf("dat2.txt", column_widths = rep(1, cols),
column_types=rep("integer", cols))
## further processing (larger in memory)
dat <- laf[,]
我正在尝试读取 R 中的大型(~100mb)二进制矩阵。这就是明文的样子:
10001010
10010100
00101101
预期输出:
V1 V2 V3 V4 V5 V6 V7 V8
r1 1 0 0 0 1 0 1 0
r2 1 0 0 1 0 1 0 0
r3 0 0 1 0 1 1 0 1
我目前正在阅读每一行并将这些位分开。有没有更有效的方法来做到这一点?
一个 base R
选项(可能很慢)将是 scan
.txt
文件,split
分隔符 ""
的元素,将 list
元素转换为 numeric/integer
和 rbind
以创建 matrix
.
m1 <- do.call(rbind,lapply(strsplit(scan("inpfile.txt",
what=""), ""), as.numeric))
m1
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#[1,] 1 0 0 0 1 0 1 0
#[2,] 1 0 0 1 0 1 0 0
#[3,] 0 0 1 0 1 1 0 1
稍微快一点的版本是用fread
读取文件,然后用tstrsplit
library(data.table)
fread("inpfile.txt", colClasses="character")[, tstrsplit(V1, "")]
# V1 V2 V3 V4 V5 V6 V7 V8
#1: 1 0 0 0 1 0 1 0
#2: 1 0 0 1 0 1 0 0
#3: 0 0 1 0 1 1 0 1
我还会通过使用 awk
(如果 OP 使用 linux
)在每个字符之间创建 space 来更改分隔符,然后使用 fread
读取(我无法测试它,因为我在 windows
系统上。)
更快的选择可能还包括使用 library(iotools)
n <- nchar(scan(file, what="",n=1))
library(iotools)
input.file("inpfile.txt", formatter=dstrfw,
col_types=rep("integer",n), widths=rep(1,n))
# V1 V2 V3 V4 V5 V6 V7 V8
#1 1 0 0 0 1 0 1 0
#2 1 0 0 1 0 1 0 0
#3 0 0 1 0 1 1 0 1
基准
使用稍大的数据集,readr
和 iotools
之间的时间如下。
n <-100000
cat(gsub("([[:alnum:]]{8})", "\1\n", paste(sample(0:1,
n*8, TRUE), collapse="")),
file="dat2.txt")
library(readr)
tic <- Sys.time()
read_fwf("dat2.txt", fwf_widths(rep(1, 8)))
difftime(Sys.time(), tic)
#Time difference of 1.142145 secs
tic <- Sys.time()
input.file("dat2.txt", formatter=dstrfw,
col_types=rep("integer",8), widths=rep(1,8))
difftime(Sys.time(), tic)
#Time difference of 0.7440939 secs
library(LaF)
tic <- Sys.time()
laf <- laf_open_fwf("dat2.txt", column_widths = rep(1,
8), column_types=rep("integer", 8))
## further processing (larger in memory)
dat <- laf[,]
difftime(Sys.time(), tic)
#Time difference of 0.1285172 secs
到目前为止最有效的是@Tyler Rinker 发布的library(LaF)
,其次是library(iotools)
使用 readr 的固定宽度文件 reader:
在大文件上这可能会非常快library(readr)
read_fwf("dat.txt", fwf_widths(rep(1, 8)))
## X1 X2 X3 X4 X5 X6 X7 X8
## (int) (int) (int) (int) (int) (int) (int) (int)
## 1 1 0 0 0 1 0 1 0
## 2 1 0 0 1 0 1 0 0
## 3 0 0 1 0 1 1 0 1
我想扩大规模和时间。在下面的过程中,读取与您讨论的文件相当的文件需要 readr ~7.5 秒。
n <-10000000
cat(gsub("([[:alnum:]]{8})", "\1\n", paste(sample(0:1, n*8, TRUE), collapse="")), file="dat2.txt")
file.size('dat2.txt') #100000000
tic <- Sys.time()
read_fwf("dat2.txt", fwf_widths(rep(1, 8)))
difftime(Sys.time(), tic)
## Time difference of 7.41096 secs
您可能还想考虑使用 LaF 包来读取固定宽度的大文件。类似于:
library(LaF)
cols <- 8
laf <- laf_open_fwf("dat2.txt", column_widths = rep(1, cols),
column_types=rep("integer", cols))
## further processing (larger in memory)
dat <- laf[,]