星期三, 九月 26, 2012

用Parallel和foreach包玩转并行计算


众所周知,在大数据时代R语言有两个弱项,其中一个就是只能使用单线程计算。但是在2.14版本之后,R就内置了parallel包,强化了R的并行计算能力。parallel包实际上整合了之前已经比较成熟的snow包和multicore包。前者已经在之前的文章中介绍过了,而后者无法在windows下运行,所以也就先不管了。parallel包可以很容易的在计算集群上实施并行计算,在多个CPU核心的单机上,也能发挥并行计算的功能。我们今天就来探索一下parallel包在多核心单机上的使用。

parallel包的思路和lapply函数很相似,都是将输入数据分割、计算、整合结果。只不过并行计算是用到了不同的cpu来运算。下面的例子是解决欧拉问题的第14个问题

星期六, 九月 22, 2012

使用GitHub进行版本控制的傻瓜方法


不论是团队合作还是单打独斗,代码和文档的版本控制是数据极客不可缺少的工具。高阶极客能随心所欲的用 linux终端+Git+编辑器完成这类任务。但是对于像本人一样的Git入门者来讲,图形工具还是略微让人心安一点。我们下面就来示例,用RStudio结合GitHub for Windows来完成这项任务。

首先你需要在GitHub中建立一个帐号,然后安装上述两种软件。试着登录GitHub for Windows看是否正常。此时你的本地库和远程库应该都是空的。之后在RStuio中点击新建项目,以后这个项目中的代码都会同步到远程代码库中。

星期五, 九月 21, 2012

抓取网页数据的几种套路


没有数据就没有乐趣。有的数据提供者心肠很好,会直接给出txt或是csv文档。这个时候我们可以直接在R里头用read.table()函数把数据读进来。

有的时候我们需要的数据在网页上以一个表格呈现,例如前面文章遇到过的地震数据。此时可以用XML包中的readHTMLTable()函数读取数据,后续再配合一些字符串处理一般就OK了。

如果你对R不大熟悉,抓取这些表格也有更方便的法子,就是利用Chrome的扩展。有两个扩展值得推荐使用:一个扩展叫作table capture,它会自动找出网页中的若干表格,你只需选择所需的那个将其拷贝到剪贴板即可,然后再用下面的命令就可以读入到R中。
data <- read.table('clipboard',T)

另一个扩展叫作scraper。先选择你所需要的部分内容,然后右键选择scraper similar也能抓取表格,不过它会存到一个google doc中去。在天朝这玩意儿不大方便。

有些数据不是以表格方式出现的,例如用XML或是JSON方式储存的数据。在R中都有对应的包来处理。下面的示例即是用XML包来处理XML数据。在此之先你需要有一点关于XML和XPath的知识,首先处理的对象是这样一个页面:http://www.w3schools.com/xml/plant_catalog.xml
library(XML)
xml.url <- "http://www.w3schools.com/xml/plant_catalog.xml"
# 解析xml页面
xmlfile <- xmlTreeParse(xml.url)
# 观察对象属性
class(xmlfile)
# 获取根结点
xmltop <- xmlRoot(xmlfile)
# 用xmlValue函数获取叶结点处的值
xmlValue(xmltop[[1]][[1]])
xmlValue(xmltop[['PLANT']][['COMMON']])
# xmlSApply类似于sapply函数,取出第一个子结点中的所有叶结点值
xmlSApply(xmltop[[1]],xmlValue)
# 进一步可以取出所有子结点中的叶结点值
plantcat <- xmlSApply(xmltop, function(x) xmlSApply(x, xmlValue))
# 将数据转为数据框
plantcat_df <- data.frame(t(plantcat),row.names=NULL)
plantcat_df[1:5,1:4]
有时候会遇到更为复杂的XML页面,此时的节点内含有参数值。如果要获取这些数据则需要使用getNodeSet()函数配合xmlValue()函数。当遇到更为复杂的数据,那我们只能用readLines读进来,再用字符串函数配合正则表达式来加以处理了。

参考资料:
http://www.omegahat.org/RSXML/Tour.pdf
http://www.stat.berkeley.edu/~statcur/Workshop2/Presentations/XML.pdf

星期三, 九月 19, 2012

如何在WIN下写一个简单的R包


虽然玩了一段时间的R,但很惭愧的是一直没有学着自己编写一个R包。一个是觉得R本身的包已经是浩如烟海了,另一个感觉好象写包非常麻烦。在参加完北京的这次统计夏令营后,看太云讲写包也不是太难。于是回来找了些资料尝试了一下,于是就形成了这篇笔记。

在WIN下面除了要安装好R之外,还要安装Rtools,这个在官网上可以找到。如果不写复杂的帮助文档和Vignette的话也不需要装MikTeX。此外在WIN中还要确保PATH的设置正确,这些可以在后面的参考文献中得到详细说明。在编写R包时还要知道自己的工作目录在哪,可以用getwd()函数来了解。

星期日, 九月 02, 2012

笨办法学R编程(6)

有时候用R来解一些Project Euler的题目会非常简单,今天就来三题连解(6、7、8)。题目就不再这里复述了,可以查看官方网站。用到函数和表达式大部分在前面都已经熟悉过了,不过还是会接触到一些新的函数。废话不多说直接上代码吧。

# Euler 6  
x <- 1:100
sum(x)^2 - sum(x^2)
 
# Euler 7 
 
n <- 0
i <- 1
m <- rep(0,10001)
while (n <10001) {
    if (findprime(i)) {
        n <- n +1 
        m[n] <- i}
    i <- i + 1
}
m[10001]
 
# 预备练习,熟悉一些字符串操作函数
text <- c('hello','world','I','love','code')
gsub('o',' ',text)
gsub('o','*',text)
gsub('o','',text)
 
(temp1 <-paste(text,collapse=' '))
paste(text,collapse='*')
paste(text,collapse='')
 
(temp2 <- strsplit(temp1," "))
class(temp2)
(temp3 <- unlist(strsplit(temp1," ")))
class(temp3)
 
# Euler 8 
 
web <- 'http://projecteuler.net/problem=8'
# 用readLines函数来抓取网页
raw <- readLines(web)
raw <- raw[54:73]
# 删除多余字符串
data <- gsub('<br />','',raw)
# 粘合成一个字符串
num <- paste(data,collapse='')
# 分割后转为数值向量
temp <- as.numeric(unlist(strsplit(num,'')))
 
p <- numeric()
for ( i in 1:(1000-4)) {
    p[i] <- prod(temp[i:(i+4)])
}
max(p)

第六题用R的向量化计算非常简单,第七题需要用到第二题中建立的findprime函数。第八题的解决是用字符串方法,先将那一长串数字作为字符串切开,再转为数值型向量,最后用循环求乘积。为了偷懒,是直接抓取的网页,没有输入那个长长的数字。