Quantcast
Channel: 数据科学中的R和Python
Viewing all 85 articles
Browse latest View live

XML和XPath使用方法备忘

$
0
0

如果把XML看作传统的关系数据库,那么XPath就是SQL。R语言中的XML包可用来解析处理XML或是HTML数据。在之前的文章中,我们了解到readHTMLTable函数,如果页面中的数据是一个规整的表格,用它是很方便的,但如果页面中是一些非结构化的数据,就要用到XML包中的其它函数了。其中最重要两个函数是xmlTreeParse()和getNodeSet(),前者负责抓取页面数据并形成树状结构,后者对抓取的数据根据XPath语法来选取特定的节点集合。下面用一个简单的例子来看一下这两个函数配合使用的效果。

这里是一个简单的XML文档,下面是一些简单的节点选取操作:
library(XML)
# 解析XML文件
doc
<- xmlParse('http://www.w3school.com.cn/example/xmle/books.xml')
# 选取属于 bookstore 子元素的第一个 book 元素
getNodeSet
(doc,'/bookstore/book[1]')
# 选取属于 bookstore 子元素的最后一个 book 元素。
getNodeSet
(doc,'/bookstore/book[last()]')
# 选取最前面的两个属于 bookstore 元素的子元素的 book 元素
getNodeSet
(doc,'/bookstore/book[position()<3]')
# 选取所有拥有名为 lang 的属性的 title 元素。
getNodeSet
(doc,'//title[@lang]')
#选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性
getNodeSet
(doc,"//title[@lang='eng']")
# 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
getNodeSet
(doc,"/bookstore/book[price>35.00]")
# 选取 bookstore 元素中的 book 元素的所有 title 元素,且 price 元素的值须大于 35.00。
getNodeSet
(doc,"/bookstore/book[price>35.00]/title")
# 选取 book 元素的所有 title 和 price 元素
getNodeSet
(doc,"//book/title | //book/price")
# 选取文档中的所有 title 和 price 元素
getNodeSet
(doc,"//title | //price")
# 选取 bookstore 元素的所有子元素
getNodeSet
(doc,"/bookstore/*")
# 选取所有带有属性的 title 元素
getNodeSet
(doc,"//title[@*]")
# 选择所有属性lang的值
unlist(getNodeSet(doc,"//title/@lang"),use.names = FALSE)
# title结点下的所有文本
getNodeSet
(doc,"//title/text()")
 
如果你比较习惯操作R,也可以用xmlToList转成list格式再说。如果说XML的结构比较简单,我们可以使用xmlToDataFrame直接将其转为R语言中的data.frame。下面再来看一个操作豆瓣API的例子和其它一些有用的函数。
# 豆瓣的例子
url<-'http://api.douban.com/movie/subject/imdb/tt0111161'
# 解析获得树结构数据
doc
<- xmlTreeParse(url,useInternal=TRUE,encoding="UTF-8")
# 获得根结点信息
top
<- xmlRoot(doc)
# 获取子节点
top
[[5]]
# 子节点名称
xmlName
(top[[5]])
# 按名字取子节点
top
[['author']]
# 与上一命令相同
xmlChildren
(top)[['author']]
# 显示子节点数量
xmlSize
(top)
# 获取节点元素
xmlValue
(top[['author']])
# 获取节点属性
xmlAttrs
(top[[5]])
#获取节点属性值
xmlGetAttr
(top[[5]],name='href')
# 向量化操作,获取所有子结点的名字
sapply(xmlChildren(top), xmlName)
# 使用专门的xmlSApply函数,等价于上一条
xmlSApply
(top, xmlName)
 
# 使用xpath语法进行XML查询
# 找出合乎条件的节点,例如找出所有主演的节点集合
(node <- getNodeSet(top,
path=
"//db:attribute[@name='cast']"))
# 然后取出其中的元素
sapply(node,xmlValue)
# 也可以从根节点一步操作得到结果
(cast <- xpathSApply(top,
path=
"//db:attribute[@name='cast']",
xmlValue
))
 
# 取出link节点中的属性和属性值
# 定义命名空间,再使用前述函数
namespaces
<-c(ns='http://www.w3.org/2005/Atom')
getNodeSet
(top,"//ns:link", namespaces)
xpathSApply
(top,"//ns:link",
fun=xmlAttrs
,
namespaces=namespaces
)
xpathApply
(top,"//ns:link",
fun=xmlGetAttr
,
'href',
namespaces=namespaces
)

R书精选之十二宫

$
0
0

以前人的烦恼是没有书可读,现在人的烦恼是书太多了。关于R语言的书已经出版很多了,博主大约读过其中的四十多本,但是书在精,而不在多,学在透,而不在速。把有限的时间放到无限的书海中,这不是阅读的真意。本着造福学习者的角度,博主精选出十二本R书。什么是好书的标准?我以为是:有案例,有代码,有习题,有讲解,逻辑清楚,排版精良,体系完备,互有补充,内容千锤百炼,值得反复揣摩。书单均为英文版,都可以从网上找到。当然这份书单的选择是有主观偏见的。


一、初学入门:
《R in Action》
《The Art of_R Programming》
入门者可首选两本,前者从统计角度入手,分高中低三部分由浅入深的讲解了如何用R来实现统计分析,另外此书已经有中文版面世。后者从程序编写的角度入手,对R的本身特点进行了清晰的介绍。中文版应该快有了。

二、统计进阶:
《A Handbook of Statistical Analyses_Using_R》
《Modern Applied Statistics With S》
这两本书基本上涵盖了统计的一些高阶内容,例如多元分析、多层回归模型、荟萃分析、生存分析等内容。案例丰富,公式不多,值得反复学习参考。

