【发布时间】:2015-11-18 16:40:55
【问题描述】:
我对使用 data.table 并了解其所有细微之处还有些陌生。 我查看了文档和 SO 中的其他示例,但找不到我想要的,所以请帮忙!
我有一个 data.table,它基本上是一个字符向量(每个条目都是一个句子)
DT=c("I love you","she loves me")
DT=as.data.table(DT)
colnames(DT) <- "text"
setkey(DT,text)
# > DT
# text
# 1: I love you
# 2: she loves me
我想做的是能够在 DT 对象内执行一些基本的字符串操作。例如,添加一个新列,其中我将有一个 char 向量,其中每个条目都是“text”列中字符串中的一个 WORD。
所以我想有一个新的列 charvec where
> DT[1]$charvec
[1] "I" "love "you"
当然,我想用data.table的方式来做,超快,因为我需要在>1Go文件的fils上做这种事情,并且使用更复杂和计算量大的函数。所以不要使用 APPLY、LAPPLY 和 MAPPLY
我最接近的尝试如下:
myfun1 <- function(sentence){strsplit(sentence," ")}
DU1 <- DT[,myfun1(text),by=text]
DU2 <- DU1[,list(charvec=list(V1)),by=text]
# > DU2
# text charvec
# 1: I love you I,love,you
# 2: she loves me she,loves,me
例如,要制作一个删除每个句子的第一个单词的函数,我这样做了
myfun2 <- function(l){l[[1]][-1]}
DV1 <- DU2[,myfun2(charvec),by=text]
DV2 <- DV1[,list(charvec=list(V1)),by=text]
# > DV2
# text charvec
# 1: I love you love,you
# 2: she loves me loves,me
问题是,在 charvec 列中,我有一个列表而不是向量...
> str(DU2[1]$charvec)
# List of 1
# $ : chr [1:3] "I" "love" "you"
1) 我怎样才能做我想做的事? 我正在考虑使用的其他类型的函数是对 char 向量进行子集化,或者对其应用一些哈希等。
2) 顺便说一句,我可以用一条线而不是两条线到达 DU2 或 DV2 吗?
3) 我不太了解 data.table 的语法。为什么使用 [..] 内的命令 list() 时,V1 列消失了?
4) 在另一个线程上,我读到了一些关于函数cSplit 的内容。
。有什么好处吗?是适配data.table对象的函数吗?
非常感谢
更新
感谢@Ananda Mahto 也许我应该让自己更清楚我的最终目标 我有一个存储为字符串的 10,000,000 个句子的巨大文件。 作为该项目的第一步,我想对每个句子的前 5 个单词进行哈希处理。 10,000,000 个句子甚至不会进入我的记忆,所以我首先将 1,000,000 个句子分成 10 个文件,大约是 10x 1Go 文件。 以下代码在我的笔记本电脑上只为一个文件需要几分钟。
library(data.table); library(digest);
num_row=1000000
DT <- fread("sentences.txt",nrows=num_row,header=FALSE,sep="\t",colClasses="character")
DT=as.data.table(DT)
colnames(DT) <- "text"
setkey(DT,text)
rawdata <- DT
hash2 <- function(word){ #using library(digest)
as.numeric(paste("0x",digest(word,algo="murmur32"),sep=""))
}
那么,
print(system.time({
colnames(rawdata) <- "sentence"
rawdata <- lapply(rawdata,strsplit," ")
sentences_begin <- lapply(rawdata$sentence,function(x){x[2:6]})
hash_list <- sapply(sentences_begin,hash2)
# remove(rawdata)
})) ## end of print system.time for loading the data
我知道我将 R 推到了极限,但我正在努力寻找更快的实现,我正在考虑 data.table 功能......因此我的所有问题
这是一个不包括 lapply 的实现,但它实际上更慢!
print(system.time({
myfun1 <- function(sentence){strsplit(sentence," ")}
DU1 <- DT[,myfun1(text),by=text]
DU2 <- DU1[,list(charvec=list(V1)),by=text]
myfun2 <- function(l){l[[1]][2:6]}
DV1 <- DU2[,myfun2(charvec),by=text]
DV2 <- DV1[,list(charvec=list(V1)),by=text]
rebuildsentence <- function(S){
paste(S,collapse=" ") }
myfun3 <- function(l){hash2(rebuildsentence(l[[1]]))}
DW1 <- DV2[,myfun3(charvec),by=text]
})) #end of system.time
在这个使用数据文件的实现中,没有 lapply,所以我希望散列会更快。但是,因为在每一列中我都有一个列表而不是一个 char 向量,所以这可能会显着减慢(?)整个事情。
使用上面的第一个代码(lapply/sapply)在我的笔记本电脑上花费了 1 个多小时。我希望通过更有效的数据结构来加快速度?使用 Python、Java 等的人......在几秒钟内完成类似的工作。
当然,另一种方法是找到更快的哈希函数,但我假设 digest 包中的那个已经优化了。
【问题讨论】:
-
你的最终目标是什么?
-
如上所述,主要目标是避免使用 lapply、sapply、mapply,仅使用 data.table 语法非常快速地操作大文件的字符串 data.table(超过 1Go,基本上内存和速度允许的最大值....)。我希望能够将字符串列转换为 char 向量列到同一个表中,然后取它的一个子集,比如前 5 个单词或最后 5 个单词,我想计算这 5 个词,或者整个句子的散列......我已经使用 data.table 和 lapply 样式完成了 not ,它花了几分钟时间。太长了。
-
对于我的教育,从表 DU2 及其第二列(每个元素都是一个列表)你将如何重建原始文本(单个字符串)?
-
您是否尝试过正则表达式解决方案来提取前五个单词并直接对其进行哈希处理?
-
@AnandaMahto 什么是正则表达式?
标签: r string data.table strsplit