经过一个周末的思考,我再把这个问题的解决方案优化了一步。
首先,各位同学别怪我在这个问题上的较真,因为“split”的问题是R语言数据处理中的一个普遍性问题,大神Hadley Wickham在其文章The Split-Apply-Combine Strategy for Data Analysis中就将Split-Apply-Combine的操作方法提升到了策略的高度,并因此有了plyr软件包。故而,将split的各种可能的瓶颈研究清晰,并提出针对性的优化方案,将终究会使大家未来的数据研究工作受益。
这次我的思路是从factor这一环节展开的。split()对factor参数与非factor参数的效率可谓天差地远:
由此,可知split环节的瓶颈其实是在as.factor环节。
而之前“ntsean”同学的发言让我无意中发现integer数据类型和double数据类型在as.factor环节也有着非常大的差别,比如:
至此,我推测数据类型是制约as.factor环节的一个重要因素,也是可以优化的一个重要方向。
我仔细观察了一下as.factor和factor两个函数,这两个函数都是用R语言编写的,并非用C语言。虽然我没有完全搞清楚其机理,但我猜测将integer和double的数据类型分开不同的程序处理仅仅是为了容错性上的考虑,而并非是技术性上的限制。
于是我将as.factor源程序中的一段抽取了出来,单独写了一个函数:
测试了一下,对double数据类型的操作是没有问题的,且效率提升了很多:
这下好了,我将在28楼的测试思路延续到新的含有factor.num()的解决方案上来,且我将每种方法均用30次测试,观测均值和中位数。第一种方法是“suimong”的lapply方法,第二种方法是“ntsean”的tapply方法,第三种是我用split.num()的解决办法(在本帖28楼有说明),第四种方法是本楼用factor.num()函数的方法。最后将结果检验了一下,没有问题。
OK,执行效率再进一步,在我的i3 CPU上基本0.6秒左右可以完成,不同的电脑上可能会更快。
通过这个例子,让我对R语言的优化有了很直观的感悟,其中一条,有些函数由于考虑容错性、兼容性的要求,往往代码会比较多,在一些比较极端的对优化要求很高的场合,如果针对具体数据的特点,去掉函数不必要的容错代码,有可能大幅提高执行效率。
不知我这一思路有没有错漏,多谢各位指正!
好了,以我的水平,已经在这个问题上发挥到极致了,现在我真的可以狗带了