三、科学计算:
《Introduction to Scientific Programming and Simulation Using R》
除了统计分析外,此书独特之处在于使用R来做数值分析,如求根,最优化,数值积分。还包括了一些常见的模拟技术。书后的习题和最后的案例非常有用。该书的中文版据说还在翻译。

四、数据挖掘:
《Data Mining with R_ Learning with Case Studies》
《Machine Learning for Hackers》
两本侧重于数据挖掘的R书,全是以案例为线索,示范的代码量很大。跟一遍下来会有很大的收获。

五、数据绘图:
《ggplot2 Elegant Graphics for Data Analysis》
ggplot2还有什么好说的呢,R中最优秀的绘图包,但由于近期该包升级很快,这书显得有些过时。好在中文版进行了大幅更新,即将面世。

六、参考手册:
《R Cookbook》
《R in a Nutshell》
有时候我们需要类似词典的案头参考手册,以方便随时查阅。又或者可以通读一遍以查漏补缺。上面两本书虽然有些厚度,但仍然推荐之。后者的中文版也在翻译状态。

七、高级编程:
《R Programming for Bioinformatics》
《software for data analysis programming with R》
如果你是初学者,不要去看上面两本书。如果你想进阶为专家级R用户,那你需要精读它们。前者讲解了R少为人知的一面,例如字符处理、正则表达和XML,还有报错处理以及与其它语言的交互。后者更是编写生产级代码的圣经指南。

数据挖掘的三行俳句

$
0
0

最近才看到Tom Khabaza写的一篇很有份量的文章,阐述了数据挖掘的九大法则,在最后他以俳句方式进行了总结,可谓是字字珠玑。原文很长,只将俳句和各法则的纲要翻译放在这里。

First the business goal // Is all in data mining // This defines the field
Second is knowledge // Of business at every stage // This is the centre
Third prepare data // The form permits the question // Shape the problem space
Fourth is no free lunch / /By searching find the model // And the goal may change
Fifth is Watkins law / /There will always be patterns // Traces in data
Sixth is perception // Data mining amplifies // Thus we find insight
Seventh prediction // Generalised from data // New facts locally
Eighth is the value // All value comes from business // Not technical things
Ninth and last is change // No pattern lasts forever // We do not stand still
Miners know this truth / /How can business be better? / /If we see what is
Can the process change? // Technology can change it / /None has done so yet

1、商业目标是数据挖掘的起点
2、业务知识贯穿着数据挖掘的每个阶段
3、数据挖掘中的大部分工作是数据准备
4、对于给定的问题,只有不断尝试才能得到适合的模型
5、模式总会存在
6、数据挖掘能增强对业务的理解
7、通过归纳,预测模型增加了信息量
8、数据挖掘的价值并不取决于模型的准确或稳定
9、所有的模式都会改变

灰色模型的R代码

$
0
0
最近帮朋友写了一个灰色模型GM(1,1)的R实现,参考网上现有的matlab代码,比较容易就可以弄出来。下面是具体过程,主函数是GM(),建立的模型是一个S3类,搭配两个自定义的泛型函数print和plot可以得到结果输出和图形。
# 本代码用来计算GM(1,1)灰度模型
# 输入:x 原始数据,adv为外推预测步长
# 输出:actual 原始数据,fit 拟合数据,degree 拟合精度,
# C 后验差比值,P 小概率误差,predict 外推预测值
 
 
# 主函数
GM <- function(x,adv=0){
x0 <- x
k = length(x0)
# AGO
x1 = cumsum(x0)
# construct matrix B & Y
B = cbind(-0.5*(x1[-k]+x1[-1]),rep(1,times=k-1))
Y = x0[-1]
# compute BtB...
BtB = t(B)%*%B
BtB.inv = solve(BtB)
BtY = t(B)%*%Y
 
# estimate
alpha = BtB.inv%*%BtY
 
# 建立预测模型
 
predict<- function(k){
y = (x0[1] - alpha[2]/alpha[1])*exp(-alpha[1]*k)+alpha[2]/alpha[1]
return(y)
}
pre <- sapply(X=0:(k-1),FUN=predict)
prediff <- c(pre[1],diff(pre))
# 计算残差
error <- round(abs(prediff-x0),digits=6)
emax <- max(error)
emin <- min(error)
# 模型评价
incidence <- function(x){
return((emin + 0.5*emax)/(x+0.5*emax))
}
degree <- mean(sapply(error,incidence))
 
s1 <- sqrt(sum((x0-mean(x0))^2)/5)
s2 <- sqrt(sum((error-mean(error))^2)/5)
 
C<- s2/s1
 
e <- abs(error-mean(error))
p <- length(e<0.6745)/length(e)
 
result <- list(actual = x0,
fit = prediff,
degree = degree,
C = C,
P = p)
 
# 外推预测第k+adv项
if(adv > 0){
pre.adv <- predict(k+adv-1)-predict(k+adv-2)
 
result$predict <- pre.adv
}
class(result)<- 'GM1.1'
return(result)
}
 
# 增加对应gm1.1类的泛型函数 print & plot
print.GM1.1 <- function(mod){
cat('the result of GM(1,1)\n')
cat('Actual Data:','\n',mod$actual ,'\n')
cat('Fit Data:','\n',round(mod$fit,2),'\n')
cat('Degree:',round(mod$degree,3),'\n')
cat('C:',round(mod$C,3),'\n')
cat('P:',round(mod$P,3),'\n')
if(!is.null(mod$predict)){
cat('Predict Data:',round(mod$predict,2),'\n')
}
}
 
