R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。
R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。
要成为有理想的极客,我们不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让我们一起动起来吧,开始R的极客理想。
关于作者:
- 张丹(Conan), 程序员Java,R,PHP,Javascript
- weibo:@Conan_Z
- blog: http://blog.fens.me
- email: bsspirit@gmail.com
转载请注明出处:
http://blog.fens.me/r-package-chinaweather/
前言
本节将继续R语言天气可视化应用一文的内容,把我们已经完成的R语言程序,封装成R语言程序包。这个看起来简单的任务,其实要花很多的时间来处理细节。整个的R包开发过程,将按照文章在巨人的肩膀前行 催化R包开发的流程进行,为了保证check()函数的顺利执行,代码有多处改动。
目录
- 构建项目
- 静态数据
- 编写功能代码
- 项目配置文件
- 调试程序
- 程序打包
1. 构建项目
在R语言天气可视化应用一文,我们写的R程序都在Window中完成,由于R的跨平台代码有兼容性的问题,我们的应用程序最终将在Linux中发布,所以为了减少发布时不必要的麻烦,我们转到Linux系统中完成R包的开发。
本节的系统环境
- Linux: Ubuntu Server 12.04.2 LTS 64bit
- R: 3.1.1 x86_64-pc-linux-gnu (64-bit)
- RStudio-Server 0.97.551
在巨人的肩膀前行 催化R包开发文中,我们其实已经创建好了chinaWeather项目,那么R包的开发将继续在这个项目中进行。进入chinaWeather项目的目录,我单独开一个Git分支,进行本节的R包开发。
~ cd /home/conan/R/chinaWeather # 进入项目目录
~ git branch app # 新建分支,名为app
~ git checkout app # 切换到分支app
~ git branch # 查看当查的分支
* app
master
查看Linux系统中,R语言环境变量的设置,字符集是特别要处理的部分。
> sessionInfo()
R version 3.1.1 (2014-07-10)
Platform: x86_64-pc-linux-gnu (64-bit)
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
[3] LC_TIME=zh_CN.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=zh_CN.UTF-8 LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=zh_CN.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=zh_CN.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
环境准备就绪,下面就是开始R包开的工作了。
2. 静态数据
在开始写R包代码之前,我们需要先来整理一下静态数据。 这个项目中,静态数据包括了地图数据、WOEID映射数据、天气概况的映射数据、中英文图片可视化数据、测试数据集。对于普通的R应用程序来说可以用CSV格式文件保存在本地,但对于R包项目来说,最好是封装成rda的数据文件,随R包一起打包发布。
首先,我们就要对这些静态数据文件进行整理,新建目录metadata,用于存储原始CSV文件和地图文件。
~ mkdir /home/conan/R/chinaWeather/metadata # 新建目录,并把原数据文件复制到metadata目录
~ ls -l /home/conan/R/chinaWeather/metadata # 查看metadata目录
-rw-rw-r-- 1 conan conan 3396 10月 4 22:14 20141001.csv # 测试数据集
-rw-r--r-- 1 conan conan 754 2月 5 2013 ADCODE99.csv # ADCODE99与省份中文映射数据
-rw-r--r-- 1 conan conan 1418 2月 6 2013 code.csv # 天气概况映射数据
-rw-r--r-- 1 conan conan 214 2月 6 2013 labelcode.csv # 天气概况映射数据
drwxr-xr-x 2 conan conan 4096 4月 23 2013 mapdata # 地图数据目录
-rw-rw-r-- 1 conan conan 1900 2月 4 2013 WOEID.csv # WOEID映射数据
~ ls -l /home/conan/R/chinaWeather/metadata/mapdata # 查看地图数据文件
-rw-r--r-- 1 conan conan 86283 4月 10 1999 bou2_4p.dbf
-rw-r--r-- 1 conan conan 1508752 4月 10 1999 bou2_4p.shp
-rw-r--r-- 1 conan conan 7500 4月 10 1999 bou2_4p.shx
把静态数据转换为rda格式的文件,存储在data目录中。
~ mkdir /home/conan/R/chinaWeather/data # 新建目录data
~ R # 启动R语言程序。
2.1 WOEID数据文件 WOEID.rda
对WOEID数据进行处理,把adcode99代码合并到WOEID数据集中,合并WOEID.csv文件和ADCODE99.csv文件的数据,生成WOEID.rda的文件。
> WOEID<-read.csv(file="metadata/WOEID.csv",header=FALSE,fileEncoding="utf-8", encoding="utf-8") # 加载WOEID数据集
> names(WOEID)<-c("en","woeid","zh",'prov','long','lat')
> adcode99<-read.csv(file="metadata/ADCODE99.csv",header=TRUE,fileEncoding="utf-8", encoding="utf-8") # 加载ADCODE99数据集
> fc<-function(row){
+ code<-adcode99$ADCODE99[which(row[4]==as.character(adcode99$prov))]
+ if(length(code)==0)code=0
+ code
+ }
> WOEID<-cbind(WOEID,adcode99=unlist(apply(WOEID,1,fc))) # 合并数据集
> save(WOEID,file="data/WOEID.rda") # 生成WOEID.rda文件
> WOEID # 合并后的WOEID数据集
en woeid zh prov long lat adcode99
1 beijing 2151330 北京 北京市 116.46667 39.90000 110000
2 shanghai 2151849 上海 上海市 121.48333 31.23333 310000
3 tianji 2159908 天津 天津市 117.18333 39.15000 120000
4 chongqing 20070171 重庆 重庆市 106.53333 29.53333 500000
5 harbin 2141166 哈尔滨 黑龙江省 126.68333 45.75000 230000
6 changchun 2137321 长春 吉林省 125.31667 43.86667 220000
7 shenyang 2148332 沈阳 辽宁省 123.40000 41.83333 210000
8 hohhot 2149760 呼和浩特 内蒙古自治区 111.80000 40.81667 150000
9 shijiazhuang 2171287 石家庄 河北省 114.46667 38.03333 130000
10 wulumuqi 26198317 乌鲁木齐 新疆维吾尔自治区 87.60000 43.80000 650000
11 lanzhou 2145605 兰州 甘肃省 103.81667 36.05000 620000
12 xining 2138941 西宁 青海省 101.75000 36.63333 630000
13 xian 2157249 西安 陕西省 108.90000 34.26667 610000
14 yinchuan 2150551 银川 宁夏回族自治区 106.26667 38.33333 640000
15 zhengzhou 2172736 郑州 河南省 113.70000 34.80000 410000
16 jinan 2168327 济南 山东省 117.00000 36.63333 370000
17 taiyuan 2154547 太原 山西省 112.56667 37.86667 140000
18 hefei 2127866 合肥 安徽省 117.30000 31.85000 340000
19 wuhan 2163866 武汉 湖北省 114.35000 30.61667 420000
20 changsha 26198213 长沙 湖南省 113.00000 28.18333 430000
21 nanjing 2137081 南京 江苏省 118.83333 32.03333 320000
22 chengdu 2158433 成都 四川省 104.08333 30.65000 510000
23 guiyang 2146703 贵阳 贵州省 106.70000 26.58333 520000
24 kunming 2160693 昆明 云南省 102.68333 25.00000 530000
25 nanning 2166473 南宁 广西壮族自治区 108.33333 22.80000 450000
26 lasa 26198235 拉萨 西藏自治区 91.16667 29.66667 540000
27 hangzhou 2132574 杭州 浙江省 120.15000 30.23333 330000
28 nanchang 26198151 南昌 江西省 115.86667 28.68333 360000
29 guangzhou 2161838 广州 广东省 113.25000 23.13333 440000
30 fuzhou 2139963 福州 福建省 119.30000 26.08333 350000
31 taipei 2306179 台北 台湾省 121.51667 25.05000 710000
32 haikou 2162779 海口 海南省 110.33333 20.03333 460000
33 hongkong 24865698 香港 香港特别行政区 114.16667 22.30000 810000
34 macau 20070017 澳门 澳门特别行政区 113.50000 22.20000 0
我们看到WOEID数据集包括了中文字符,而R语言的rda的规范中,要求不能包括ASCII以外的字符集了。在执行check()检查的过程中,就会遇到非法字符集的警告错误。因此,就需要对中文数据集进行特殊转码处理,把中文字符统一转码成unicode来表示,如 北京 unicode转码后表示为 \u5317\u4eac。当数据集用于中文显示的时候,需要再反转unicode到中文,这样就可以中文与R语言程序的兼容了。
对WOEID的数据集转码处理,我们需要用到stringi包。
> install.packages("stringi") # 安装stringi包
> library("stringi") # 加载stringi包
通过 stri_escape_unicode()函数,对WOEID数据集的zh和prov列的中文进行unicode转码。
> WOEID$prov<-stri_escape_unicode(WOEID$prov) # 对WOEID$prov列转码
> WOEID$zh<-stri_escape_unicode(WOEID$zh) # 对WOEID$zh列转码
> save(WOEID,file="data/WOEID.rda",compress=TRUE) # 保存数据集
> head(WOEID) # 查看转码后的WOEID数据集
en woeid zh prov long lat adcode99 adcode99
1 beijing 2151330 \\u5317\\u4eac \\u5317\\u4eac\\u5e02 116.4667 39.90000 110000 110000
2 shanghai 2151849 \\u4e0a\\u6d77 \\u4e0a\\u6d77\\u5e02 121.4833 31.23333 310000 310000
3 tianji 2159908 \\u5929\\u6d25 \\u5929\\u6d25\\u5e02 117.1833 39.15000 120000 120000
4 chongqing 20070171 \\u91cd\\u5e86 \\u91cd\\u5e86\\u5e02 106.5333 29.53333 500000 500000
5 harbin 2141166 \\u54c8\\u5c14\\u6ee8 \\u9ed1\\u9f99\\u6c5f\\u7701 126.6833 45.75000 230000 230000
6 changchun 2137321 \\u957f\\u6625 \\u5409\\u6797\\u7701 125.3167 43.86667 220000 220000
我们再试一下,把unicode的数据转码成原来的中文字符,通过stri_unescape_unicode()函数实现。
> head(stri_unescape_unicode(WOEID$prov))
[1] "北京市" "上海市" "天津市" "重庆市" "黑龙江省" "吉林省"
> head(stri_unescape_unicode(WOEID$zh))
[1] "北京" "上海" "天津" "重庆" "哈尔滨" "长春"
转码的操作正常,所以在遇到非ASCII的字符集,我们就可以用这种方式进行转换了。
2.2 地图数据文件 chinaMap.rda
对地图数据进行处理,加载原始地图数据,生成chinaMap.rda文件。在chinaMap对象中,NAME列也是中文字符,但Linux系统在加载地图数据时,字符编码已经被修改,我们不能看到编码类型,所以这里不能通过上面所说的unicode转码。NAME列数据,我们刚好用不到,一种简单的操作方法就是将他从数据集中去掉。
> library(maps)
> library(mapdata)
> library(maptools)
> chinaMap<-readShapePoly('metadata/mapdata/bou2_4p.shp') # 加载地图数据
> head(chinaMap$NAME) # NAME列,非ASCII编码
[1] \xba\xda\xc1\xfa\xbd\xadʡ
[2] \xc4\xda\xc3ɹ\xc5\xd7\xd4\xd6\xce\xc7\xf8
[3] \xd0½\xaeά\xce\xe1\xb6\xfb\xd7\xd4\xd6\xce\xc7\xf8
[4] \xbc\xaa\xc1\xd6ʡ
[5] \xc1\xc9\xc4\xfeʡ
[6] \xb8\xca\xcb\xe0ʡ
33 Levels: \xb0\xb2\xbb\xd5ʡ ... \xd6\xd8\xc7\xec\xca\xd0
> chinaMap<-chinaMap[,c(1:6)] # 去掉NAME列
> save(chinaMap,file="data/chinaMap.rda",compress='xz') # 生成chinaMap.rda文件
2.3 中英文图片可视化数据 props.rda
对于可视化的图片输出时,用于中文名的字段显示,生成props.rda文件,中文编码通过转成unicode进行处理。
> props<-data.frame(
+ key=c('high','low'),
+ zh=c('中国各省白天气温','中国各省夜间气温'),
+ en=c('Daytime Temperature','Nighttime Temperature')
+ )
> props$zh<-stri_escape_unicode(props$zh)
> save(props,file="data/props.rda",compress=TRUE)
2.4 测试数据集weather20141001.rda
以2014年10月01日的天气数据集,做为一个demo数据集,生成weather20141001.rda文件,中文编码通过转成unicode进行处理。
> weather20141001<-read.csv(file="metadata/20141001.csv",header=TRUE,fileEncoding="utf-8", encoding="utf-8") # 加载数据庥
> weather20141001$prov<-stri_escape_unicode(weather20141001$prov) # 对weather20141001$prov列转码
> weather20141001$zh<-stri_escape_unicode(weather20141001$zh) # 对weather20141001$zh列转码
> save(weather20141001,file="data/weather20141001.rda",compress=TRUE) # 生成weather20141001.rda文件。
查看data目录下面的文件列表,生成了4个静态数据集文件。
> dir('data')
[1] "WOEID.rda" "chinaMap.rda" "props.rda" "weather20141001.rda"
我们把所有的静态数据集先整理好,下面的R包代码,就可以直接使用这些静态数据集了。
3. 编写功能代码
按照函数功能的不同,我们定义4个文件来描述这些函数。
- getData.R,用于定义爬去数据的函数。
- render.R,用于静态图片可视化渲染的函数。
- chinaWeather.R,用于定义各种工具函数。
- chinaWeather-packages.R,用于定义R包内的数据集。
3.1 文件 getData.R
新建文件getData.R,用于爬取数据和XML文档解析,文件中定义了3个函数。
- getWeatherFromYahoo(), 从Yahoo的开放数据源,获取天气数据。
- getWeatherByCity(), 通过城市英文名,获取当前城市的天气数据。
- getWeather(), 获取中国省会城市的天气数据,在WOEID数据集中定义的城市。
~ vi R/getData.R
#' Get weather data from Yahoo openAPI.
#'
#' @importFrom RCurl getURL
#' @importFrom XML xmlTreeParse getNodeSet xmlGetAttr
#' @param woeid input a yahoo woeid
#' @return data.frame weather data
#' @keywords weather
#' @export
#' @examples
#' \dontrun{
#' getWeatherFromYahoo()
#' getWeatherFromYahoo(2151330)
#' }
getWeatherFromYahoo<-function(woeid=2151330){
url<-paste('http://weather.yahooapis.com/forecastrss?w=',woeid,'&u=c',sep="")
doc = xmlTreeParse(getURL(url),useInternalNodes=TRUE)
ans<-getNodeSet(doc, "//yweather:atmosphere")
humidity<-as.numeric(sapply(ans, xmlGetAttr, "humidity"))
visibility<-as.numeric(sapply(ans, xmlGetAttr, "visibility"))
pressure<-as.numeric(sapply(ans, xmlGetAttr, "pressure"))
rising<-as.numeric(sapply(ans, xmlGetAttr, "rising"))
ans<-getNodeSet(doc, "//item/yweather:condition")
code<-as.numeric(sapply(ans, xmlGetAttr, "code"))
ans<-getNodeSet(doc, "//item/yweather:forecast[1]")
low<-as.numeric(sapply(ans, xmlGetAttr, "low"))
high<-as.numeric(sapply(ans, xmlGetAttr, "high"))
print(paste(woeid,'==>',low,high,code,humidity,visibility,pressure,rising))
return(as.data.frame(cbind(low,high,code,humidity,visibility,pressure,rising)))
}
#' Get one city weather Data.
#'
#' @param en input a English city name
#' @param src input data source
#' @return data.frame weather data
#' @keywords weather
#' @export
#' @examples
#' \dontrun{
#' getWeatherByCity()
#' getWeatherByCity(en="beijing")
#' }
getWeatherByCity<-function(en="beijing",src="yahoo"){
woeid<-getWOEIDByCity(en)
if(src=="yahoo"){
return(getWeatherFromYahoo(woeid))
}else{
return(NULL)
}
}
#' Get all of city weather Data.
#'
#' @param lang input a language
#' @param src input data source
#' @return data.frame weather data
#' @keywords weather
#' @export
#' @examples
#' \dontrun{
#' getWeather()
#' }
getWeather<-function(lang="en",src="yahoo"){
cities<-getCityInfo(lang)
wdata<-do.call(rbind, lapply(cities$woeid,getWeatherFromYahoo))
return(cbind(cities,wdata))
}
3.2 文件 render.R
新建文件render.R,用于数据处理和静态图片可视化渲染,文件中定义了5个函数。
- getColors(),用于根据天气情况匹配不同的颜色
- drawBackground(),画出背景
- drawDescription(),画出文字描述
- drawLegend(),画出图例
- drawTemperature(),画出气温及地图结合
~ vi R/render.R
#' match the color with ADCODE99.
#'
#' @param temp the temperature
#' @param breaks cut the numbers
#' @return new color vector
#' @keywords color
getColors<-function(temp,breaks){
f=function(x,y) ifelse(x %in% y,which(y==x),0)
colIndex=sapply(chinaMap$ADCODE99,f,WOEID$adcode99)
arr <- findInterval(temp, breaks)
arr[which(is.na(arr))]=19
return(arr[colIndex])
}
#' Draw the background.
#'
#' @param title the image's title
#' @param date the date
#' @param lang the language zh or en
drawBackground<-function(title,date,lang='zh'){
text(100,58,title,cex=2)
text(105,54,format(date,"%Y-%m-%d"))
#text(98,65,paste('chinaweatherapp','http://apps.weibo.com/chinaweatherapp'))
#text(120,-8,paste('provided by The Weather Channel',format(date, "%Y-%m-%d %H:%M")),cex=0.8)
}
#' Draw the description.
#'
#' @importFrom stringi stri_unescape_unicode
#' @param data daily data
#' @param temp the temperature
#' @param lang the language zh or en
drawDescription<-function(data,temp,lang='zh'){
rows<-1:nrow(data)
x<-ceiling(rows/7)*11+68
y<-17-ifelse(rows%%7==0,7,rows%%7)*3
fontCols<-c("#08306B","#000000","#800026")[findInterval(temp,c(0,30))+1]
if(lang=='zh'){
txt<-stri_unescape_unicode(data$zh)
text(x,y,paste(txt,temp),col=fontCols)
}else{
text(x,y,paste(data$en,temp),col=fontCols)
}
#text(x,y,bquote(paste(.(data$en),.(temp),degree,C)),col=fontCols)
}
#' Draw the legend.
#'
#' @param breaks cut the numbers
#' @param colors match the color
drawLegend<-function(breaks,colors){
breaks2 <- breaks[-length(breaks)]
par(mar = c(5, 0, 15, 10))
image(x=1, y=0:length(breaks2),z=t(matrix(breaks2)),col=colors[1:length(breaks)-1],axes=FALSE,breaks=breaks,xlab="",ylab="",xaxt="n")
axis(4, at = 0:(length(breaks2)), labels = breaks, col = "white", las = 1)
abline(h = c(1:length(breaks2)), col = "white", lwd = 2, xpd = FALSE)
}
#' Draw temperature picture.
#'
#' @importFrom RColorBrewer brewer.pal
#' @importFrom stringi stri_unescape_unicode
#' @import maptools
#' @param data daily data
#' @param lang language
#' @param type low or high
#' @param date the date
#' @param output output a file or not
#' @param path image output position
#' @export
drawTemperature<-function(data,lang='zh',type='high',date=Sys.time(),output=FALSE,path=''){
colors <- c(rev(brewer.pal(9,"Blues")),"#ffffef",brewer.pal(9,"YlOrRd"),"#500000")
breaks=seq(-36,44,4)
if(type=='high') {
temp<-data$high
ofile<-paste(format(date,"%Y%m%d"),"_day.png",sep="")
}else{
temp<-data$low
ofile<-paste(format(date,"%Y%m%d"),"_night.png",sep="")
}
if(lang=='zh'){
title<-stri_unescape_unicode(props[which(props$key=='high'),]$zh)
}else{
title<-props[which(props$key=='high'),]$en
}
if(output)png(filename=paste(path,ofile,sep=''),width=600,height=600)
layout(matrix(data=c(1,2),nrow=1,ncol=2),widths=c(8,1),heights=c(1,2))
par(mar=c(0,0,3,10),oma=c(0.2,0.2,0.2,0.2),mex=0.3)
plot(chinaMap,border="white",col=colors[getColors(temp,breaks)])
points(data$long,data$lat,pch=19,col=rgb(0,0,0,0.3),cex=0.8)
drawBackground(title,date,lang)
drawDescription(data,temp,lang)
drawLegend(breaks,colors)
}
3.3 文件 chinaWeather.R
修改文件chinaWeather.R,用于定义各种工具函数,文件中定义了3个函数。
- filename(),根据日期定义文件名称。
- getWOEIDByCity(),通过城市名获得WOEID代码。
- getCityInfo(),查看所有城市的信息,在WOEID数据集中定义的城市。
#' Define a filename from current date.
#'
#' @param date input a date type
#' @return character a file name
#' @keywords filename
#' @export
#' @examples
#' \dontrun{
#' filename()
#' filename(as.Date("20110701",format="%Y%m%d"))
#' }
filename<-function(date=Sys.time()){
paste(format(date, "%Y%m%d"),".csv",sep="")
}
#' Get WOEID of Yahoo By City Name
#'
#' @param en input a English city name
#' @return integer WOEID
#' @keywords WOEID
#' @export
#' @examples
#' \dontrun{
#' getWOEIDByCity()
#' getWOEIDByCity(en="beijing")
#' }
getWOEIDByCity<-function(en="beijing"){
return(WOEID$woeid[which(WOEID$en==en)])
}
#' Get all of city info
#'
#' @param lang input a language
#' @return data.frame city info
#' @keywords language
#' @export
#' @examples
#' \dontrun{
#' getCityInfo()
#' getCityInfo(lang="en")
#' getCityInfo(lang="zh")
#' }
getCityInfo<-function(lang="en"){
if(lang=="en")return(WOEID[-c(3,4)])
if(lang=="zh")return(WOEID[-c(4)])
}
3.4 文件 chinaWeather-package.R
新建文件chinaWeather-package,用于定义R包的说明和内置数据集。
- NULL,关于chinaWeather包的定义说明
- 'WOEID',WOEID数据集的描述
- 'chinaMap',chinaMap数据集的描述
- 'props',props数据集的描述
- 'weather20141001',weather20141001数据集的描述
#' China Weather package.
#'
#' a visualized package for china Weather
#'
#' @name chinaWeather-package
#' @aliases chinaWeather
#' @docType package
#' @title China Weather package.
#' @keywords package
NULL
#' The yahoo code for weather openAPI.
#'
#' @name WOEID
#' @description The yahoo code for weather openAPI.
#' @docType data
#' @format A data frame
#' @source \url{https://developer.yahoo.com/geo/geoplanet/guide/concepts.html}
'WOEID'
#' China Map.
#'
#' @name chinaMap
#' @description China Map Dataset.
#' @docType data
#' @format A S4 Object.
'chinaMap'
#' Charset for Chinease and English.
#'
#' @name props
#' @description Charset.
#' @docType data
#' @format A data frame
'props'
#' Dataset for 20141001.
#'
#' @name weather20141001
#' @description A demo dataset.
#' @docType data
#' @format A data frame
#' @source \url{http://weather.yahooapis.com/forecastrss?w=2151330}
'weather20141001'
4. 项目配置文件
我们在chinaWeather项目中,增加了好几个函数定义,同时增加了5包的依赖,那么项目配置文件也需要做相当的修改。
需要修改的文件有3个。
- DESCRIPTION,项目描述文件,用于项目全局的配置。
- NAMESPACE,命令空间文件,用于函数的访问权限控制。
- .Rbuildignore,在打包时,用于排除不参与打包的文件。
4.1 修改文件 DESCRIPTION
DESCRIPTION文件,用于全局项目配置,在Imports选项中定义了5个包的依赖,并增加LazyData的选项。
Package: chinaWeather
Type: Package
Title: a visualized package for china Weather
Version: 0.1
Authors@R: "Dan Zhang [aut, cre]"
Description: a visualized package for china Weather
Depends:
R (>= 3.1.1)
Imports:
RCurl,
XML,
maptools,
RColorBrewer,
stringi
LazyData: TRUE
License: GPL-2
Date: 2014-09-28
4.2 修改文件 NAMESPACE
NAMESPACE文件用于函数的访问控制,我们先手动定义需要输出的函数用,稍后在运行roxygen2包的document()函数,NAMESPACE文件会自动更新。
export(drawTemperature)
export(filename)
export(getCityInfo)
export(getWOEIDByCity)
export(getWeather)
export(getWeatherByCity)
export(getWeatherFromYahoo)
4.3 新建文件 .Rbuildignore
在打包的时候,可以排除不相关的文件,比如 metadata目录 和 .gitignore文件等。
.gitignore
dist
metadata
^.*\.Rproj$
^\.Rproj\.user$
README*
NEWS*
FAQ*
我们把R语言代码、函数注释和配置文件,都修改完成了,下面开始调试程序。
5. 调试程序
用devtools包的工具函数,调试程序还是比较简单的。
> library(devtools) # 加载devtools包
> load_all("/home/conan/R/chinaWeather") # 加载chinaWeather项目
Loading chinaWeather
> data(package="chinaWeather") # 查看chinaWeather的数据集
Data sets in package ‘chinaWeather’:
WOEID
chinaMap
props
weather20141001
调用weather20141001测试数据集,画出2014年10月01日的白天气温静态图。
> date<-as.Date(as.character(20141001), format = "%Y%m%d")
> drawTemperature(weather20141001,date=date)
再画出2014年10月01日的英文的夜间气温图。
> drawTemperature(weather20141001,type='low',date=date,lang='en')
生成的可视化图片,完成符合我们的要求。这里偷懒一下,暂时跳过单元测试了。之前我们在代码上已经加了注释,接下就通过roxygen2包生成文档。
> library(roxygen2)
> roxygenize("/home/conan/R/chinaWeather")
First time using roxygen2 4.0. Upgrading automatically...
Writing NAMESPACE
Writing chinaWeather-package.Rd
Writing WOEID.Rd
Writing chinaMap.Rd
Writing props.Rd
Writing weather20141001.Rd
Writing filename.Rd
Writing getWOEIDByCity.Rd
Writing getCityInfo.Rd
Writing getWeatherFromYahoo.Rd
Writing getWeatherByCity.Rd
Writing getWeather.Rd
Writing getColors.Rd
Writing drawBackground.Rd
Writing drawDescription.Rd
Writing drawLegend.Rd
Writing drawTemperature.Rd
文件NAMESPACE也被同时更新了,通过自动化的方式,我们又可以少维护一个文件了。运行一切正常,最后就是程序打包。
6. 程序打包
我们把用于打包的程序放到dist目录中,新建dist目录。
~ mkdir /home/conan/R/chinaWeather/dist # 新建目录dist
6.1 程序打包
执行打包函数build(),存在于dist目录。
> build("/home/conan/R/chinaWeather",path="dist")
'/usr/lib/R/bin/R' --vanilla CMD build '/home/conan/R/chinaWeather' --no-manual --no-resave-data
* checking for file ‘/home/conan/R/chinaWeather/DESCRIPTION’ ... OK
* preparing ‘chinaWeather’:
* checking DESCRIPTION meta-information ... OK
* checking for LF line-endings in source and make files
* checking for empty or unneeded directories
* looking to see if a ‘data/datalist’ file should be added
* building ‘chinaWeather_0.1.tar.gz’
[1] "dist/chinaWeather_0.1.tar.gz"
在本地安装chinaWeather包。
~ R CMD INSTALL dist/chinaWeather_0.1.tar.gz
* installing to library ‘/home/conan/R/x86_64-pc-linux-gnu-library/3.1’
* installing *source* package ‘chinaWeather’ ...
** R
** data
*** moving datasets to lazyload DB
** inst
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
* DONE (chinaWeather)
加载chinaWeather包,下载当天的天气数据,并可视化输出,如图5-20所示。
> library(chinaWeather)
> data<-getWeather(lang='zh')
[1] "2151330 ==> 8 19 28 32 NA 1023.5 0"
[1] "2151849 ==> 17 25 34 51 9.99 1015.92 0"
[1] "2159908 ==> 9 19 30 35 9.99 1015.92 0"
[1] "20070171 ==> 16 26 28 60 NA 1021.7 0"
[1] "2141166 ==> 0 14 34 22 9.99 1015.92 0"
[1] "2137321 ==> 2 16 30 27 9.99 1015.92 2"
[1] "2148332 ==> 6 18 28 35 9.99 1015.92 0"
[1] "2149760 ==> 3 15 30 31 9.99 1015.92 0"
[1] "2171287 ==> 9 22 34 27 9.99 1015.92 2"
[1] "26198317 ==> 9 18 34 55 9.99 1015.92 2"
[1] "2145605 ==> 6 21 32 39 NA 812.73 0"
[1] "2138941 ==> 3 19 32 34 NA 745.01 0"
[1] "2157249 ==> 12 26 32 44 NA 1022 0"
[1] "2150551 ==> 8 21 32 29 16 1022.7 0"
[1] "2172736 ==> 13 24 20 64 1.5 1015.92 0"
[1] "2168327 ==> 9 21 32 44 15 1022.3 0"
[1] "2154547 ==> 6 20 34 26 9.99 1015.92 2"
[1] "2127866 ==> 15 26 34 42 9.99 1015.92 2"
[1] "2163866 ==> 17 28 28 55 4.01 1019.8 0"
[1] "26198213 ==> 17 28 34 33 9.99 1015.92 0"
[1] "2137081 ==> 14 25 30 54 9.99 1015.92 2"
[1] "2158433 ==> 18 28 30 37 9.99 1015.92 2"
[1] "2146703 ==> 11 22 28 53 9.99 1015.92 2"
[1] "2160693 ==> 8 20 30 49 9.99 1015.92 2"
[1] "2166473 ==> 19 29 30 74 9 982.05 2"
[1] "26198235 ==> -1 16 32 20 NA 643.41 0"
[1] "2132574 ==> 16 25 34 39 9.99 1015.92 0"
[1] "26198151 ==> 19 28 30 40 NA 1018.4 0"
[1] "2161838 ==> 20 31 34 31 9.99 982.05 0"
[1] "2139963 ==> 18 27 34 42 9.99 982.05 2"
[1] "2306179 ==> 23 27 28 51 9.99 982.05 0"
[1] "2162779 ==> 23 28 30 66 9.99 982.05 2"
[1] "24865698 ==> 23 29 30 38 9.99 982.05 0"
[1] "20070017 ==> 25 29 34 48 9.99 982.05 2"
> drawTemperature(data,date=Sys.Date())
6.2 check检查
打包过程一切正常,接下就是check()函数检查。 从check()函数的输出来看,顺利地通过了检查,但其实程序调试的过程中遇到了N多的问题,是一点一点花时间解决的。
> check("/home/conan/R/chinaWeather") # 执行check检查
Updating chinaWeather documentation
Loading chinaWeather
'/usr/lib/R/bin/R' --vanilla CMD build '/home/conan/R/chinaWeather' --no-manual --no-resave-data
* checking for file ‘/home/conan/R/chinaWeather/DESCRIPTION’ ... OK
* preparing ‘chinaWeather’:
* checking DESCRIPTION meta-information ... OK
* checking for LF line-endings in source and make files
* checking for empty or unneeded directories
* looking to see if a ‘data/datalist’ file should be added
* building ‘chinaWeather_0.1.tar.gz’
'/usr/lib/R/bin/R' --vanilla CMD check '/tmp/Rtmp3YI3Ar/chinaWeather_0.1.tar.gz' --timings
* using log directory ‘/tmp/Rtmp3YI3Ar/chinaWeather.Rcheck’
* using R version 3.1.1 (2014-07-10)
* using platform: x86_64-pc-linux-gnu (64-bit)
* using session charset: UTF-8
* checking for file ‘chinaWeather/DESCRIPTION’ ... OK
* checking extension type ... Package
* this is package ‘chinaWeather’ version ‘0.1’
* checking package namespace information ... OK
* checking package dependencies ... OK
* checking if this is a source package ... OK
* checking if there is a namespace ... OK
* checking for executable files ... OK
* checking for hidden files and directories ... OK
* checking for portable file names ... OK
* checking for sufficient/correct file permissions ... OK
* checking whether package ‘chinaWeather’ can be installed ... OK
* checking installed package size ... OK
* checking package directory ... OK
* checking DESCRIPTION meta-information ... OK
* checking top-level files ... OK
* checking for left-over files ... OK
* checking index information ... OK
* checking package subdirectories ... OK
* checking R files for non-ASCII characters ... OK
* checking R files for syntax errors ... OK
* checking whether the package can be loaded ... OK
* checking whether the package can be loaded with stated dependencies ... OK
* checking whether the package can be unloaded cleanly ... OK
* checking whether the namespace can be loaded with stated dependencies ... OK
* checking whether the namespace can be unloaded cleanly ... OK
* checking loading without being on the library search path ... OK
* checking dependencies in R code ... OK
* checking S3 generic/method consistency ... OK
* checking replacement functions ... OK
* checking foreign function calls ... OK
* checking R code for possible problems ... OK
* checking Rd files ... OK
* checking Rd metadata ... OK
* checking Rd line widths ... OK
* checking Rd cross-references ... OK
* checking for missing documentation entries ... OK
* checking for code/documentation mismatches ... OK
* checking Rd \usage sections ... OK
* checking Rd contents ... OK
* checking for unstated dependencies in examples ... OK
* checking contents of ‘data’ directory ... OK
* checking data for non-ASCII characters ... OK
* checking data for ASCII and uncompressed saves ... OK
* checking examples ... OK
* checking PDF version of manual ... OK
6.3 Github上传
最后,把项目代码上传到Github中,在Github中开源发布。
~ git add .
~ git commit -m 'app
~ git push origin app
To https://github.com/bsspirit/chinaWeatherDemo.git
* [new branch] app -> app
项目的访问地址为 https://github.com/bsspirit/chinaWeatherDemo/tree/app,感兴趣的用户可以自行查看源代码。
6.4 从Github安装chinaWeatherDemo项目
我们把代码上传到github的同时,就完成了在Github上发布项目,用户可以通过devtools包从Github安装项目。
> library(devtools) # 加载devtools包
> install_github("bsspirit/chinaWeatherDemo",ref="app") # 安装项目,配置app分支
Downloading github repo bsspirit/chinaWeatherDemo@app
Installing chinaWeather
'/usr/lib/R/bin/R' --vanilla CMD INSTALL '/tmp/RtmpTkR2Sd/devtools8435b61dfe5/bsspirit-chinaWeatherDemo-54e36d4' \
--library='/home/conan/R/x86_64-pc-linux-gnu-library/3.1' --install-tests
* installing *source* package ‘chinaWeather’ ...
** R
** data
** inst
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
* DONE (chinaWeather)
Reloading installed chinaWeather
到此为止,整个项目关于R语言的程序开发部分,就全都完成了。接下来就是PHP的部分了,下一篇文章中将继续介绍。