数据集需要6-12个小时才能加载到R.更多大型数据集即将推出 我目前的进口过程显然还没有为他们做好准备。一旦它全部存在于数据中 框架尺寸不是问题;大多数操作只需几秒钟,所以我的 硬件可能不是问题。
注意:这个问题不是类似问题的重复,因为我已经实现了相关主题的大部分建议,例如:指定colClasses。
制表符分隔文本文件中的行如下所示:
20 -0.5 1 2 1 1 19 0 119 30 exp(-31.3778)
我已经定义了一些函数,这些函数一起循环遍历文件以加载 将数据转换为单个数据帧,然后将其另存为blob。这是一个过程 需要几个小时该过程可预测地减慢并在进展时使用更多内存; top表示R正在使用> 95%的CPU和(更重要的是?)>到数据文件的中途时,1.5 GB的实内存。
# get numeric log from character data
extract_log <- function(x) {
expr <- "exp\\((.*)\\)"
substring <- sub(expr, "\\1", x)
log <- as.numeric(substring)
return(log)
# reads .dat files into data frames
read_dat <- function(x, colClasses = c(rep("numeric", 10), "character")) {
df <- read.table(x, header = TRUE, sep = "\t", comment.char = "",
colClasses = colClasses)
df <- cbind(df, log_likelihood = sapply(df$likelihood, extract_log))
df$likelihood <- exp(df$log_likelihood)
# drop nat. log col, add log10 column shifting data to max = 0
df <- transform(df,
rlog_likelihood = log10(likelihood) - max(log10(likelihood)))
return(df)
}
# creates a single data frame from many .dat files
df_blob <- function(path = getwd(), filepattern = "*.dat$",
outfile = 'df_blob.r', ...) {
files <- list.files(path = path, pattern = filepattern, full.names = TRUE)
progress_bar <- {
txtProgressBar(min = 0, max = length(files),
title = "Progress",
style = 3)
}
df <- read_dat(files[1])
setTxtProgressBar(progress_bar, 1)
for (f in 2:length(files)) {
df <- rbind(df, read_dat(files[f]))
setTxtProgressBar(progress_bar, f)
}
close(progress_bar)
save(df, file = outfile)
}
所需时间从几小时减少到几秒钟。
使用shell脚本连接数据文件(所需时间约为12秒) 然后完全按照JD Long's answer to a related question中所述并按照blog post中的描述加载sqldf()。
Justin和Joran的评论显着提高了read.table()方法的效率,对于较小的数据集,这种方法应该可以正常工作。特别是Justin建议用rbind(df, read_dat(files[f]))
替换文件do.call(rbind, lapply(files, read_dat))
的循环,将执行时间减少大约2/3。其他建议的改进虽然仍然值得,但仍然较为温和。
答案 0 :(得分:5)
基本你遇到的一个大问题是read.table
不是很快。您可以通过设置colClasses
和nrows
进行调整,但在一天结束时,如果您的数据需要12小时加载,则需要使用不同的技术。
更快的方法是将数据导入数据库,然后将其读入R. JD Long演示了使用sqlite
数据库和sqldf
包in this answer的方法。 MonetDB和MonetDB.R
软件包专为快速完成此类工作而设计,值得研究。
正如Justin和Joran所发现的那样,使用rbind(df, read_dat(files[f]))
在循环中逐步增长数据框是一个巨大的瓶颈。在完整数据集适合RAM的情况下,使用do.call(files, read.table)
的更好的方法是。 (如果没有,请使用上述方法将所有内容删除到数据库中,然后将所需内容拉入R中。)