plot.GM1.1 <- function(mod,adv=5){
prex <- numeric(adv)
x <- mod$actual
for(k in1:adv){
prex[k]<- GM(x,k)$predict
}
 
value = c(x,prex)
 
res <- data.frame(index = 1:length(value),
value = value,
type = factor(c(rep(1,length(x)),rep(2,length(prex)))))
library(ggplot2)
p <- ggplot(res,aes(x=index,y= value))
p + geom_point(aes(color=type),size=3)+
geom_path(linetype=2) +
theme_bw()
}
 
 
# 原始数据
x = c(26.7,31.5,32.8,34.1,35.8,37.5)
 
# 预测第7项
res <- GM(x,1)
print(res)
plot(res,3)

R语言玩转资产组合计算

$
0
0

以前都是用MATLAB或是EXCEL给学生讲资产组合的计算问题,实际R语言也可以做一样的事情。资产组合要解决的问题并不复杂,即给定一个可选的资产集合,要从中选择出一个最优组合,使其收益率较大,而风险较小。如果可选资产只有两个的话,问题非常简单,可以通过求导最优化的方式得到结果,即有效资产前沿的解析解。如果资产集合超过两个那么问题要复杂一些。首先需要给定一个要求的期望收益率,再求出在此约束下的方差最小组合,这可以通过二次规划解出。这样得到有效前沿上的一个点。然后更改期望收益率,又可以得到另一个最优解,如此反复即可得到多资产组合的有效前沿。

下面我们先用R语言中quadprog包的二次规划求解函数来计算一个例子,再用fPortfolio包中的函数来完成同样的任务。例子中使用的数据来自于fPortfolio包中的SMALLCAP.RET数据集,使用了其中的四个资产来示例。



library(quadprog)
library(fPortfolio)
data<- SMALLCAP.RET[,c("BKE","GG","GYMB","KRON")]
# 计算得到收益率数据的协方差矩阵和期望
sigma <- covEstimator(data)$Sigma
mu <- covEstimator(data)$mu
# 计算给定期望收益率为0.03条件下的最优组合,且不可作空
A <- cbind(rep(1,4), mu,diag(rep(1,4)))#约束系数
D<- sigma # 协方差矩阵
x <- mu # 期望收益
b <- c(1,0.03,0,0,0,0)#约束的右侧值
res <- solve.QP(2 * D, x, A, b, meq=2)
round(res$solution,2)

得到最优资产组合的权重向量为0.26,0.26,0.00,0.48,quadprog包的二次规划求解在设置参数上不那么直观,而且不能够直接计算原始数据。更为方便的是使用fPortfolio包中的系列函数。下面使用efficientPortfolio()函数来计算给定期望下的最优组合,使用前需要设定函数所需的参数,一个用来表示组合的设定,另一个用来表示组合的约束。

# 设定组合的期望收益率为0.03
spec <- portfolioSpec(portfolio=list
(targetReturn=0.03))
# 设定组合的约束不许做空
cons <- 'LongOnly'
# 求解
res <- efficientPortfolio(data, spec = spec,
constraints = cons)
summary(res)

存在res中的输出结果非常丰富,其中包括了最优组合的权重,以及在此权重下的组合期望收益率和组合标准差,此外还提供了组合的风险价值VaR和条件风险价值CVaR。输出中的风险预算表示各资产对组合风险的贡献比例,可见KRON所占风险最高。我们还可以计算出有效前沿上的所有组合并绘制成图。
# 设定计算出前沿上的100个最优组合,无风险资产收益率为0.01
spec <- portfolioSpec(portfolio=list
(nFrontierPoints = 100,
riskFreeRate=0.01))
# 计算有效前沿,并不许做空
frontier<- portfolioFrontier(data,spec=spec,
constraints = cons)
# 有效前沿绘图
frontierPlot(frontier,
pch = 19,
cex = 0.5,
xlim=c(0,0.25),
ylim=c(0,0.035))
grid()
abline(h = 0,col = "grey30")
abline(v = 0,col = "grey30")
minvariancePoints(frontier, pch = 19,col = "red")
tangencyPoints(frontier, pch = 19,col = "blue")
tangencyLines(frontier,col = "darkblue",lwd=3)
singleAssetPoints(frontier, pch = 19, cex = 1.5,col = topo.colors(6))
front <- frontierPoints(frontier)
monteCarloPoints(frontier, mcSteps = 500, pch = 19,
cex = 0.3)
lines(front,col = "red4", lwd = 3)

R连接MySQL数据库方法备忘

$
0
0

R语言连接数据库可以利用数据库的存贮能力和R的计算能力,起到取长补短的效果。之前我们也说过了如何在R中使用SQL,很多教材上也提到了连接MySQL的方法,但是在安装上还需要注意一些细节问题。以下的解决方法也是在网上放狗加撞墙实验得出的结论。


一、win平台
如果是在windows平台上安装,推荐采用ODBC连接方式。除了需要安装R和MySQL之外,还要安装RODBC扩展包,以及MySQL的ODBC驱动。下面是具体步骤:

1、R下载RODBC包,安装好。
2、在http://dev.mysql.com/downloads/connector/odbc
下载mySQL ODBC,安装好。
3、windows:控制面板->管理工具->数据源(ODBC)->双击->添加->选中mysql ODBC driver一项
填写:data source name 一项填入你要使用的名字,自己随便命名,例如:mysql_data;
description一项随意填写,例如mydata
TCP/IP Server 填写服务器IP,本地数据库一般为:127.0.0.1
user 填写你的mysql用户名
password 填写你的mysql密码
然后数据库里会出现你的mysql里的所有数据库,选择一个数据库。
确定。
4、打开R调用数据库:
library(RODBC)
channel <- odbcConnect("mysql_data", uid="abc", pwd="abc")
sqlTables(channel)#查看数据中的表
data<-sqlFetch(channel,"abc")# 查看表的内容,存到数据框里

