我想从文本文件中获取列名和行名,并使用行和列信息构建稀疏矩阵(该算法可在下面的描述中找到)。我有一个有效的解决方案,但对于包含超过3,000,000个条目的文本文件来说,它很慢。
有没有人对比我在下面描述的算法更快的算法有任何建议?
首先,我从一个文本文件开始,该文件提供以空格分隔的列名和行名。例如:
aaaa 11111 22222 33333 bbbb 11111 22222 cccc 11111
其中{aaaa,bbbb,cccc}
是4个字符的列名,{11111,22222,33333}
是5个字符的行名。
其次,我使用扫描功能将此文本文件加载到R
:
char_vec <- scan(file = "textFile.txt", what = "character")
将textFile信息转换为字符向量。
第三,我找到了所有可能的列名和行名:
c_names <- unique(char_vec[nchar(char_vec) == 4])
r_names <- unique(char_vec[nchar(char_vec) == 5])
第四,我从数据中创建一个稀疏矩阵:
library(Matrix)
createMatrix <- function(char_vec=char_vec, c_names=c_names, r_names=r_names)
{
mySparseMatrix <- Matrix(0, nrow = length(r_names), ncol = length(c_names),
sparse = TRUE)
for (i1 in 1:length(char_vec))
{
if (char_vec[i1] %in% c_names)
{
c_index <- match(char_vec[i1], c_names)
}
if (char_vec[i1] %in% r_names)
{
r_index <- match(char_vec[i1], r_names)
mySparseMatrix[r_index, c_index] <- 1
}
}
colnames(mySparseMatrix) <- c_names
rownames(mySparseMatrix) <- r_names
return(mySparseMatrix)
}
这给出了这个输出:
aaaa bbbb cccc
11111 1 1 1
22222 1 1 .
33333 1 . .
为了说明这个算法的工作速度,我填写了字符向量(尽管是以不切实际的方式,但我认为它的目的是作为一个例子):
char_vec <- rep(c("aaaa", "11111", "22222", "33333", "bbbb", "11111", "22222", "cccc", "11111"), 1000)
然后跑了:
system.time(createMatrix(char_vec, c_names, r_names))
输出:
user system elapsed
9.89 0.00 9.94
我使用以下方式分析了该功能:
Rprof("createMatrixOut.out")
z <- createMatrix(char_vec, c_names, r_names)
Rprof(NULL)
并使用以下方式显示输出的子集:
summaryRprof("createMatrixOut.out")$by.total[1:10,]
输出:
total.time total.pct self.time self.pct
"createMatrix" 8.08 100.00 0.08 0.99
"[<-" 7.96 98.51 0.08 0.99
"replCmat4" 7.40 91.58 0.04 0.50
"as" 5.64 69.80 0.04 0.50
"asMethod" 5.06 62.62 0.16 1.98
"standardGeneric" 4.68 57.92 0.24 2.97
"new" 4.52 55.94 0.02 0.25
"initialize" 4.40 54.46 0.04 0.50
"callNextMethod" 4.24 52.48 0.08 0.99
".Call" 4.12 50.99 0.60 7.43
答案 0 :(得分:1)
我更改了数据的结构:我创建了列表:
,而不是将它们存储在字符向量中> lst
$aaaa
[1] "11111" "22222" "33333"
$bbbb
[1] "11111" "22222"
$cccc
[1] "11111"
迭代这个列表要快得多
createMatrix2 <- function(char_vec=char_vec, c_names=c_names, r_names=r_names)
{
# create list
lst <- list()
for (i1 in 1:length(char_vec))
{
if (nchar(char_vec[i1])==4)
{
cn <- char_vec[i1]
} else {
if (!(char_vec[i1] %in% lst[[cn]])){lst[[cn]] <- c(lst[[cn]],char_vec[i1])}
}
}
# create empty matrix
mySparseMatrix <- Matrix(0, nrow = length(r_names), ncol = length(c_names),
sparse = TRUE)
# fill the matrix
for (cn in names(lst)){
c_index <- match(cn, c_names)
for(rn in lst[[cn]]){
r_index <- match(rn, r_names)
mySparseMatrix[r_index, c_index] <- 1
}
}
# names and return
colnames(mySparseMatrix) <- c_names
rownames(mySparseMatrix) <- r_names
return(mySparseMatrix)
}
> system.time(createMatrix(char_vec, c_names, r_names))
user system elapsed
9.60 0.00 10.36
> system.time(createMatrix2(char_vec, c_names, r_names))
user system elapsed
0.06 0.00 0.06