转载

一个简单并行运行R的方法

也许很多人对R都是既爱又恨。而人们常见的一个争论的主题就是并行计算,换一种更直接的说法:“当耗尽内存的时候我该如何在R中处理数据?”

一个简单并行运行R的方法

不必担心,实际上在R中有一些简易的方式去使用并行包!在这里也为大家介绍了一种:

选择一个库

首先做的事情是,你需要选择一个并行计算方案。在这里以doMC和plyr作为测试组合。

配置环境

当挑选完库之后,我们需要加载它们。导入之后,我们实际上需要“告诉”doMC我们机器上有多少核是可以使用的。要做到这一点可参考以下代码:

library(plyr)
library(doMC)
doMC::registerDoMC(cores=32) # or however many cores you have access to

如果你紧接着链接 ec2instances.info 时,你会发现32核等同于“104个ec2计算单位”

编者注:关于ec2可查看《 Amazon EC2 常见问题 》

处理数据

接下来,我们需要使用plyr来执行数据处理。plyr将自动的使用多核。这里你不需要用到doMC。

举个简单的例子来说,使用ddply函数来处理iris数据集,功能将暂停2秒。由于iris有三种类型,所以该命令将花费6秒。

system.time(ddply(iris, .(Species), function(x) {
Sys.sleep(2)
nrow(x)
}))
# user system elapsed
# 0.005 0.001 6.016

不过当你向ddply中添加.parallel = TRUE时,你发现了什么?

system.time(ddply(iris, .(Species), function(x) {
Sys.sleep(2)
nrow(x)
}, .parallel = TRUE))
# user system elapsed
# 0.018 0.015 2.031

正如结果所显示的那样,时间缩短为2秒。这意味着我们在同一时间内处理了iris的三个种类。而在plyr中,几乎所有的功能都有.parallel选项。

接下来我们再用 雅虎搜索市场广告竞价数据集 来测试一下,读取它并通过phrase_id和account_id对它进行划分:

headers <- c("timestamp", "phrase_id", "account_id", "price", "auto")
df <- read.table("./ydata-ysm-advertiser-bids-v1_0.txt")
colnames(df) <- headers
system.time(ddply(df, .(phrase_id, account_id), function(x) {
data.frame(mean=mean(x$price, na.rm=T), median=median(x$price, na.rm=T))
nrow(x)
}))
# user system elapsed
# 96.645 3.343 99.964

当我们使用并行处理相同的代码时,我们可以看到只有48.5秒:

system.time(ddply(df, .(phrase_id, account_id), function(x) {
data.frame(mean=mean(x$price, na.rm=T), median=median(x$price, na.rm=T))
nrow(x)
}, .parallel = TRUE))
# user system elapsed
# 94.228 16.267 48.553

最后

并行计算并没有想的那么困难和复杂,在R中保持并行的简单性可以让你不那么“头痛”。这里也列举了其他好的并行处理R包的方法。感兴趣的可以点击查看:

正文到此结束
Loading...