二、linux平台
在linux平台下使用ODBC连接安装比较麻烦,推荐采用JDBC连接方式。具体安装方式如下:

在软件源中增加R官方源,方法具体见官网说明;之后在term中运行发下命令,安装需要的软件:
sudo apt-get update
sudo apt-get install r-base
sudo apt-get install r-dev
sudo apt-get install r-cran-rmysql
sudo apt-get install r-cran-dbi
sudo apt-get install mysql-server my-client
sudo apt-get install libmysqlclient-dev

在R中加载RMySQL两个包,并使用dbConnect函数设置好用户名和密码
library(RMySQL)
con <- dbConnect(MySQL(),
user='abc',# 用户名
password='abc',# 密码
dbname='abc',# 要使用的数据库名称
host="localhost")# 主机地址
dbListTables(con)# 列出所有数据库中的表
# 运行sql语句并返回数据到R 
data<- dbGetQuery(con,"select * from abc")
SQL查询可以通过dbSendQuery或dbGetQuery传给数据库管理系统。dbGetQuery传送查询语句,把结果以数据框形式返回。dbSendQuery传送查询,返回的结果是继承"DBIResult"的一个子类的对象。"DBIResult"类可用于取得结果,而且还可以通过调用dbClearResult清除结果。函数fetch用于获得查询结果的部分或全部行,并以列表返回。函数dbHasCompleted确定是否所有行已经获得了,而dbGetRowCount返回结果中行的数目。如果只是简单的读整个表,也可以用dbReadTable函数。


在设置连接时会在R语言环境中明文标示了数据库用户和密码,为了安全起见,可以作如下设置:
在本机目录中定义一个配置文档( ~/.my/cnf),例如定义两个使用MySQL的用户组:
[local]
user = root
password = ultra_secret
host = localhost

[toto]
user = capitaine_flam
password = galaxy
host = milky.way.net

然后在R中使用用户组:

library(RMySQL)
con <- dbConnect(MySQL(),group='toto', dbname="user_profile")
m <- dbGetQuery(con,"SELECT DISTINCT user_id FROM demographics WHERE gender='0'")
dbDisconnect(con)

另外R连接mysql会出现中文乱码变问号情况,查到COS上一个贴子,解决方案如下:


在MySQL的配置文件/etc/mysql/my.cnf中[client]标签下加default-character-set=utf8





初学D3的感觉

$
0
0

简单来讲有如下三点感受:

  • D3很强大
  • D3并不容易学
  • 学会D3并不等于学会了可视化

一山还有一山高,在翻过ggplot2这座山后,发现还有D3这座珠穆朗玛。ggplot2已经非常好了。能够实现The Grammar of Graphics的精义,有很丰富的对象和灵活的自由度,但这都还不够,因为ggplot2只能够生成静态的图形。如果你只需要写一篇分析报告,那么ggplot2是足够的。但如果你想让数据在网页上飞翔,就需要D3做为翅膀。


D3和ggplot2的共同点在于都可以实现数据到图形元素的映射,但D3更为底层一些。它的优点在于:

  • 用D3进行可视化,你只需要一个浏览器+编辑器就可以完成工作,并不需要其它环境,也便于分享。
  • 灵活性强,它可以很好的利用现有的web技术 HTML, CSS, SVG,操纵页面的任何一个对象,和数据绑定,无中生有的生成svg元素,进而由浏览器渲染成图形。
  • 它也能利用现有浏览器上可以实现的js函数,实现和用户的即时交互。
  • 此外,大量的文档和案例提供了很好的学习资源。

底层也意味着用它来绘图不是一蹴而就的事情。D3并不是一个图表库,例如它没有任何一个函数可以直接画出箱线图出来。它只是javaScript的一个函数库,你需要考虑到各个方面,操很多心,费很多步骤才能画出一个简单的图形。当然现在已经有了很多基于D3的库,例如xCharts/NVD3/Vega,在R里面也有clickme包可以将数据直接转为D3。不过对于D3,知道的越多越好,例如HTML,CSS,SVG,DOM,JavaScript。

可以这样来描述一下D3的特点:D3是一个组装生产线,这个生产线首先要放在一个车间里面,这个车间就是HTML。其次生产线上要有元件进来用以组装,有两种主要元件分别是数据和svg元素,D3首先读取json,csv,tsv格式文件,然后将数据和body内的svg元素属性绑定,组装的结果是一个新的HTML页面,最后的任务就是交给浏览器去展现数据特征。而D3这个生产线应该如何运转,则依赖于工程师头脑中的生产工艺或方法。

D3是一种可视化的工具,它本身并不能告诉你如何实现一个优秀的可视化。正如同拿着青釭剑的夏侯恩,并不能击败常山赵子龙。学会了D3,只是学会了将数据摆放到屏幕上,但什么样的摆放方式才是美的,有效的。这还需要更多可视化的理论学习和实践。

数据可视化本身不是目的,目的在于传送数据中隐藏的信息。人类不善于直接解读数据。但人类的视觉系统善于阅读图形,并从中搜寻模式。可视化就是将数据编码成图形,再由其它人读取图形,解码信息。这种可视化实际上是一种对已知数据进行解释性可视化的过程,一种讲故事的方式,这种情况下用D3是很适合的。而另一种探索性可视化,是对未知数据的描述,讲故事的人本身不晓得数据中有什么玄机,此时用D3就不大合适了,而应该换用快速的绘图工具。不过总而言之,学习D3是值得的,正如同学习R一样,谢益辉曾说:使用R将迫使你深入的理解统计,而使用D3也有同样的效果,使D3它将迫使你成为真正的可视化大师。

