我想知道是否有关于R
中操作效率的任何文档,特别是与数据操作相关的文档。
例如:
C level
的数组中,你必须分配一个长度为n+1
的新数组并复制所有元素。开发人员可能不希望将自己绑定到特定的实现,但是有一些比猜测还要坚实的东西会很好。
另外,我知道主R
性能提示是尽可能使用向量操作而不是loops
。
apply
的各种风味怎么样? hidden loops
? matrices
与data frames
的对比?答案 0 :(得分:28)
在我致力于学习R之前,数据IO是我所研究的功能之一。无论好坏,这是我对这些问题的观察和解决方案/姑息治疗:
1。 R无法处理大数据(> 2 GB?)对我来说这是用词不当。默认情况下,公共数据输入功能会将数据加载到RAM中。不要愚蠢,但对我来说,这是一个功能而不是一个错误 - 任何时候我的数据都适合我的可用内存,这就是我想要的地方。同样,SQLite最受欢迎的功能之一是内存中选项 - 用户可以轻松选择将整个dB加载到RAM中。如果你的数据不适合内存,那么通过连接到常见的RDBMS系统(RODBC,RSQLite,RMySQL等),通过像filehash包这样的简单选项,通过R,可以非常容易地保存它。当前技术/实践的系统(例如,我可以推荐ff)。换句话说,R开发人员选择了一个明智的(也可能是最佳的)默认值,从中很容易选择退出。
<强> 2。 read.table的性能(read.csv,read.delim等),这是将数据导入R的最常用方法,只需选择性就可以提高5倍(通常我的经验更多)在一些read.table的默认参数中 - 在R的帮助(?read.table)中提到了对性能影响最大的参数。简而言之,R开发人员告诉我们,如果您为参数'colClasses','nrows','sep'和'comment.char'提供值(特别是,如果您知道您的文件以标题开头,则传入''第1行的数据,你会看到显着的性能提升。我发现这是真的。
以下是我用于这些参数的片段:
要获取数据文件中的行数(在调用read.table时将此代码段作为参数的参数提供,'nrows'):
as.numeric((gsub("[^0-9]+", "", system(paste("wc -l ", file_name, sep=""), intern=T))))
获取每列的类:
function(fname){sapply(read.table(fname, header=T, nrows=5), class)}
注意:您不能将此片段作为参数传递,您必须先调用它,然后传入返回的值 - 换句话说,调用函数,将返回的值绑定到变量,然后在调用read.table:
时,将变量作为值传递给参数'colClasses'第3。使用扫描。只需稍微麻烦一点,你可以做得更好(优化'read.table')使用'scan'而不是'read.table'('read.table'实际上只是'scan'的包装)。再一次,这很容易做到。我使用'scan'分别输入每一列,然后在R中构建我的data.frame,即df = data.frame(cbind(col1,col2,....))。
<强> 4。使用R的容器来代替普通文件格式的持久性(例如,'txt','csv')。 R的原生数据文件'.RData'是一种二进制格式,比压缩('.gz')txt数据文件略小。您可以使用保存(,)创建它们。使用加载()将其加载回R命名空间。与“read.table”相比,加载时间的差异是巨大的。例如,w / 25 MB文件(未压缩大小)
system.time(read.table("tdata01.txt.gz", sep=","))
=> user system elapsed
6.173 0.245 **6.450**
system.time(load("tdata01.RData"))
=> user system elapsed
0.912 0.006 **0.912**
<强> 5。注意数据类型通常可以提高性能并减少内存占用。这一点在从R中获取数据时可能更有用。这里要记住的关键点是默认情况下,R表达式中的数字被解释为双精度浮点,例如&gt; typeof(5)返回“double”。比较每个的合理大小的数组的对象大小,您可以看到重要性(使用object.size())。所以当你可以时强制转换为整数。
最后,'apply'系列函数(以及其他)不是“隐藏循环”或循环包装器。它们是用C实现的循环 - 性能差异很大。 [编辑:AWB正确地指出,虽然'sapply','tapply'和'mapply'是用C实现的,'apply'只是一个包装函数。
答案 1 :(得分:11)
这些东西会在列表中弹出,特别是在r-devel上。一个相当成熟的金块是例如matrix
操作往往比data.frame
操作更快。然后有一些很好的附加软件包--Matt的data.table软件包非常快,Jeff已经快速获得了xts索引。
但它“完全取决于” - 因此,您通常最好建议对您的特定代码进行配置。 R
有很多分析支持,所以你应该使用它。我的Intro to HPC with R tutorials有很多分析示例。
答案 2 :(得分:6)
我会尝试回来提供更多细节。如果您对一项操作相对于另一项操作的效率有任何疑问,您最好对自己的代码进行分析(如Dirk建议的那样)。 system.time()
函数是最简单的方法,尽管还有许多高级实用程序(例如Rprof,如文档here所述)。
对问题第二部分的快速回复:
各种口味的申请怎么样?那些只是隐藏的循环吗?
大多数情况下,apply函数只是循环,可能比for
语句慢。他们的主要好处是更清晰的代码。我发现的主要例外是lapply
,它可以更快,因为它直接用C编码。
那么矩阵与数据帧呢?
矩阵比数据帧更有效,因为它们需要更少的内存来存储。这是因为数据帧需要额外的属性数据。来自R Introduction:
出于多种目的,数据框可以被视为具有可能具有不同模式和属性的列的矩阵