我有一些R脚本,我必须尽快在R中加载几个数据帧。这非常重要,因为读取数据是程序中最慢的部分。例如:从不同的数据框架绘图。我以sav(SPSS)格式获取数据,但我可以将其转换为建议的任何格式。遗憾的是,合并数据框不是一种选择。
加载数据的最快方法是什么?我在考虑以下几点:
read.spss
快得多attr
值(例如,来自Spss导入文件的 variable.labels )?或者这应该在一个单独的表中完成?欢迎任何其他想法。提前感谢您的每一个建议!
我根据你给出的答案做了一个小实验below,并且还添加了(24/01/2011)一个非常“hackish”但非常快速的解决方案,只加载一个特殊的几个变量/列二进制文件。后者似乎是我现在能想象的最快的方法,这就是为什么我编写了一个名为saves的小包来处理这个功能(05/03/2011:ver.0.3)。该套餐正在“重”开发,欢迎任何推荐!
我将很快在microbenchmark包的帮助下发布一个具有准确基准测试结果的小插图。
答案 0 :(得分:39)
感谢大家的提示和答案,我做了一些总结和实验。
请参阅下面的公共数据库(ESS 2008 in Hungary)进行一点测试。该数据库有1508个案例和508个变量,因此它可能是一个中型数据。这可能是(对我而言)进行测试的一个很好的例子,但当然特殊需要需要进行足够数据的实验。
从SPSS sav 文件中读取数据而不做任何修改:
> system.time(data <- read.spss('ESS_HUN_4.sav'))
user system elapsed
2.214 0.030 2.376
使用已转换的二进制对象加载:
> save('data',file='ESS_HUN_4.Rdata')
> system.time(data.Rdata <- load('ESS_HUN_4.Rdata'))
user system elapsed
0.28 0.00 0.28
尝试 csv :
> write.table(data, file="ESS_HUN_4.csv")
> system.time(data.csv <- read.csv('ESS_HUN_4.csv'))
user system elapsed
1.730 0.010 1.824
尝试使用“微调” csv 加载:
> system.time(data.csv <- read.table('ESS_HUN_4.csv', comment.char="", stringsAsFactors=FALSE, sep=","))
user system elapsed
1.296 0.014 1.362
同样使用包 sqldf ,这似乎加快了csv文件的速度:
> library(sqldf)
> f <- file("ESS_HUN_4.csv")
> system.time(bigdf <- sqldf("select * from f", dbname = tempfile(), file.format = list(header = T, row.names = F, sep="\t")))
user system elapsed
0.939 0.106 1.071
还要从运行在localhost上的MySQL数据库加载数据:
> library(RMySQL)
> con <- dbConnect(MySQL(), user='root', dbname='test', host='localhost', password='')
> dbWriteTable(con, "data", as.data.frame(data), overwrite = TRUE)
> system.time(data <- dbReadTable(con, 'data'))
user system elapsed
0.583 0.026 1.055
> query <-('SELECT * FROM data')
> system.time(data.sql <- dbGetQuery(con, query))
user system elapsed
0.270 0.020 0.473
在这里,我认为我们应该添加两个system.time
报告,因为在我们的案例中连接数据也很重要。如果我误解了什么,请评论。
但是让我们看看是否只查询一些变量,例如。在绘图时我们在大多数情况下不需要所有数据帧,只查询两个变量就足以创建一个很好的情节:
> query <-('SELECT c1, c19 FROM data')
> system.time(data.sql <- dbGetQuery(con, query))
user system elapsed
0.030 0.000 0.112
这真的很棒!当然只是在用dbReadTable
摘要:无需从二进制文件中读取整个数据,但只能从相同的数据库表中读取几列(或其他已过滤的数据)在一些特殊情况下加权。
测试环境:配备低端SSD的HP 6715b笔记本电脑(AMD X2 2Ghz,4 Gb DDR2)。
更新(2011年1月24日):我添加了一种相当hackish但非常“创造性”的方式来加载二进制对象的几列 - 这看起来比任何方法快得多检查上面。
请注意:代码看起来非常糟糕,但仍然非常有效:)
首先,我通过以下循环将data.frame的所有列保存到不同的二进制对象中:
attach(data)
for (i in 1:length(data)) {
save(list=names(data)[i],file=paste('ESS_HUN_4-', names(data)[i], '.Rdata', sep=''))
}
detach(data)
然后我加载了两列数据:
> system.time(load('ESS_HUN_4-c19.Rdata')) +
> system.time(load('ESS_HUN_4-c1.Rdata')) +
> system.time(data.c1_c19 <- cbind(c1, c19))
user system elapsed
0.003 0.000 0.002
这看起来像一个“超快”的方法! :)注意:它加载比上面的最快(加载整个二进制对象)方法快<100> 。
我已经制作了一个非常小的包(名为saves),如果感兴趣,可以查看github以获取更多详细信息。
更新(06/03/2011):我的小包(saves)的新版本已上传到CRAN,可以更快地保存和加载变量 - 如果只有用户只需要数据框或列表中可用变量的子集。有关详细信息或vignette上的my homepage,请参阅软件包源代码中的{{3}},并让我介绍一些基准测试的好框图:
此框图显示了使用保存包从基数load
加载read.table
和read.csv
或read.spss
的变量子集的好处。来自国外或sqldf
或RMySQL
个包裹。
答案 1 :(得分:19)
这取决于您想要做什么以及如何进一步处理数据。在任何情况下,只要您始终需要相同的数据集,从二进制R对象加载总是会更快。这里的限制速度是硬盘的速度,而不是R.二进制形式是工作空间中数据框的内部表示,因此不再需要转换。
任何类型的文本文件都是一个不同的故事,因为你总是包含一个开销:每次读入文本文件时,数据都必须转换为二进制R对象。我会忘记他们。它们仅用于将数据集从一个应用程序移植到另一个应用程序。
如果您需要不同的数据部分或不同组合的不同子集,则设置MySQL后端非常有用。特别是在处理大型数据集时,您无需在开始选择行/列之前加载整个数据集这一事实可以获得相当长的时间。但这仅适用于大型数据集,因为读取二进制文件比搜索数据库要快得多。
如果数据不是太大,您可以将不同的数据帧保存在一个RData文件中,这样您就有机会简化一些事情。我经常在列表或单独的环境中有一组数据帧(有关一些简单示例,另请参阅?environment
)。这允许lapply
/ eapply
解决方案一次处理多个数据帧。
答案 2 :(得分:1)
我对RMySQL很满意。我不确定我的问题是否正确,但标签应该不是问题。有几个便捷函数只使用默认的SQL表和行名,但当然你可以使用一些SQL语句。
我想说(除了证明喧嚣的大数据集之外)使用RMySQL的一个主要原因是熟悉SQL语法而不是R数据杂耍函数。我个人更喜欢GROUP BY而不是聚合。请注意,使用R内部的存储过程并不是特别有效。
底线......设置MySQL本地主机并不是太费劲 - 试一试!我无法确切地说出速度,但我觉得它有可能更快。但是,我会尝试回到这里。
编辑:这是测试......获胜者是:spacedman
# SQL connection
source("lib/connect.R")
dbQuery <- "SELECT * FROM mytable"
mydata <- dbGetQuery(con,dbQuery)
system.time(dbGetQuery(con,dbQuery))
# returns
#user system elapsed
# 0.999 0.213 1.715
save.image(file="speedtest.Rdata")
system.time(load("speedtest.Rdata"))
#user system elapsed
#0.348 0.006 0.358
这里的文件大小只有大约1 MB。 MacBook Pro 4 GB Ram 2.4 GHZ Intel Core Duo,Mac OSX 10.6.4,MySQL 5.0.41 从来没有尝试过,因为我通常使用更大的数据集,加载不是问题,而是处理......如果有时间问题的话。 Q为+1!
答案 3 :(得分:1)
如果可能的话,将数据转换为csv
或其他&#34;简单&#34;尽可能快地进行阅读的格式(参见Joris&#39;答案)。我使用csv
函数导入apply
个文件 en masse ,类似于:
list.of.files <- as.list(list.files("your dir"))
lapply(list.of.files, FUN = function(x) {
my.object <- read.table(...) # or some other function, like read.spss
})