正所谓:内修于心,外显于形。

其它:
学习D3的预备资料:
http://www.w3school.com.cn/
www.codecademy.com
学习D3的几种入门材料:
http://code.hazzens.com/d3tut/lesson_0.html
http://www.dashingd3js.com/table-of-contents
http://ofps.oreilly.com/titles/9781449339739/

实现可重复的统计slides

$
0
0

制作幻灯片是数据分析师的必备技能之一,优秀的slides对外可以忽悠住客户,对内可以震慑住领导。精良的slides要秀外慧中,有逻辑有内容,还要有外形有风格。达到这种标准并不容易。在过去,你可能使用office中的ppt来做传统意义的幻灯片,将图片和代码费力的copy到一张张的slides上去,然后到处找模板。但这种方式已经凹特了。

在HTML5的发展背景下,已经出现了大批以网页形式的slides框架,例如:Google IO 2012\HTML5 slides\HTML5 Rocks\Shower\Deck.js这个名单可以很长。而这里只是其中六种演示框架的介绍。在这些slides框架下,你只需要懂一点点web知识,将图片和数据嵌入到一个html模板中,就可以生成一个动态可交互的slides。

实际上对于统计分析的slides,有一种工具可以使我们的制作效率更高。这就是谢益辉的knitr包。knitr像一把钥匙,打开了可重复统计报告的大门,同时也打开了通向html的大门。可以使R代码、运算结果和分析文字自然的融为一体,能自由的输出为LaTex、Markdown或者是Html。在借助knitr打通了这些奇经八脉之后,可以惊奇的发现,knitr可以将以上所有东西粘在一起,有助于实现可重复的统计分析幻灯片。

以后的工作流应该是这样的:数据分析的过程和结果均存放在rmd文件中,可根据不同需要转换为pdf或是html,当需要制作slides的时候,只要将生成的html进行一点加工,加入一些js/css效果即可生成美观炫目的slides。目前已经有很多这类现成的例子,例如coursera的公开课data analysis就是使用了这种slides来讲解R和数据分析。作者利用的是名为slidify的R包,直接从rmd文档生成html5的slides页面,非常推荐各位去下载来研究一下。

slidify使用的默认框架是io2012,比较淡雅朴素,另一种比较炫目的框架是reveal.js,这里有一个例子值得参考下。这份slides的原码可以在此找到。这份slides是使用reports包来生成的,基本流程如下:
install.packages("reports")
library(reports)
presentation('example')
setwd('~/example')
reveal.js()
安装reports包后使用presentation建立一个目录,这个目录会在当前R工具目录下自动生成,之后用户在目录下的rmd文件中编辑内容,保存后生成html文件,最后使用reveal.js函数生成slides,你会在reveal.js目录下找到index.html,就是最终的文件。由于reports包的瑕疵问题,在reveal.js前一步你可能需要手动切换一下工作目录。而且最好是再手动编辑一下index.html文件,以完全自定义实现reveal.js的各种特效。笔者也做了一个简单的slides可以看一看。关于reveal.js的完整资料看这里。 

相比reports包,slidify要显得稳定些,使用方法也类似,但它还放在github上,所以要用devtools包来下载它:
install_github("slidify", "ramnathv")
install_github("slidifyLibraries", "ramnathv")
library(slidify)
author('example')
slidify('index.Rmd')
加载slidify后使用author,它会自动在当前工作目录下建立example目录,并打开index.Rmd文档,供用户编辑,当然在写slides的时候需要遵从一定的格式才会让它识别。写完之后使用slidify即可生成网页。目前slidify支持的框架不多,但在开发版本中已经支持了包括reveal.js在内的很多框架了,所以尽请期待吧。


适合初学者的R语言教程

关于可视化的一个slide

电影爱好者的R函数

$
0
0
作为一个伪影迷,经常纠结一些电影该不该下,要不要看。毕竟吾生也有涯而片源无涯。还好可以去豆瓣一类的地方看看大家的评分择优录用。去豆瓣查分需要登录网站搜索再鼠标点点点,如果要查好几部电影就有点费事儿。其实可以用R写个函数,先抓取相应的网页,再筛选返回需要的分值。这样在R里头就可以批量查分了,恩,走起来。
library(RCurl)
library(XML)
movieScore <- function(x) {
stopifnot(is.character(x))
# 提交搜索豆瓣表单
search <- getForm("http://movie.douban.com/subject_search", search_text = x)
searchweb <- htmlParse(search)
# 解析搜索结果页面
resnodes <- getNodeSet(searchweb, "//div[@id='wrapper']//table[1]//a")
if (is.null(resnodes))
return(NULL) else resurl <- xmlGetAttr(resnodes[[1]], name = "href")
# 得到影片页面后第二次解析
resweb <- getURL(resurl, .encoding = "UTF-8")
content <- htmlParse(resweb, encoding = "UTF-8")
resnodes <- getNodeSet(content, "//div[@id='interest_sectl']//p[@class='rating_self clearfix']//strong")
namenodes <- getNodeSet(content, "//div[@id='content']//h1//span")
# 得到影片评分
score <- xmlValue(resnodes[[1]])
name <- xmlValue(namenodes[[1]])
return(list(name = name, score = score))
}
看看天机这部大烂片多少分。
movieScore("天机")
## $name
## [1] "天机·富春山居图"
##
## $score
## [1] "2.9"
抓网页比较慢,豆瓣为人民群众着想提供了API,我们也可以使用API来调取分数,函数也比较简单。
library(RCurl)
library(XML)
library(RJSONIO)
movieScoreapi <- function(x) {
api <- "https://api.douban.com/v2/movie/search?q={"
url <- paste(api, x, "}", sep = "")
res <- getURL(url)
reslist <- fromJSON(res)
name <- reslist$subjects[[1]]$title
score <- reslist$subjects[[1]]$rating$average
return(list(name = name, score = score))
}
movieScoreapi("僵尸世界大战")
## $name
## [1] "僵尸世界大战"
##
## $score
## [1] 7.5
有了这个查分函数,我们可以在R中批量查阅电影评分了。但是豆瓣对于频繁的访问会有限制,对于没有认证的API使用是每分钟10次,超过就会暂时封IP。对于网页抓取,肖楠在第六次R会议上有个很棒的演讲,有兴趣的同学可以去统计之都看看。

培训广告

$
0
0
本月中旬本人将在上海举行一次为期三天的R语言商业培训,有兴趣的朋友可以点这里查看。

生存分析函数小结

$
0
0
生存分析(survival analysis)适合于处理时间-事件数据。例如中风病人从首次发病到两次复发,其中就涉及到时间和事件。此例中时间就是复发的时间间隔,事件就是是否复发。如果用普通的线性回归对复发时间进行分析,就需要去除那些没有复发的病人样本。如果用Logistic回归对是否复发进行分析,就没有用到时间这个因素。而生存分析同时考虑时间和事情这两个因素,效果会更好些。

在R语言中我们可以使用survival包进行生存分析,其中主要的函数功能罗列如下:

Surv:用于创建生存数据对象
survfit:创建KM生存曲线或是Cox调整生存曲线
survdiff:用于不同组的统计检验
coxph:构建COX回归模型
cox.zph:检验PH假设是否成立
survreg:构建参数模型



下面是使用一个实例来使用R中的生存分析函数,其中用到的数据集可以在这里下载

说英雄谁是英雄之光荣三国

$
0
0

本文的缘起是知乎的这一篇文章,老马这位三国历史专家让大家都知道了有这么一份三国志游戏数据的存在。这份数据很容易从网上找到,而本人只关心三国志四的各人物数据,为什么呢,因为只玩过三国志四嘛。游戏是多年前玩的,如今来玩玩数据吧。下面的问题主要围绕一个焦点,谁是三国志四中文武兼资第一人。


网上下载的数据是一个Excel表格,整理之后只取了三国志四的部分,去除了分值为0的人物,整理后数据你可以从这里下载。整个数据有454名人物,包括了六个变量,分别为人物'名字','统率','武力','智力','政治','魅力'。我们可以使用plyr包中的arrange函数找到各指标分别对应的前十名。不出意外,武神关二爷获得统率第一,人中吕布获得武力第一,诸葛亮获得智力第一,张昭获得政治第一,而会哭的刘备获得魅力第一,晕!
arrange(data,desc(tongshuai))[1:10,]
arrange(data,desc(wuli))[1:10,]
arrange(data,desc(zhili))[1:10,]
arrange(data,desc(zhengzhi))[1:10,]
arrange(data,desc(meili))[1:10,]
 
由于每个人物对应多个指标,我们需要一个综合指标来比较,最简单的,上PCA。
prinModel <- prcomp(x=data[,2:6],
retx=TRUE,
center=TRUE,
scale=TRUE)
 
prinModel$rotation[,1:2,drop=F]
summary(prinModel)
 
对数据进行主成份分析,发现前两个主成份的累积方差贡献率达到88%,还不错,第一PC以智力和政治为主,达到50%贡献率,第二PC以武力和统率为主,达到30%贡献率。那么第一主成份可以认为是文韬因素,第二主成份可以认为是武略因素。好的,下面可以根据两个主成份得分列出文韬前十和武略。

# 武略榜
data$name[order(prinModel$x[,2],decreasing=T)][1:10]
[1]"關羽""趙雲""曹操""孫策""孫堅""黃忠"
[7]"周瑜""陸遜""夏侯惇""姜維"
# 文韬榜
data$name[order(prinModel$x[,1],decreasing=T)][1:10]
[1]"郭嘉""張紘""張昭""諸葛亮""荀彧""諸葛瑾"
[7]"荀攸""曹植""魯肅""馬良"
 
下面要将这两个主成分合为一个综合指标,采用加权平均方法,权重是方差贡献率,大致上0.6*文韬+0.4*武略,下面就取出兼资文武之名将前十名,当当当当,他们是:
final <- prinModel$x[,1]*0.6 + prinModel$x[,2]*0.4
data$name[order(final,decreasing=T)][1:10]
 
[1]"諸葛亮""曹操""周瑜""陸遜""司馬懿""趙雲"
[7]"魯肅""姜維""龐統""徐庶"
 
看来在三国志的游戏数据中,诸葛亮是最强人物啊。最后来看看蜀国五虎排序,通常民间排序是关张赵马黄,这种序列显然没有考虑到智力因素问题啊,下面我们用前面的评价体系来为五虎重新排序。
shu5 <- c('趙雲','馬超','張飛','關羽','黃忠')
data.frame(round(prinModel$x[data$name %in% shu5,1:2],2),
final=round(final[data$name %in% shu5],2),
name=data$name[data$name%in% shu5])
 
PC1 PC2 final name
437 -1.512.22 -0.02馬超
488 -2.651.31 -1.07張飛
6580.592.921.52黃忠
7411.683.312.34趙雲
9221.203.482.12關羽
 
从上面这个表格可以看到,根据游戏数据正确的排序应该是赵关黄马张,赵云君,我看好你啊。我们还可以看看五虎将在群雄中的位置,将PC1和PC2做散点图如下,这张图中处于右上角的就是文韬武略兼备的人才。
library(ggplot2)
ggdata <- data.frame(prinModel$x[,1:2],name=data$name)
p <- ggplot(ggdata,aes(PC1,PC2))+
geom_point(size=3,alpha=0.5)+
geom_text(data=subset(ggdata,name %in% shu5),
aes(label=name))+
labs(x='文韬',y='武略')+
theme_bw()
print(p)


 
最后还可以用雷达图看这五虎的技能值


使用PCA来进行综合指标评价不一定是最好的方法,各位有什么好主意,请不吝赐教。

奇异值分解和潜在语义分析

$
0
0
奇异值分解是一种矩阵分解技术,如果将列看作特征,SVD也能看作是一种降维技术。如果将数据先进行标准化之后,再进行SVD操作,其左奇异向量U就是主成分得分,右奇异向量V就是主成分负载。但SVD的优势恰恰在于不进行标准化,当我们处理高维稀疏数据(例如文本数据)时,标准化会使矩阵不再稀疏,影响计算效率。所以一般是用SVD直接对原始数据进行操作。得到U的第一列是平均值的意义,U的后几列才有区别各样本的功能。

在文本挖掘中,潜在语义分析(LSA)假设在词项和文档之间有一个潜在语义层,词汇和语义产生关联,文档也和语义产生关联。这样通过语义概念,可以将词项和文档放在一个语义空间中观察分析。进一步我们可以将语义所为词项的“主成分”放到数据挖掘中进行分析。LSA的一般过程是先构造词项-文档矩阵(其转置为文档-词项矩阵,视需要而定),再计算TFIDF值,然后用SVD来分解这个矩阵,得到的奇异向量就是潜在语义。U的第一列可以认为是词项在文档中的平均出现频率,V的第一列可以认为是文档中包含的词项频率,我们更有兴趣的是后几列。关于SVD和LSA有一份精彩的入门文档,下面的R代码就是对该文档的模仿,但是SVD得到的结果却和文档不同,我很奇怪为什么会这样。(使用的数据



如何善用R的语法:三段示例

$
0
0
在改进R代码的运算效率时,我们常说的第一句话就是:要善用R的语法。那么问题是:HOW?下面用一个具体的问题来表达这句比较抽象的话。问题就是用R代码来模拟一个二维布朗运动,一个人从原点出发,随机的向任何一个方向前进或后退一步,不会停留在原地。这个问题是一位英国留学的朋友问我的,我觉得可能比较典型,就顺便写在博客上供大家参考比较吧。

下面就这个问题,给出了三个解答,slowwalk是运行最慢的,在我的电脑上大约要运算8秒,这段代码慢的原因在于用c来补进新的向量元素。而在R中,对一个向量进行新增的操作实际上是进行了复制重建,所以速度是很慢的。为了改进这一点,speedwalk1函数中,先用一个空向量占好了位置,再向这个向量中放东西,这样不需要反复新建,速度会增加10倍,只花了0.7秒左右。但R最重要的运算思路是向量化,也就是同时对向量各元素进行计算,而不是把向量元素一个个放到循环中。speedwalk2函数就是向量化计算的实现,这样下来代码速度又加快了十几倍,大约只需0.05秒,而且还没有用到多核心计算。

如何批量处理文本文件

$
0
0
最近数据堂为了弄数据挖掘比赛提供了一批用户行为日志数据。对于以前没玩过的数据,我是特别的好奇。处理这批文本文件确实花了不少时间。数据以不同的日期作文件夹分别存放,每个文件夹中又有近一千个文本文件,每个文件都是一个用户的行为日志。为了分析这些数据,首先需要将这两万个文本文件读入R中,再用字符串函数进行处理成结构化的数据。处理方法如下:
library(stringr)
setwd('D:\\kaggle\\tang\\data')
data<- read.table('data.csv',T,sep=',')
 
# 读入文档地址
path <- 'D:\\kaggle\\tang\\data\\behavior'
dir.name <- dir('D:\\kaggle\\tang\\data\\behavior')
doc.name <- list()
fre <- numeric()
for(i in1:length(dir.name)){
doc.name[[i]]<- dir(paste(path,dir.name[i],sep='\\'))
fre[i]<- length(doc.name[[i]])
}
dir<- rep(dir.name,fre)
doc.name <-unlist(doc.name)
file.name <- character()
for( i in1:length(dir)){
file.name[i]<- paste(path,dir[i],doc.name[i],sep='\\')
}
 
# 建立抽取主函数,返回列表
data.get <- function(file.name){
#获取文本
temp <- readLines(file.name,encoding='UTF-8')
if(length(temp)<=2)return(NA)
# 用户编号
id <- str_match(file.name,"[A-Z0-9]{32}")
# 调查日期
day <- str_match(file.name,"\\d+-\\d+-\\d+")
# 开机时点
clock <-str_sub(str_match(file.name,'_\\d{2}-'),2,3)
# 切分转换文本函数
trans <- function(x){
res <- unlist(str_split(x,"\\[=\\]|<=>"))
# res <- str_extract(x, "[^<=>]+\\.[a-z]+")
return(res)
}
# 将文本切开转为列表
result <- lapply(temp,trans)
 
# 开机时长
opentime <- as.numeric(result[[1]][2])
# 先进行时间分析,由于有的信息不是按顺序排列,所以要按时点重排
# 时点抽取
time<- unlist(lapply(result[-c(1:2)],function(x) x[2]))
time<- as.numeric(time)
# 时点排序,然后重排result列表
new.res <- result[-c(1:2)][order(time)]
 
# 返回用户使用的程序向量
prog <- unlist(lapply(new.res,function(x) x[4]))
# 各程序使用时间
time<- unlist(lapply(new.res,function(x) x[2]))
time<- as.numeric(time)
time[length(time)+1]<- opentime
time<- diff(time)
 
prog.time <- data.frame(prog=prog,time=time)
progtime <- dcast(prog.time,prog~.,sum,value.var='time')
names(progtime)<- c('program','time')
 
# 使用的软件个数
numofsoft <- nrow(progtime)
# 真实使用时长
realtime <- sum(progtime$time,na.rm=T)
return(list(id=as.character(id),day=as.character(day),
clock = as.numeric(clock),opentime=opentime,
numofsoft = numofsoft,
realtime= realtime,progtime=progtime))
}
所有的文件名都已经存在file.name变量中,用上面建立好的函数data.get来提取第一份文件中的信息 
> data.get(file.name[[1]])
$id
[1]"0143692D264FD906F10B8ECAB0F139D1"
 
$day
[1]"2012-05-07"
 
$clock
[1]12
 
$opentime
[1]7771
 
$numofsoft
[1]9
 
$realtime
[1]7610
 
$progtime
program time
1 360chrome.exe 1237
2 360leakfixer.exe 3
3 360Safe.exe 12
4 360sd.exe 20
5 explorer.exe 510
6 iexplore.exe 5473
7 liveupdate.exe 6
8 popup_QQ.exe 44
9 QQ.exe 305

用模拟来理解混合效应模型之一:random intercept model

$
0
0
混合效应模型(Mixed-effect Model)在之前文章提到过,但感觉仍是雾里看花。此番又研究了一些资料,准备来做一个系列讲讲清楚,也算是自己学习的一个总结。

普通的线性回归只包含两项影响因素,即固定效应(fixed-effect)和噪声(noise)。噪声是我们模型中没有考虑的随机因素。而固定效应是那些可预测因素,而且能完整的划分总体。例如模型中的性别变量,我们清楚只有两种性别,而且理解这种变量的变化对结果的影响。

那么为什么需要 Mixed-effect Model?因为有些现实的复杂数据是普通线性回归是处理不了的。例如我们对一些人群进行重复测量,此时存在两种随机因素会影响模型,一种是对某个人重复测试而形成的随机噪声,另一种是因为人和人不同而形成的随机效应(random effect)。如果将一个人的测量数据看作一个组,随机因素就包括了组内随机因素(noise)和组间随机因素(random effect)。这种嵌套的随机因素结构违反了普通线性回归的假设条件。


你可能会把人员ID(组间的随机效应)看作是一种分类变量放到普通线性回归模型中,但这样作是得不偿失的。有可能这个factor的level很多,可能会用去很多自由度。更重要的是,这样作没什么意义。因为人员ID和性别不一样,我们不清楚它的意义,而且它也不能完整的划分总体。也就是说样本数据中的路人甲,路人乙不能完全代表总体的人员ID。因为它是随机的,我们并不关心它的作用,只是因为它会影响到模型,所以不得不考虑它。因此对于随机效应我们只估计其方差,不估计其回归系数。

混合模型中包括了固定效应和随机效应,而随机效应有两种方式来影响模型,一种是对截距影响,一种是对某个固定效应的斜率影响。前者称为 Random intercept model,后者称为 Random Intercept and Slope Model。Random intercept model的函数结构如下:

Yij = a0 + a1*Xij +  bi + eij

a0: 固定截距
a1: 固定斜率
b: 随机效应(只影响截距)
X: 固定效应
e: 噪声

下在的代码就是人工生成这种数据,再用nlme包建模展示。

参考资料:
Regress by simulation
A very basic tutorial for performing linear mixed effects analyses


一份数据挖掘小书评

$
0
0
书看得多了,渐渐有了品味,所以看那些英文版的时候也不再有很膜拜的感觉。不过再差的书,总会有些许长处或教训,值得借鉴。下面列出一些在数据挖掘实现方面的书,主要是基于R和python的。


  • Data mining with R Learning with Case studies: 我的启蒙书,很好的案例教学,这种书应该出更多些。
  • Data Mining Applications with R: 风格类似上面,多人合作的案例讲解,非常不错,就是每个例子略为简短了一点。
  • Machine Learning for Hackers: 也是以案例为主,但是内容质量不能保持在同一水准上,代码讲的比较细。
  • An Introduction to Statistical Learning: 比较系统的讲解了统计学习的内容,以及相应的R包函数,优点在于有习题。
  • Machine Learning with R: 同样是系统的列出各机器学习算法对应的R包函数,直观理解很好,而且讲了一些caret包的使用。比较新的书。
  • Applied predictive modeling: 对预测算法讲的最细,涉及R包最多,由于作者是caret的开发者,所以要学习caret则必看此书。
  • Big Data Analytics with R and Hadoop: 刚出的大数据挖掘书籍,讲解了如何用RHadoop来整合R和hadoop,什么时候会有R和spark的书出来啊。

  • programming_collective_intelligence: 有些年头的书了,但确实是经典,原理讲的简洁,就讲python代码实现,喜欢这种风格。
  • Machine Learning in Action: 和上面风格类似,不过实现是主要基于python的numpy库,这样代码量要精简很多,也很好。
  • Python for data analysis: 主要讲pandas库,精彩例子不多,可以直接去看帮助文档。
  • Learning scikit-learn Machine Learning: 主要以scikit-learn扩展库为工具做机器学习,比较简单,可以直接去看帮助文档。
  • Building Machine Learning Systems with Python: 和上面那本类似,讲函数功能为主,原理直觉没涉及到。

R语言公开课在网易上线

$
0
0
对于R语言的初学者来讲,有一些视频教学的参考是很好的帮助。为此我们在网易云课堂上线了R语言免费教学视频。请猛戳这里
Viewing all 85 articles
Browse latest View live