.xlsx搜索xlsx打开内容动不了的问题,请问你解决了吗?我也遇到这情况

查看: 554|回复: 5
WORD中的文本框,搜索“替换表.xlsx”的A列替换为B列数据问题
阅读权限10
在线时间 小时
本帖最后由 csbixi 于
10:59 编辑
小弟第一次发帖求助
希望大大们帮忙,感谢万分
我用下面以前这个坛里的大大的按表替换宏,可以将WORD里的数据对应替换表A列,替换为B列数据,
但是WORD文本框内的数据不会替换,如何修改,使他可以操作?最好保持文本框属性,不然格式都变了。
Sub 按表替换()
'首先引用ms excel
'运行前关闭所有excel程序
Dim ex As Excel.Application, boo As Excel.Workbook, shee As Worksheet, i As Integer
Set ex = New Excel.Application
Set boo = ex.Workbooks.Open(&D:\替换表.xlsx&) '假如在D盘根目录
ex.Visible = True '设置EXCEL对象可见(或不可见)
Set shee = boo.Worksheets(1) '设置活动工作表
For i = 1 To .Range(&b65536&).End(xlUp).Row
ActiveDocument.Content.Find.Execute findtext:=.Range(&a& & i), replacewith:=.Range(&b& & i), Replace:=wdReplaceAll, Forward:=True '将word中含有的A列内容替换为B列内容
Set boo = Nothing
Set ex = Nothing
附件已经添加
10:58 上传
点击文件名下载附件
39.36 KB, 下载次数: 8
阅读权限95
在线时间 小时
上个附件吧 .....
阅读权限10
在线时间 小时
上个附件吧 .....
http://club.excelhome.net/thread--1.html
附件已经添加
阅读权限95
在线时间 小时
csbixi 发表于
附件已经添加
这是WordVBA操控excel的意思?发错板块了吗?
阅读权限10
在线时间 小时
这是WordVBA操控excel的意思?发错板块了吗?
额 是的没找到WORD的VBA
那我发OFFICE-WORD板块看看
阅读权限95
在线时间 小时
额 是的没找到WORD的VBA
那我发OFFICE-WORD板块看看
WORD VBA 没什么人气,只有duquancai等个别大神会去逛...
最新热点 /1
本活动是由微软(中国)有限公司发起,申请通过者可以得到Office 365企业级E3 试用账号,并享有全套Office 365客户端及云端高效、协作办公体验。 机会有限,先到先得!
玩命加载中,请稍候
玩命加载中,请稍候
Powered by
本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任! & & 本站特聘法律顾问:徐怀玉律师 李志群律师&figure&&img src=&https://pic4.zhimg.com/v2-a98bfef8deda9bcd49b2f3_b.jpg& data-rawwidth=&1116& data-rawheight=&535& class=&origin_image zh-lightbox-thumb& width=&1116& data-original=&https://pic4.zhimg.com/v2-a98bfef8deda9bcd49b2f3_r.jpg&&&/figure&&p&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&上文&/a&我们讨论到使用data.table包完成数据分析框架,遗留如下几个问题&/p&&ul&&li&增添列,另外一种删除列的方法,修改数据框&/li&&li&计算或分组计算时,可不可以一次对所有列进行计算,而不需要再每一列都指定(.SD)&/li&&li&DT中可不可以按照行名来提取(key)&/li&&li&普通合并数据框(改进了的函数,会在下一篇中介绍)&/li&&li&融合重铸&/li&&/ul&&p&本文介绍data.table包更深入的使用方法,顺带解决上述问题,下面是本文目录&/p&&ul&&li&key的使用&/li&&li&融合重铸的深入使用和改进&/li&&li&特殊符号如.N .SD := 等&/li&&li&高效读写文件函数及参数解释&/li&&/ul&&h2&Key&/h2&&p&&b&数据集创建&/b&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&name1 &- c(&Bob&,&Mary&,&Jane&,&Kim&)
name2 &- c(&Bob&,&Mary&,&Kim&,&Jane&)
weight &- c(60,65,45,55)
height &- c(170,165,140,135)
birth &- c(&1990-1&,&1980-2&,&1995-5&,&1996-4&)
accept &- c(&no&,&ok&,&ok&,&no&)
library(data.table)
dft &- data.table(name1,weight,height,accept)
&/code&&/pre&&/div&&p&&b&DT数据框的行名及key的介绍&/b&&/p&&p&之前提到过提取时没有使用行名提取这个方法,这是因为data.table没有行名,如果硬要说有,那就是1234,而且不能修改,也不能根据行名来做提取等操作。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&rownames(dft) # &1& &2& &3& &4&
rownames(dft) &- letters[1:4]
rownames(dft) # &a& &b& &c& &d&
dft # 虽然上面rownames改过来了,但是这样输出发现还没有变
# dft[&a&,&weight&] # 报错,无法根据行名提取
dft[1,&weight&] # 使用行数才可以
&/code&&/pre&&/div&&p&这不是data.table的漏洞,而是因为它有更强大的操作,根本就不需要使用行名。具体的使用方法是,把data.frame的行名当成一列读进去,通过设置key来指定该列为行名。这样做的好处是,不止可以指定这一列,任意一列都可以,还可以指定多列,我们下面来看一看。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&ndt &- copy(dft) # 为了和原数据框对比,创建一个新的
setkey(ndt,name1)
ndt # 发现数据框自动按照name1这一列进行排序了
# 如果想去掉key,则setkey(ndt,NULL)
# 实现通过行名提取
ndt[&Bob&,weight]
ndt[&Bob&,&weight&]
ndt[&Bob&,2]
dft[&Bob&,2,on=&name1&] # key 相当于使用了on
ndt[&Bob&]
setkey(ndt, weight)
ndt[60] # 认为是提取第60行
ndt[.(60)] # 下面两个才是提取weight为60的行
ndt[J(60)]
&/code&&/pre&&/div&&p&当我们把data.frame数据框转化成data.table时,默认抛弃行名,不过我们也可以用一个参数保留行名成为新的一列&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&df1 &- data.frame(weight,height,row.names = name1)
dt1 &- as.data.table(df1)
dt2 &- as.data.table(df1,keep.rownames=T) # 将原来数据框中的行名当成一列,列名为rn
as.data.table(df1,keep.rownames = &rownames&) # 自己指定新增列的列名
&/code&&/pre&&/div&&p&&b&设置key时还有另外一个函数setkeyv&/b&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&name1 &- &weight&
setkey(ndt,name1) # 设置name1这一列为key
ndt # 观察这里的排序和下面一个的区别
setkeyv(ndt,name1) # 设置name1这个变量指向的weight这一列为key
setkey(ndt,name1,weight) # 设置两个key
setkeyv(ndt,c(&name1&,&weight&))
&/code&&/pre&&/div&&p&这里注意到数据框会自动按照设置key的列进行排序&/p&&p&&b&检查key的函数&/b&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&haskey(ndt) # 返回TF值,检查是否有Key
key(ndt) # 检查它的key是什么
&/code&&/pre&&/div&&p&&b&使用key来辅助计算&/b&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&setkey(ndt,accept)
ndt[&ok&,sum(weight)] # 指定计算accept为ok的weight之和
ndt[c(&ok&,&no&),sum(weight)] # 全部合在一起算
ndt[c(&ok&,&no&),sum(weight),by=.EACHI] # 分类算
ndt[accept,sum(weight),by=.EACHI] # 每一类计算完,保留所有行输出
ndt[unique(accept),sum(weight),by=.EACHI] # 只显示和类数相同的行
ndt[,sum(weight),by=accept] # 上面等价于分组计算
&/code&&/pre&&/div&&p&我们可以发现,key的作用相当于设定on参数。计算时使用key,再指定计算哪些行,by=.EACHI,可以实现和分组计算一样的功能。&/p&&p&&b&设置多个key&/b&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# 设置多个key,可以对多列进行筛选
setkey(ndt,name1,weight)
ndt[.(&Kim&,50:60)] # 不匹配的全部显示NA
ndt[.(&Kim&,50:60),nomatch=0] # 不匹配的删除掉
ndt[.(&Kim&,50:60),roll=T] # 没有信息的用上面的添
ndt[.(&Kim&,50:60),roll=Inf] # 和上一条一样
ndt[.(&Kim&,50:60),roll=-Inf] # 没有信息的用下面的添
ndt[!&Kim&]
ndt[!.(&Kim&,56)]
&/code&&/pre&&/div&&h2&融合重铸&/h2&&p&data.table包改写了reshape2包中的融合重铸功能。加载了data.table包之后,不需要加载reshape2包,但是它的所有用法都可以照常使用。而data.table不仅运行速度更快,而且增加了一些reshape2包没有的功能,melt和dcast函数都有改进。&/p&&p&&b&melt&/b&&/p&&p&先来看一下两个包中的函数的帮助文档,在控制台输入 ?melt 会发现这两个包中都有这个函数,下面是函数参数&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# reshape2包中处理data.frame的melt函数
#(在页面中点击melt.data.frame,这涉及到R语言中的泛函,我们以后会专门讲解)
# 现在理解就是当接的data是数据框时,使用 melt.data.frame这个函数
melt(data, id.vars, measure.vars,
variable.name = &variable&, ..., na.rm = FALSE, value.name = &value&,
factorsAsStrings = TRUE)
# data.table包中的melt函数
melt(data, id.vars, measure.vars,
variable.name = &variable&, value.name = &value&,
..., na.rm = FALSE, variable.factor = TRUE,
value.factor = FALSE,
verbose = getOption(&datatable.verbose&))
&/code&&/pre&&/div&&p&读者如果看过我的上一篇讲&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&融合重铸的文章&/a&会发现,这里的很多参数我都没有使用到,在这里我会用它们实现更多的功能。下面我们列出三个主要功能,并总结每一个功能中两个包的差异&/p&&p&1.得到的数据是否转化为factor的问题&/p&&ul&&li&reshape2中的factorsAsStrings参数可以控制value列是否为因子型,而variable列则自动为因子型&/li&&li&data.table中通过variable.factor和value.factor分别控制两列是否为因子型&/li&&li&明显可以看出data.table的使用更灵活,更方便&/li&&/ul&&p&2.多种数据类型融合问题&/p&&p&之前我们遇到的问题都是被融合的数据是同样的数据类型,比如都是整数或都是字符串,现在我们要面对的是很多不同数据类型的数据框。这里我们使用data.table包中例子里创建的数据框&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&set.seed(45)
DT &- data.table(
i_1 = c(1:5, NA),
i_2 = c(NA,6,7,8,9,10),
f_1 = factor(sample(c(letters[1:3], NA), 6, TRUE)),
f_2 = factor(c(&z&, &a&, &x&, &c&, &x&, &x&), ordered=TRUE),
c_1 = sample(c(letters[1:3], NA), 6, TRUE),
d_1 = as.Date(c(1:3,NA,4:5), origin=&&),
d_2 = as.Date(6:1, origin=&&))
DT[, l_1 := DT[, list(c=list(rep(i_1, sample(5,1)))), by = i_1]$c]
DT[, l_2 := DT[, list(c=list(rep(c_1, sample(5,1)))), by = i_1]$c]
i_1 i_2 f_1 f_2 c_1
1,1 b,b,b,b
&/code&&/pre&&/div&&p&我们可以看到,这个数据框中各列的数据类型是不相同的,总结一下是这样&/p&&ul&&li&i前缀的列是数值型&/li&&li&f前缀的列是因子型&/li&&li&c前缀的列是字符型&/li&&li&d前缀的列是时间型&/li&&li&l前缀的列是列表&/li&&/ul&&p&我们如果直接用一条命令保留前两列&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&melt(DT, id=c(&i_1&,&i_2&))
melt(DT, id=1:2)
&/code&&/pre&&/div&&p&其他列融合在一起,就会出现warning,强制转换数据类型。这时就需要我们能够选择相同类型的数据融合在一起,也就是相同的前缀融合在一起。两个包都是使用了measure.vars参数来控制要被融合的列&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&melt(DT, id=1:2, measure=&f_1&) # 只选择f_1列来融合
melt(DT, id=c(&i_1&, &i_2&), measure=3) # 和上面一样
melt(DT, id=3:4, measure=c(&d_1&, &d_2&))
# 接list时,产生两列value,同时variable列不再显示原来的各列名,而是用123代替,因为有两列value,无法对应同一个列名
melt(DT, id=1:2, measure=list(3:4, c(&d_1&, &d_2&)))
&/code&&/pre&&/div&&p&(细心的读者可能会注意到参数明明是id.vars, measure.vars,为什么我使用时就用了id和measure,这是参数的模糊匹配功能,只要提取前面的字符,不会发生歧义,就能代表这个参数)&/p&&p&上面四行代码两个包中都可以使用,不过data.table包中提供了选择列更好的方法&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&melt(DT, id=1:2, measure=patterns(&^f_&, &^d_&), value.factor=TRUE)
melt(DT, id=1:2, measure=patterns(&l_&, &c_&), na.rm=TRUE)
&/code&&/pre&&/div&&p&使用patterns指定,将所有以f&i&开头的列融合在一列,d&/i&开头的列融合在一列,产生两列value。&/p&&p&特殊情况&/p&&ul&&li&如果id和measure两个参数只指定一个,则默认将剩余所有列全部赋予未指定的那个参数上&/li&&li&如果两个参数都不指定,则默认measure指定numeric/integer/logical类型数据,其余为id指定&/li&&/ul&&p&3.新列命名&/p&&p&融合之后得到一列自动命名为variable和value,如果我想自己指定名字,就使用variable.name和value.name两个参数,在这个功能上,两个包没有区别&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&melt(DT, id=3:4, measure=c(&d_1&, &d_2&)) # 默认
melt(DT, id=3:4, measure=c(&d_1&, &d_2&),variable.name=&newvar&,value.name=&newval&) # 指定
# 两列value时,只指定一个,自动添加123区分
melt(DT, id=1:2, measure=patterns(&l_&, &c_&), na.rm=TRUE, variable.name=&newvar&, value.name=&newval&)
melt(DT, id=1:2, measure=patterns(&l_&, &c_&), na.rm=TRUE, variable.name=&newvar&, value.name=c(&nv1&,&nv2&)) # 使用向量自己指定
&/code&&/pre&&/div&&p&&b&cast&/b&&/p&&p&我们还是用?dcast查看帮助文档,发现两个包中都有这个函数,其中reshape2包中还有acast函数,而data.table包中没有&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# reshape2中的函数
dcast(data, formula, fun.aggregate = NULL, ..., margins = NULL,
subset = NULL, fill = NULL, drop = TRUE,
value.var = guess_value(data))
# data.table中的函数
dcast(data, formula, fun.aggregate = NULL, sep = &_&,
..., margins = NULL, subset = NULL, fill = NULL,
drop = TRUE, value.var = guess(data),
verbose = getOption(&datatable.verbose&))
&/code&&/pre&&/div&&p&和melt一样,上一篇文章中我们没有深入了解函数的各种参数,这里我们通过这些参数来比较两个包中的重铸功能&/p&&p&1.两个包相同的参数margins/fill/drop/subset,相同的使用方法&/p&&ul&&li&margins=T或者字符串向量,可以对得到的矩阵的每行每列在使用该函数计算&/li&&li&fill当遇到缺失值时如何填充问题&/li&&li&drop是否要去除掉不匹配的行,即全是NA的行&/li&&li&subset提取结果的一部分进行展示&/li&&/ul&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&DT &- data.table(v1 = rep(1:2, each = 6),
v2 = rep(rep(1:3, 2), each = 2),
v3 = factor(rep(c(1,3),6),levels=1:3),
v4 = rnorm(6))
# margins参数
dcast(DT,v1~v2,mean) # 生成2*3的矩阵,默认选择v4作为value计算
dcast(DT,v1~v2,mean,margins=T) # 3*4的矩阵,多出了对每行每列求的均值
dcast(DT,v1~v2,mean,margins=&v1&) # 只每列求均值
dcast(DT,v1~v2,mean,margins=&v2&) # 只每行求均值
# drop 参数
# v3因子型,2没有出现过,在融合时还会与其他列进行匹配,就会出现一行全是NA的情况
dcast(DT,v1+v3~v2,drop=F)
dcast(DT,v1+v3~v2,drop=T)
# fill参数
dcast(DT,v1+v3~v2,drop=F,fill=0) # 是NA的地方填充0
# subset参数
dcast(DT,v1~v2,mean)
dcast(DT,v1~v2,mean,subset=.(v3==1)) # 挑选v3是1的出来计算
dcast(DT,v1~v2,mean,subset=.(v1==1)) # 计算完挑选v1是1的出来
dcast(DT,v1~v2,mean,subset=.(v2==1)) # 计算完挑选v2是1的出来
dcast(DT,v1~v2,mean,subset=.(v1==1&v3==1)) # 挑选v3是1的出来计算,之后挑选v1是1的来展示
&/code&&/pre&&/div&&p&2.value.var参数&br&之前那篇讲reshape2包的文章中,value正好只有一列,但当有多列可以作为value时,如果不加以指定,计算的结果可能不是我们想要的&/p&&p&运行了上面代码的读者也会发现,每次输出结果时都会打印出如今选用的作为value的列是什么,我们如果想要自己指定哪一列作为value,就要用value.var参数&/p&&p&在这个参数的使用上,data.table包比reshape2包功能更强大&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# 两个包都可以这样使用
DT &- data.table(v1 = rep(1:2, each = 6),
v2 = rep(rep(1:3, 2), each = 2),
v3 = factor(rep(c(1,3),6),levels=1:3),
v4 = rnorm(6))
dcast(DT,v1~v3,mean) # 默认使用v4来计算
dcast(DT,v1~v3,mean,value.var=&v2&) # 指定v2作为value来计算
dcast(DT,v1~v3,mean,value.var=&v4&) # 使用v4和默认的结果相同
&/code&&/pre&&/div&&p&下面是data.table包独有的功能&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&dcast(DT,v1~v3,mean,value.var=c(&v4&,&v2&)) # v3中的元素分别和v2和v4组合,生成四列
dcast(DT,v1~v3,fun=list(sum, mean),value.var=&v2&) # 同时使用两种计算函数生成四列
dcast(DT,v1~v3,fun=list(sum, mean),value.var=c(&v4&,&v2&)) # 二者结合,生成8列
dcast(DT,v1~v3,fun=list(sum, mean),value.var=list(&v4&,&v2&)) # v4的使用sum,v2的使用mean,生成4列
&/code&&/pre&&/div&&h2&特殊符号&/h2&&p&&b&添加、更新和删除 := 符号&/b&&/p&&p&这个符号可以实现在本身直接更改,而无需产生一个新的数据框,再赋值给原本相同的变量名&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&dft &- data.table(name1,weight,height,accept)
dft[,u:=1] # 添加一个全是1的列
dft[,height:=1:4] # 更改height列
dft[,c(&accept&,&height&):=.(1:4,2:5)] # 作用于多个列
dft[,`:=`(m=1:4,n=3:6)] # 使用:=函数的真正调用方式
dft[,weight:=NULL] # 删除weight列
dft[,c(&m&,&n&):=NULL] # 删除多列
dft[2,height:=22][] # 只修改一个值,加一个[]返回得到的数据框
dft &- data.table(name1,weight,height,accept)
dft[&Bob&,accept:=&yes&,on=&name1&] # 通过逻辑判断修改
dft[,m:=mean(height),by=accept] # 增加一个列,这个列根据分组计算得出
# 注意一点
dft[name1==&Bob&][,height:=13][] # :=作用在提取之后的数据框,所以对原数据框没有改变
# 使用一个指向字符串的变量作为新名称
dft[,a:=1][] # 使用a作为列名
dft[,(a):=2][] # 使用aa作为列名
&/code&&/pre&&/div&&p&&b&.N&/b&&/p&&p&.N 代表行的数量,用by参数分组时则是每一组的行数量&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&dft[.N-1] # 返回倒数第二行
dft[,.N] # 返回数据框一共有几行(放在第二个参数位置表示计算并输出结果)
dft[,.N,by=accept] # 分组计算行数
&/code&&/pre&&/div&&p&&b&.SD&/b&&/p&&p&.SD 代表整个数据框,用by参数分组时则是每一组的数据框&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&dft &- data.table(name1,weight,height,accept)
dft[,print(.SD),by=accept]
dft[,head(.SD,1),by=accept]
dft[,.SD[2],by=accept]
dft[,lapply(.SD[,c(-1,-4)],sum),by=accept] # 分组多列计算
&/code&&/pre&&/div&&p&之前我们提到过,在DT中计算时输出的总是DT,但是如果我想返回多个矩阵怎么办,那就是使用嵌套list,像把矩阵压缩成一个元素一样,放在DT中。这里我们要用分组计算,返回矩阵。&/p&&p&下面这个例子是要对分组之后的每个数据框求covariance,计算得到的是列与列两两对应协方差矩阵。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&dft[,cov(.SD[,c(-1,-4)]),by=accept] # 矩阵被变成向量
l &- dft[,.(.(cov(.SD[,c(-1,-4)]))),by=accept]
&/code&&/pre&&/div&&p&这里解释一下连续嵌套两层list的理由&/p&&ul&&li&第一个list是指对每一组计算出来的结果矩阵,用list压缩成为可以放在DT中的元素&/li&&li&第二个list是将两个压缩了的元素整合在一起,使之成为一列。这一层中还可以加第二个元素,输出结果放在下一列展示,功能类似我们平时使用的计算多个结果l &- dft[,.(.(cov(.SD[,c(-1,-4)])),.(cor(.SD[,c(-1,-4)]))),by=accept]&br&l &- dft[,.(.(cov(.SD[,c(-1,-4)])),.(cor(.SD[,c(-1,-4)])),sum(weight)),by=accept]&br&dft[,.(m=mean(weight),s=sum(weight)),by=accept] # 外层list功能类似这里&/li&&/ul&&p&&b&.SDcols&/b&&/p&&p&.SDcols 指定.SD 代表的数据框包括哪些列&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&dft[,lapply(.SD[,c(-1,-4)],sum),by=accept]
# 下面4条命令和上面那条有相同的效果
dft[,lapply(.SD,sum),by=accept,.SDcols=c(&weight&,&height&)] #.SD中只包含这两列
dft[,lapply(.SD,sum),by=accept,.SDcols=weight:height] #用:指定这列到这列之间的所有列
dft[,lapply(.SD,sum),by=accept,.SDcols=2:3]
dft[,lapply(.SD,sum),by=accept,.SDcols=-c(1,4)]
&/code&&/pre&&/div&&p&&b&.I&/b&&/p&&p&.I 表示(分组后)每一行在原数据框中是第几行&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&dft[,.I[2],by=accept]
&/code&&/pre&&/div&&p&&b&.GRP&/b&&/p&&p&如果不使用by参数,则为1。使用by,则是组的计数(第一组的值是1,第二组是2)&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&dft[,grp:=.GRP][]
dft[,grp:=.GRP,by=accept][]
&/code&&/pre&&/div&&p&&b&串联操作,避免多余中间变量&/b&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&dft[weight&50][height&100][order(height)]
&/code&&/pre&&/div&&p&&b&%between% 范围&/b&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# 以下6个等价
dft[weight&=50&weight&=60]
dft[weight %between%c(50,60)]
dft[weight %inrange%c(50,60)]
dft[weight %between% list(rep(50,4),rep(60,4))]
dft[between(weight,50,60)]
dft[inrange(weight,50,60)]
&/code&&/pre&&/div&&p&&b&%like% 字符串中含有某个字符&/b&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&dft[name1%like%&a&]
&/code&&/pre&&/div&&h2&读写文件&/h2&&p&data.table包中的fread和fwrite读写文件的速度非常快,可以处理.txt.csv.dat等文件,下面是最基本的使用方法&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&dataw &- data.table(a=1:10,b=2:11)
fwrite(dataw,&dataw.csv&)
fwrite(dataw,&dataw.txt&)
fwrite(dataw,&dataw.dat&)
fread(&dataw.csv&) # 读取文件直接用字符串,赋予参数input
fread(file=&dataw.csv&) # 也可以赋予参数file
&/code&&/pre&&/div&&p&下面我们来详细讨论fread函数的各个参数&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&data = &A,B,C,D\n1,3,a,7\n2,4,6,NA\n2,,6,8\n&
cat(data) # 看一下这个数据长什么样
fread(data) # 第一行作为列名,生成一个data.table
str(fread(data))
str(fread(data, stringsAsFactors=T)) # stringsAsFactors默认F,自动将字符型转化为因子型
fread(data,col.names = letters[1:4]) # 改变列名
fread(data,verbose = T) # 显示一些信息
fread(data,data.table=F) # 生成data.frame
fread(data,showProgress = T) # 显示进度条
# data.table和showProgress都可以再options里面设置
fread(data) # header默认为&auto&,自动第一行作为列名
fread(data, header=F) # header第一行不作为行名
data1 = &1,1,a,7\n2,4,6,NA\n2,,6,8\n&
fread(data1) # 而当数据是这样时又不会自动将第一行作为列名
fread(data1,header=T) # 将第一行作为列名
fread(data1,header=T,check.names = T) # 检查,避免数字作为列名,避免两列名重复
# sep控制列与列之间用什么分隔。默认为&auto&,会自动寻找 空格 , ; : | \t 这些符号自动分列
# 当既有:又有空格时,当:很规整,若空格非常整齐,一个不落,:会被当成字符处理,否则就会把:当做分隔符
dataa1 = &a: b: c: d\n1: 2: 3: 4\n3: 4: 5:6& # 只有最后一个少空格
dataa2 = &a: b: c: d\n1: 2: 3: 4\n3: 4: 5: 6&
dataa3 = &a : b: c: d\n1: 2: 3: 4\n3: 4: 5: 6& # 前面加一个空格
fread(dataa1) # 按照:分,得到规整的数据
fread(dataa2) # 带有:
fread(dataa3) # 规整的数据
# 当改变sep的取值时
fread(data, sep=&\n&) # 此时读成一列
# nrow控制读取第几行,默认-1全部读取,0取列名,1只取第一行
fread(data, nrow=0)
fread(data, nrow=1) # 取第一行,一般用这个来检测读进来的形式是否正确
fread(data, nrow=3) # 取前三行
# na.strings默认将 ,, 这样没有值的、&NA& &N/A& &null& 当成缺失值
fread(data, na.strings=&a&) # 将读进去的字符&a&当成缺失值
str(fread(data, na.strings=NULL)) # 不将那些转化为缺失值
# autostart自动选择合适的行开始
data1 = &i,can,do,it\n A,B,C,D\n1,3,a,7\n2,4,6,NA\n2,,6,8\n&
data2 = &i,can,do,it\n friends are kind to\n A,B,C,D\n1,3,a,7\n2,4,6,NA\n2,,6,8\n&
fread(data1) # i,can,do,it 作为列名,(同时注意到,,没有变成NA,因为这列是字符串)
fread(data2) # 自动从A,B,C,D开始读取,将其作为列名
# skip跳过前几列不读,默认是0,自动从autostart点开始读取
data2 = &i,can,do,it\n friends are kind \n A,B,C,D\n1,3,a,7\n2,4,6,NA\n2,,6,8\n&
fread(data2) # 从ABCD开始读
fread(data2,skip=2) # skip=0,1,2结果相同,ABCD作为列名
fread(data2,skip=3) # 自动不将第一列作为列名
data3 = &i,can,do,it\n friends are kind \n A,B,C,D\nbob,mary,and,jane\n1,3,a,7\n2,4,6,NA\n2,,6,8\n&
fread(data3) # 从ABCD开始读
fread(data3,skip=&bob&) # 从bob这一行开始读,bob等作为列名
# select and drop
data = &A,B,C,D\n1,3,a,7\n2,4,6,NA\n2,,6,8\n&
fread(data, select=&A&) # 只取A这列
fread(data, select=c(&A&,&B&)) # 取AB列
fread(data, drop=&A&) # 取除了A这列
# colclasses
data = &A,B,C,D\n1,3,a,7\n2,4,6,NA\n2,,6,8\n&
fread(data)
str(fread(data,colClasses = c(A=&character&)))
str(fread(data,colClasses = c(A=&character&,B=&double&)))
str(fread(data,colClasses = list(character=c(&A&,&B&))))
str(fread(data,colClasses = list(character=1:3)))
fread(data,colClasses = list(NULL=1:3)) # 只保留第四列
&/code&&/pre&&/div&&h2&专栏信息&/h2&&p&专栏主页:&a href=&https://zhuanlan.zhihu.com/Data-AnalysisR& class=&internal&&Data Analysis&/a&&br&专栏目录:&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&目录&/a&&/p&&h2&文末彩蛋 &/h2&&p&这里介绍R语言几个行名列名函数的联系和区别&/p&&ul&&li&colnames和names&/li&&li&rownames和row.names&/li&&/ul&&p&这两对区别如下&/p&&ul&&li&names和colnames的区别在于,作用于数据框时二者相同,作用于矩阵时names无效&/li&&li&rownames和row.names基本上没差别a &- data.frame(a=1:4,b=letters[1:4])&br&ma &- as.matrix(a)&br&names(a) # &a& &b&&br&colnames(a) # &a& &b&&br&names(ma) # NULL&br&colnames(ma) # &a& &b&&br&rownames(a) #
&1& &2& &3& &4&&br&row.names(a) # &1& &2& &3& &4&&br&rownames(ma) # NULL&br&row.names(ma) # NULL&/li&&/ul&&p&&/p&
我们讨论到使用data.table包完成数据分析框架,遗留如下几个问题增添列,另外一种删除列的方法,修改数据框计算或分组计算时,可不可以一次对所有列进行计算,而不需要再每一列都指定(.SD)DT中可不可以按照行名来提取(key)普通合并数据框(改进了的函…
&figure&&img src=&https://pic3.zhimg.com/v2-b1efeab42ecb0cf0cc23613_b.jpg& data-rawwidth=&548& data-rawheight=&565& class=&origin_image zh-lightbox-thumb& width=&548& data-original=&https://pic3.zhimg.com/v2-b1efeab42ecb0cf0cc23613_r.jpg&&&/figure&&p&曾经有网友问我如何读取磁盘中数个文件的数据,并把这些数据合并到一张数据表中。这期就跟大家讲讲如何完成如下四种情况的文件批量读取:&/p&&br&&p&&strong&1、对于文件名有规律的情况&/strong&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-9c6dc147d4d2fad6fa8c8_b.jpg& data-rawwidth=&579& data-rawheight=&227& class=&origin_image zh-lightbox-thumb& width=&579& data-original=&https://pic3.zhimg.com/v2-9c6dc147d4d2fad6fa8c8_r.jpg&&&/figure&&p&&strong&解决方案:&/strong&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# 设置R的工作空间
setwd('D:\\data file\\data1')
#res &- NULL
# 初始化数据框,用于后面的数据合并
data1 &- data.frame()
#通过循环完成数据合并
for (i in 1:4){
# 构造数据路径
path &- paste0(getwd(),'\\','test',i,'.xlsx')
#res &- c(res,path)
# 读取并合并数据
data1 &- rbind(data1,read_excel(path = path))
&/code&&/pre&&/div&&p&&strong&2、对于文件名没有规律的情况&/strong&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-ecb645f1b91c026decc66e5_b.jpg& data-rawwidth=&516& data-rawheight=&222& class=&origin_image zh-lightbox-thumb& width=&516& data-original=&https://pic1.zhimg.com/v2-ecb645f1b91c026decc66e5_r.jpg&&&/figure&&p&&strong&解决方案:&/strong&&br&&/p&&p&# 设置工作空间&/p&&p&setwd('D:\\data file\\data2')&/p&&p&# 读取该工作空间下的所有文件名&/p&&p&filenames &- dir()&/p&&p&# 初始化数据框,用于后面的数据合并&/p&&p&data2 &- data.frame()&/p&&p&#通过循环完成数据合并&/p&&p&for (i in filenames){&/p&&p&# 构造数据路径&/p&&p&
path &- paste0(getwd(),'\\',i)&/p&&p&
#res &- c(res,path)&/p&&p&# 读取并合并数据&/p&&p&
data2 &- rbind(data2,read_excel(path = path))&/p&&p&}&/p&&br&&p&&strong&3、对于文件名没有规律的情况,并且只读取某做后缀的文件&/strong&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-fe90c9fb13bac5f938a18_b.jpg& data-rawwidth=&546& data-rawheight=&275& class=&origin_image zh-lightbox-thumb& width=&546& data-original=&https://pic4.zhimg.com/v2-fe90c9fb13bac5f938a18_r.jpg&&&/figure&&br&&p&&strong&解决方案:&/strong&&br&&/p&&p&# 设置工作空间&/p&&p&setwd('D:\\data file\\data3')&/p&&p&# 读取该工作空间下的所有文件名&/p&&p&filenames &- dir()&/p&&p&# 通过正则,获取所有xlsx结尾的文件名&/p&&p&filenames2 &- grep('\\.xlsx', filenames, value = TRUE)&/p&&p&# 初始化数据框,用于后面的数据合并&/p&&p&data3 &- data.frame()&/p&&p&#通过循环完成数据合并&/p&&p&for (i in filenames2){&/p&&p&# 构造数据路径&/p&&p&
path &- paste0(getwd(),'\\',i)&/p&&p&
#res &- c(res,path)&/p&&p&# 读取并合并数据&/p&&p&
data3 &- rbind(data3,read_excel(path = path))&/p&&p&}&/p&&br&&p&&strong&4、文件内容结构不一致,但变量名称一致&/strong&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-c9f38ce52006dfb158ef1_b.jpg& data-rawwidth=&391& data-rawheight=&347& class=&content_image& width=&391&&&/figure&&br&&p&&strong&解决方案&/strong&&br&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# 加载第三方扩展包,用于编写SQL语句
library(sqldf)
# 设置工作空间
setwd('D:\\data file\\data4')
# 读取该工作空间下的所有文件名
filenames &- dir()
# 通过正则,获取所有xlsx结尾的文件名
filenames2 &- grep('\\.xlsx', filenames, value = TRUE)
# 初始化数据框,用于后面的数据合并
data4 &- data.frame()
#通过循环完成数据合并
for (i in filenames2){
# 构造数据路径
path &- paste0(getwd(),'\\',i)
#res &- c(res,path)
# 使用read_excel函数读取xlsx文件
data &- read_excel(path = path)
# 使用sqldf函数编写SQL语句,并把结果合并起来
data4 &- rbind(data4, sqldf(&select id,name,gender,age from data&))
&/code&&/pre&&/div&&br&&p&以上四种情况是日常工作中最为常见的,这里通过R语言完成了这几种批量读取数据的落地,希望可以帮助到需要的朋友。&/p&&br&&p&下期预告:SVM理论与实战&/p&&p&----------------------------------------------&/p&&blockquote&&p&作者:刘顺祥&/p&&p&出处:&a href=&https://link.zhihu.com/?target=https%3A//ask.hellobi.com/blog/lsxxx2011& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&刘顺祥博客&/a&&/p&&p&公众号:每天进步一点点2015&/p&&/blockquote&&p&&b&大家也可以加小编微信:tswenqu(备注:知乎),进R语言中文社区 交流群,可以跟各位老师互相交流。玩R的伙伴都在里面的,一起进来多交流&/b&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-1c7f23cb04_b.jpg& data-rawwidth=&353& data-rawheight=&66& class=&content_image& width=&353&&&/figure&&p&&b&官方公众号:R语言中文社区 (ID:R_shequ) 欢迎关注,持续连载。&/b&&/p&
曾经有网友问我如何读取磁盘中数个文件的数据,并把这些数据合并到一张数据表中。这期就跟大家讲讲如何完成如下四种情况的文件批量读取: 1、对于文件名有规律的情况解决方案:# 设置R的工作空间
setwd('D:\\data file\\data1')
#res &- NULL
# 初始化数据…
&figure&&img src=&https://pic4.zhimg.com/v2-44fdc142fd3c08_b.jpg& data-rawwidth=&563& data-rawheight=&393& class=&origin_image zh-lightbox-thumb& width=&563& data-original=&https://pic4.zhimg.com/v2-44fdc142fd3c08_r.jpg&&&/figure&&p&&strong&前言&/strong&&/p&&p&程序员最痛苦的事情,不是每天加班写程序,而是每天加班读懂别人写的程序。&/p&&p&大多数程序员写的代码都没有考虑,如何让别人看着更方便!最后,实在忍受不了看其他人的丑陋代码时,有人开始制定代码编程规范;又有人实现代码的自动化排版工具。formatR就是这样的一个R语言自动化排版的工具。&/p&&p&&strong&目录&/strong&&/p&&ol&&li&formatR介绍&/li&&li&formatR安装&/li&&li&formatR的API介绍&/li&&li&formatR的使用&/li&&li&formatR的源代码解析&/li&&/ol&&h2&1. formatR介绍&/h2&&p&formatR包是一个实用的包,提供了R代码格式化功能,自动设置空格、缩进、换行等代码格式,让代码看起来更友好。&/p&&p&formatR的发布页:&a href=&https://link.zhihu.com/?target=http%3A//yihui.name/formatR/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&formatR - Yihui Xie | 谢益辉&/a&&/p&&h2&2. formatR安装&/h2&&p&系统环境&/p&&ul&&li&Win7 64bit&/li&&li&R: 3.0.1 x86_64-w64-mingw32/x64 b4bit&/li&&/ul&&p&formatR安装&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&~ R
& install.packages(&formatR&)
trying URL 'http://mirror.bjtu.edu.cn/cran/bin/windows/contrib/3.0/formatR_0.10.zip'
Content type 'application/zip' length 49263 bytes (48 Kb)
opened URL
downloaded 48 Kb
package ‘formatR’ successfully unpacked and MD5 sums checked
&/code&&/pre&&/div&&p&formatR加载&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&library(formatR)
&/code&&/pre&&/div&&h2&3. formatR的API介绍&/h2&&ul&&li&1). tidy.source: 对代码进行格式化&/li&&li&2). tidy.eval: 输出格式化的R代码和运行结果&/li&&li&3). usage: 格式化函数定义,并按指定宽度输出&/li&&li&4). tidy.gui: 一个GUI工具,支持编辑并格式化R代码&/li&&li&5). tidy.dir: 对某个目录下,所有R脚本进行格式化&/li&&/ul&&h2&3. formatR的使用&/h2&&ul&&li&1). tidy.source:以字符串形式,对代码格式化&/li&&li&2). tidy.source:以文件形式,对代码格式化&/li&&li&3). 格式化并输出R脚本文件&/li&&li&4). tidy.eval: 输出格式化的R代码和运行结果&/li&&li&5). usage: 格式化函数定义,并按指定宽度输出&/li&&li&6). tidy.gui: GUI工具,编辑并格式化R代码&/li&&li&7). tidy.dir: 对目录下,所有R脚本进行格式化&/li&&/ul&&p&&strong&1). 以字符串形式,对代码格式化&/strong&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&& tidy.source(text = c(&{if(TRUE)1 else 2; if(FALSE){1+1&, &## comments&, &} else 2}&))
if (FALSE) {
## comments
&/code&&/pre&&/div&&p&&strong&2). 以文件形式,对代码格式化&/strong&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&& messy = system.file(&format&, &messy.R&, package = &formatR&)
[1] &C:/Program Files/R/R-3.0.1/library/formatR/format/messy.R&
&/code&&/pre&&/div&&p&原始代码输出&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&& src = readLines(messy)
& cat(src,sep=&\n&)
# a single line of comments is preserved
# inline comments
x=2;print('Oh no... ask the right bracket to go away!')}
1*3 # one space before this comment will become two!
# 'short comments'
lm(y~x1+x2, data=data.frame(y=rnorm(100),x1=rnorm(100),x2=rnorm(100)))
### only 'single quotes' are allowed in comments
1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1
## comments after a long line
'a character string with \t in it'
## here is a long long long long long long long long long long long long long long long long long long long long comment
&/code&&/pre&&/div&&p&格式化后的代码输出&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&& tidy.source(messy)
# a single line of comments is preserved
if (TRUE) {
# inline comments
print(&Oh no... ask the right bracket to go away!&)
# one space before this comment will become two!
# 'short comments'
lm(y ~ x1 + x2, data = data.frame(y = rnorm(100), x1 = rnorm(100), x2 = rnorm(100)))
### only 'single quotes' are allowed in comments
1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1
## comments after a long line
&a character string with \t in it&
## here is a long long long long long long long long long long long long long long long long
## long long long long comment
&/code&&/pre&&/div&&p&&strong&3). 格式化并输出R脚本文件&/strong&&/p&&p&新建R脚本文件:demo.r&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&~ vi demo.r
a&-1+1;a;matrix(rnorm(10),5);
if(a&2) { b=c('11',832);&#a&2&;} else print('a is invalid!!')
&/code&&/pre&&/div&&p&格式化demo.r&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&& x = &demo.r&
& tidy.source(x)
a &- 1 + 1
matrix(rnorm(10), 5)
if (a & 2) {
b = c(&11&, 832)
} else print(&a is invalid!!&)
&/code&&/pre&&/div&&p&输出格式化结果到文件:demo2.r&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&& f=&demo2.r&
& tidy.source(x, keep.blank.line = TRUE, file = f)
& file.show(f)
&/code&&/pre&&/div&&figure&&img src=&https://pic1.zhimg.com/v2-ee0d2c2fd67ddd5c4655a30dad73e667_b.jpg& data-rawwidth=&464& data-rawheight=&222& class=&origin_image zh-lightbox-thumb& width=&464& data-original=&https://pic1.zhimg.com/v2-ee0d2c2fd67ddd5c4655a30dad73e667_r.jpg&&&/figure&&br&&p&&strong&4). tidy.eval: 输出格式化的R代码和运行结果&/strong&&/p&&p&以字符串形式,执行R脚本&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&& tidy.eval(text = c(&a&-1+1;a&, &matrix(rnorm(10),5)&))
a &- 1 + 1
matrix(rnorm(10), 5)
## [,1] [,2]
## [1,] 0..1725221
## [2,] 0..3434398
## [3,] -0..1138733
## [4,] 0..7286614
## [5,] 0..8288346
&/code&&/pre&&/div&&p&&strong&5). usage: 格式化函数定义,并按指定宽度输出&/strong&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&& var
function (x, y = NULL, na.rm = FALSE, use)
if (missing(use))
use &- if (na.rm)
&na.or.complete&
else &everything&
na.method &- pmatch(use, c(&all.obs&, &complete.obs&, &pairwise.complete.obs&,
&everything&, &na.or.complete&))
if (is.na(na.method))
stop(&invalid 'use' argument&)
if (is.data.frame(x))
x &- as.matrix(x)
else stopifnot(is.atomic(x))
if (is.data.frame(y))
y &- as.matrix(y)
else stopifnot(is.atomic(y))
.Call(C_cov, x, y, na.method, FALSE)
&bytecode: 0xfad030&
&environment: namespace:stats&
& usage(var)
var(x, y = NULL, na.rm = FALSE, use)
&/code&&/pre&&/div&&p&usage函数,只输出函数的定义。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&& usage(lm,width=30)
lm(formula, data, subset, weights,
na.action, method = &qr&, model = TRUE,
x = FALSE, y = FALSE, qr = TRUE,
singular.ok = TRUE, contrasts = NULL,
offset, ...)
&/code&&/pre&&/div&&p&usage的width参数,控制函数的显示宽度。&/p&&p&&strong&6). tidy.gui: GUI工具,编辑并格式化R代码&/strong&&/p&&p&安装gWidgetsRGtk2库&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&& install.packages(&gWidgetsRGtk2&)
also installing the dependencies ‘RGtk2’, ‘gWidgets’
trying URL 'http://mirror.bjtu.edu.cn/cran/bin/windows/contrib/3.0/RGtk2_2.20.25.zip'
Content type 'application/zip' length
bytes (13.0 Mb)
opened URL
downloaded 13.0 Mb
trying URL 'http://mirror.bjtu.edu.cn/cran/bin/windows/contrib/3.0/gWidgets_0.0-52.zip'
Content type 'application/zip' length 1212449 bytes (1.2 Mb)
opened URL
downloaded 1.2 Mb
trying URL 'http://mirror.bjtu.edu.cn/cran/bin/windows/contrib/3.0/gWidgetsRGtk2_0.0-82.zip'
Content type 'application/zip' length 787592 bytes (769 Kb)
opened URL
downloaded 769 Kb
package ‘RGtk2’ successfully unpacked and MD5 sums checked
package ‘gWidgets’ successfully unpacked and MD5 sums checked
package ‘gWidgetsRGtk2’ successfully unpacked and MD5 sums checked
&/code&&/pre&&/div&&p&打开GUI控制台&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&& library(&gWidgetsRGtk2&)
& g = tidy.gui()
&/code&&/pre&&/div&&p&我们输入一段不太好看的代码:&figure&&img src=&https://pic1.zhimg.com/v2-35e149fbdf1df_b.jpg& data-rawwidth=&630& data-rawheight=&319& class=&origin_image zh-lightbox-thumb& width=&630& data-original=&https://pic1.zhimg.com/v2-35e149fbdf1df_r.jpg&&&/figure&&/p&&br&&p&点击“转换”&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-3b0a2a4b3c8ca2a442d7e17ab692ca96_b.jpg& data-rawwidth=&630& data-rawheight=&308& class=&origin_image zh-lightbox-thumb& width=&630& data-original=&https://pic1.zhimg.com/v2-3b0a2a4b3c8ca2a442d7e17ab692ca96_r.jpg&&&/figure&&br&&br&&p&在GUI的编辑器中,R语言的代码被格式化了!&/p&&p&&strong&7). tidy.dir: 对dir目录下,所有R脚本进行格式化&/strong&&/p&&p&新建目录:dir&br&新建两个R脚本文件:dir.r, dir2.r&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&~ mkdir dir
~ vi dir.r
a&-1+1;a;matrix(rnorm(10),5);
~ vi dir2.r
if(a&2) { b=c('11',832);&#a&2&;} else print('a is invalid!!')
&/code&&/pre&&/div&&p&执行tidy.dir&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&& tidy.dir(path=&dir&)
tidying dir/dir.r
tidying dir/dir2.r
&/code&&/pre&&/div&&p&分别查看dir.r和dir2.r&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&~ vi dir.r
a &- 1 + 1
matrix(rnorm(10), 5)
~ vi dir2.r
if (a & 2) {
b = c(&11&, 832)
} else print(&a is invalid!!&)
&/code&&/pre&&/div&&p&我们发现不规则的代码,已经被格式化了!!&/p&&h2&5. formatR的源代码解析&/h2&&p&通过上面的使用,我们不难发现formatR包的核心函数,就是tidy.source函数,从github上面找到源代码:&a href=&https://link.zhihu.com/?target=https%3A//github.com/yihui/formatR/blob/master/R/tidy.R& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&yihui/formatR&/a&&/p&&p&我将在代码中增加注释:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&tidy.source = function(
source = 'clipboard', keep.comment = getOption('keep.comment', TRUE),
keep.blank.line = getOption('keep.blank.line', TRUE),
replace.assign = getOption('replace.assign', FALSE),
left.brace.newline = getOption('left.brace.newline', FALSE),
reindent.spaces = getOption('reindent.spaces', 4),
output = TRUE, text = NULL,
width.cutoff = getOption('width'), ...
## 判断输入来源为剪贴板
if (is.null(text)) {
if (source == 'clipboard' && Sys.info()['sysname'] == 'Darwin') {
source = pipe('pbpaste')
## 判断输入来源为字符串
source = textConnection(text); on.exit(close(source))
## 按行读取来源数据
text = readLines(source, warn = FALSE)
## 大小处理
if (length(text) == 0L || all(grepl('^\\s*$', text))) {
if (output) cat('\n', ...)
return(list(text.tidy = text, text.mask = text))
## 空行处理
if (keep.blank.line && R3) {
one = paste(text, collapse = '\n') # record how many line breaks before/after
n1 = attr(regexpr('^\n*', one), 'match.length')
n2 = attr(regexpr('\n*$', one), 'match.length')
## 注释处理
if (keep.comment) text = mask_comments(text, width.cutoff, keep.blank.line)
## 把输入的R代码,先转成表达式,再转回字符串。用来实现对每个语句的截取。
text.mask = tidy_block(text, width.cutoff, replace.assign && length(grep('=', text)))
## 对注释排版
text.tidy = if (keep.comment) unmask.source(text.mask) else text.mask
## 重新定位缩进
text.tidy = reindent_lines(text.tidy, reindent.spaces)
## 扩号换行
if (left.brace.newline) text.tidy = move_leftbrace(text.tidy)
## 增加首尾空行
if (keep.blank.line && R3) text.tidy = c(rep('', n1), text.tidy, rep('', n2))
## 在console打印格式化后的结果
if (output) cat(paste(text.tidy, collapse = '\n'), '\n', ...)
## 返回,但不打印结果
invisible(list(text.tidy = text.tidy, text.mask = text.mask))
&/code&&/pre&&/div&&p&&strong&Bug: 没有对”-&”进行处理&/strong&&/p&&p&在读源代码的过程中,发现有一个小问题,没有对”-&”进行处理,已经给作者提bug了。&br&&a href=&https://link.zhihu.com/?target=https%3A//github.com/yihui/formatR/issues/31& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&-& 符号处理的问题 · Issue #31 · yihui/formatR&/a&&/p&&p&bug测试代码:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&& c('11',832)-&x2
& tidy.source(text=&c('11',832)-&x2&)
c(&11&, 832) &- x2
& tidy.eval(text=&c('11',832)-&x2&)
c(&11&, 832) &- x2
Error in eval(expr, envir, enclos) : object 'x2' not found
&/code&&/pre&&/div&&p&BUG已修复:&br&作者回复:这个问题已经在R 3.0.2中修正了。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&& formatR::tidy.source(text=&c('11',832)-&x2&)
x2 &- c(&11&, 832)
& sessionInfo()
R version 3.0.2 ()
Platform: x86_64-pc-linux-gnu (64-bit)
[1] LC_CTYPE=en_US.UTF-8
LC_NUMERIC=C
[3] LC_TIME=en_US.UTF-8
LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_US.UTF-8
LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_US.UTF-8
[9] LC_ADDRESS=C
LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
attached base packages:
grDevices utils
loaded via a namespace (and not attached):
[1] formatR_0.10.3
&/code&&/pre&&/div&&p&formatR包提供的功能非常实用,特别是读别人写的不规范的代码的时候。建议各IDE厂商能把formatR,作为标准的格式化工具直接嵌入编辑器的工具里面。让我们把读别人的代码,也变成一件快乐的事情吧。&/p&&h2&&strong&作者介绍:&/strong&&/h2&&p&民生银行大数据中心数据分析师,前况客创始人兼CTO,10 年IT编程背景,获得多项SUN及IBM技术认证。丰富的互联网应用开发架构经验,精通R ,Java, Nodejs 多种编程语言,掌握大数据处理,数据挖掘等核心技术,有统计和金融的知识积累。熟悉金融二级市场、交易规则和投研体系。多次在互联网及数据分析大会中担任演讲嘉宾。著有《R的极客理想-工具篇》、《R的极客理想-高级开发篇》图书,新书《R的极客理想-量化投资篇》(即将出版),博客&a href=&https://link.zhihu.com/?target=http%3A//fens.me/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&粉丝日志&/a&, Alexa全球排名70k。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-beaef66fb0e68cedea7a4c76f18625c4_b.jpg& data-rawwidth=&1860& data-rawheight=&475& class=&origin_image zh-lightbox-thumb& width=&1860& data-original=&https://pic1.zhimg.com/v2-beaef66fb0e68cedea7a4c76f18625c4_r.jpg&&&/figure&&p&博客专栏:&a href=&https://link.zhihu.com/?target=https%3A//ask.hellobi.com/blog/fensme& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&张丹的博客专栏&/a&&/p&&p&&b&大家也可以加小编微信:tswenqu(备注:知乎),进R语言中文社区 交流群,可以跟各位老师互相交流&/b&&/p&
前言程序员最痛苦的事情,不是每天加班写程序,而是每天加班读懂别人写的程序。大多数程序员写的代码都没有考虑,如何让别人看着更方便!最后,实在忍受不了看其他人的丑陋代码时,有人开始制定代码编程规范;又有人实现代码的自动化排版工具。formatR就是…
&figure&&img src=&https://pic3.zhimg.com/v2-57bb1f92bf2a05bb40ec7b5_b.jpg& data-rawwidth=&574& data-rawheight=&357& class=&origin_image zh-lightbox-thumb& width=&574& data-original=&https://pic3.zhimg.com/v2-57bb1f92bf2a05bb40ec7b5_r.jpg&&&/figure&&h2&文前摘要&/h2&&ul&&li&&p&mlr包简介&/p&&/li&&li&&p&运用mlr包实现美国不同收入人群数据特征选择&/p&&/li&&li&&p&运用mlr包实现美国不同收入人群分类预测&/p&&/li&&li&&p&相似机器学习CARET、DMwR包与MLR包比较&/p&&/li&&/ul&&h2&mlr包介绍&/h2&&p& 一直以来R都以自诩数据分析和统计建模见长,然而一直以来对机器学习中的算法都是各个种类的包“占山为王”,以擅长某类具体机器学习算法游行天下,比如运用e1071包实现贝叶斯及SVM算法,运用rpart包实现决策树算法等等。而这就带来一个无法避免的问题:需要数据侠们记住每一种算法对应的R包,显然这增加了对R的学习成本。同时R粉也会无比羡慕python粉,只需要一个sklearn库就可以几乎解决机器学习算法所有涉及内容。但是这一切都因为mlr包的到来而悄然改变。&br&
mlr包提供了一个一般化、清洗易用涵盖分类、回归、生存分析、聚类等功能的可扩展机器学习工作框架。它也提供了一个对于160多个基础学习包的统一接口,包括了“元算法”和模型选择技术,并扩展了基本学习算法的功能,比如超参数调参、特征选择、集成结构等。同时并行化计算也是其天然支持的一项技能。(引用于mlr:Machine Learning in R)。
看到这样的介绍是否眼前一亮,对的,mlr包似乎有想一统江湖味道,那么这个包如何使用,有哪些优点呢,咱们通过一个案例先来一睹为快。&/p&&h2&mlr包基本思想&/h2&&p&
mlr包对待各种学习算法和模型实现,有个基本的思路即:Create a Task,Make a learner,Train then.所有所有的分析都以此为基础进行构建。&br&以美国不同收入人群数据为例,目的是对收集好的30万美国人群基本资料,预测人群是否为高收入人群(&50000美元).&/p&&h2&读取数据和查看&/h2&&p&
我们读取了美国人群数据,train数据集,test数据集99762*41.&br&
通过mlr包中的summarizeColumns()及sumizeLEVELS()函数可以对数据集进行查看,可以直接浏览所有变量的缺失值、均值、极值等基本信息和因子水平情况等,如下图:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&summarizeColumns(train)
summarizeColumns(train)[, &nlevs&]
summarizeLevels(train)$income_level
unique(train$income_level)
&/code&&/pre&&/div&&figure&&img src=&https://pic2.zhimg.com/v2-87f36fd9e1_b.png& data-rawwidth=&693& data-rawheight=&330& class=&origin_image zh-lightbox-thumb& width=&693& data-original=&https://pic2.zhimg.com/v2-87f36fd9e1_r.jpg&&&/figure&&br&&h3&特征工程&br&&/h3&&p&
mlr包进行特征工程,如对变量重要性排序等操作,首先是通过makeClassifTask()创建一个用于分类的Task,其他回归等目的有相应的创建函数。通过removeConstantFeatures()函数丢弃零变量,generateFilterValuesData()函数可选择相应的method进行特征重要性排序(这里运用信息增益衡量),并可绘图实现。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# 合并数据集
train &- cbind(num_train, cat_train)
test &- cbind(num_test, cat_train)
# 创建task
train.task &- makeClassifTask(data = train, target = &income_level&)
test.task &- makeClassifTask(data = test, target = &income_level&)
# 丢弃零变量
train.task &- removeConstantFeatures(train.task)
test.task &- removeConstantFeatures(test.task)
# #变量重要性排序
var_imp &- generateFilterValuesData(train.task, method = &information.gain&)
var_imp &- generateFilterValuesData(train.task, method = c(&information.gain&))
plotFilterValues(var_imp, feat.type.cols = TRUE)
&/code&&/pre&&/div&&figure&&img src=&https://pic1.zhimg.com/v2-a9dd3f8afaa8_b.png& data-rawwidth=&646& data-rawheight=&377& class=&origin_image zh-lightbox-thumb& width=&646& data-original=&https://pic1.zhimg.com/v2-a9dd3f8afaa8_r.jpg&&&/figure&&br&&h3&选择算法&br&&/h3&&p&
进行完特征工程等数据清洗工作,我们就开始建模的过程,在建立模型之前,如何快速选择合适的学习算法又是重中之重,那么mlr给出了非常人性的方法。通过listLearners()可以查看所有涉及到的算法以及相应的数据要求,可见下图:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&a &- listLearners(&classif&)
head(a, 10)
# 指定条件,选择适用的算法
listLearners(&classif&, &twoclass&)[c(&class&, &package&)]
&/code&&/pre&&/div&&figure&&img src=&https://pic1.zhimg.com/v2-c419c8d33f1cc2adce9f55c_b.png& data-rawwidth=&731& data-rawheight=&149& class=&origin_image zh-lightbox-thumb& width=&731& data-original=&https://pic1.zhimg.com/v2-c419c8d33f1cc2adce9f55c_r.jpg&&&/figure&&br&&h3&朴素贝叶斯&br&&/h3&&p&
我们可以以贝叶斯算法为例,运用mlr包实现机器学习算法的构建。根据“Create a Task,Make a learner,Train”原则,在前面已经完成分类Task任务之后,我们通过makeLearner()函数构建贝叶斯模型。同时通过makeResampleDesc()进行交叉验证.模型构建完成后,就可以通过trainLearner()函数和predict()函数实现训练和预测功能了。最终模型结果F score为0.819&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&naive_learner &- makeLearner(&classif.naiveBayes&, predict.type = &response&)
naive_learner$par.vals &- list(laplace = 1)
# 3folds交叉验证
folds &- makeResampleDesc(&CV&, iters = 3, stratify = TRUE)
# 交叉验证函数fun_cv &- function(a) {
crv_val &- resample(naive_learner, a, resampling = folds, measures = list(acc, tpr, tnr, fpr, fp, fn))
crv_val$aggr}fun_cv(train.task)
# 训练和预测
nB_models &- mlr::train(naive_learner, train.over)
nB_model &- trainLearner(naive_learner, train.over)
nB_predict &- predict(nB_models, test.task)
# 模型评估
nB_prediction &- nB_predict$data$response
# 混淆矩阵
dCM &- confusionMatrix(test$income_level, nB_prediction)
precision &- dCM$byClass[&Pos Pred Value&]
recall &- dCM$byClass[&Sensitivity&]
f_measure &- 2 * ((precision * recall)/(precision + recall))
&/code&&/pre&&/div&&h2&相似机器学习CARET、DMwR包与MLR包比较&br&&/h2&&p&
这是个最常见的整个机器学习的过程,而所有过程均在mlr包框架语法下实现。是不是很神奇呢。那么再来简单看看与CARET、DMwR包等相似机器学习算法集成包比较,mlr有什么优点呢!&br&
Caret包(Kuhn,2008),DMwR(Torgo,2010)仅支持分类和回归,CMA(Slawski et al., 2008)仅支持分类。相对功能都比较局限。MLR包的通用包装器机制是前面所有包所不具备的。虽然Caret包和CMA包融入了数据预处理和变量选择方法,但是MLR可以无缝同时用这些方法进行调节(Koch et al., 2012)。仅仅MLR和RMINER和CMA包支持nested cross-validation。也只有MLR包和Caret包支持内生的bagging和并行计算。&br&
(引用于mlr:Machine Learning in R)。
综上所示,mlr是运用R实现机器学习算法必备的瑞士军刀。如想了解更多,可具体可参考&&a href=&http://link.zhihu.com/?target=https%3A//github.com/mlr-org/mlr& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&mlr-org/mlr&/a&&&/p&&br&&p&------------------------------------------&/p&&p&作者:余文华&/p&&p&专栏:&a href=&http://link.zhihu.com/?target=https%3A//ask.hellobi.com/blog/datasharing& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&乐享数据DataScientists的博客专栏&/a&&/p&&p&公众号:乐享数据DataScientists&/p&&br&&p&&b&大家也可以加小编微信:tsbeidou (备注:知乎),进R语言中文社区 交流群,可以跟各位老师互相交流&/b&&/p&
文前摘要mlr包简介运用mlr包实现美国不同收入人群数据特征选择运用mlr包实现美国不同收入人群分类预测相似机器学习CARET、DMwR包与MLR包比较mlr包介绍 一直以来R都以自诩数据分析和统计建模见长,然而一直以来对机器学习中的算法都是各个种类的包“占山为王…
&figure&&img src=&https://pic1.zhimg.com/v2-cce3f9d6a0ac76bf4e3e690_b.jpg& data-rawwidth=&658& data-rawheight=&377& class=&origin_image zh-lightbox-thumb& width=&658& data-original=&https://pic1.zhimg.com/v2-cce3f9d6a0ac76bf4e3e690_r.jpg&&&/figure&&h2&爬虫基础:Rcurl与XML包&/h2&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&
爬虫是一种利用代码(例如:R code或Python code)模拟浏览器访问(下载)页面并根据HTML结构筛选获取所需信息的一种工具。在R里面我们通常用Rcurl包实现前一半的功能(模拟浏览器访问页面),用XML包完成后一半功能(通过HTML树结构筛选提取信息)。
&/code&&/pre&&/div&&h2&Rcurl包访问页面&/h2&&h3&第一步:模拟浏览器行为&/h3&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&
若想用R语言模拟浏览器行为,就必须伪装报头。实际上,当我们用浏览器访问一个网页的时候,浏览器会像网页服务器发送一些指令。
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# 构造请求报头
cust_header = c(`User-Agent` = &Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/ Firefox/26.0&,
Accept = &text/html,application/xhtml+xml,application/q=0.9,*/*;q=0.8&,
`Accept-Language` = &en-us&, Connection = &keep-alive&)
&/code&&/pre&&/div&&h3&第二步:模拟访问&/h3&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&这个过程其实就是把指定的网页临时下载下来。两行代码就可以实现。
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&library(RCurl)
library(XML)
# 读取拉手深圳美食搜索
start_url = &http://shenzhen.lashou.com/cate/meishi&
# 读取PageSouce
pagesource &- getURL(start_url, httpheader = cust_header, .encoding = &utf-8&)
&/code&&/pre&&/div&&h2&XML包树结构筛选提取信息&/h2&&h3&第三步:整理HTML结构&/h3&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&
使用XML中的htmlTreeParse函数解析刚才得到的webpage变量(其中储存了HTML所爬取网页的代码)生成标准的HTML树形结构并赋值给pagetree变量。之后便可在XML中对该变量进行各种操作了。
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&pagetree &- htmlTreeParse(pagesource, encoding = &GB2312&, error = function(...) {}, useInternalNodes = TRUE, trim = TRUE)# 注意encoding
&/code&&/pre&&/div&&h3&第四步:定位节点&/h3&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&
在这里我们需要一点HTML的基础知识。HTML下的代码实际上是一个树级结构,是不同标签的层级嵌套。每一个标签以&x&开始,以&/x&结束。举个例子:
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&ul&
&div class=&first&&
&a href=&https://ask.hellobi.com/www.baidu.com& title=&百度&&链接1&/a&
&div class=&first&&
&a href=&https://ask.hellobi.com/www.sina.com& title=&新浪&&链接2&/a&
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&&body&与&/body&之间的内容为网页的正文部分,如果我们想获取两个&a&标签中的正文(“链接1”,“链接2”),可以利用如下代码进行定位,其中text()代表的是获取标签内的文本。乍一看,是不是和文件路径很像?
&/code&&/pre&&/div&&p&ul/li/div/a/text() &/p&&p&此外,我们也可以用利用两个具有相同的class属性值直接从开始定位,也即&/p&&p&div[@class='first']/a/text() 这两个写法在XML包中都是适用的。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&
一般会利用chrome浏览器右键-&查看源代码,也可以对想要查看的内容点击右键-&检查,这时候我们如果右键某一行,就可以鼠标右键-&copy-&selector或Xpath直接复制相应的层级定位。需要注意的是,我们还需将复制来的定位代码更换成XML包所能识别的格式。比如用属性值用单引号,“//”表示所有该类型节点等。
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&node&-getNodeSet(pagetree, &//div[contains(@class,&goods&)]//a[@class=&goods-name&]//text()&)
goods_name&-sapply(node,xmlValue)
&/code&&/pre&&/div&&h2&其他细节点&/h2&&h3&对于多页面的解析&/h3&&h4&解析页数&/h4&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# 解析页数
parseTotalPage &- function(pagesource) {
doc &- htmlParse(pagesource)
as.numeric(sapply(getNodeSet(doc, &//div[@class=\&page\&]/a[last()-1]/text()&),
xmlValue))}
&/code&&/pre&&/div&&h4&构造一个提取函数提取信息&/h4&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# 解析页面内容,获取门店名称、描述、优惠价,门店价
parseContent &- function(pagesource) {
doc &- htmlParse(pagesource)
goods_name &- sapply(getNodeSet(doc, &//div[contains(@class,\&goods\&)]//a[@class=\&goods-name\&]//text()&),
goods_text &- sapply(getNodeSet(doc, &//div[contains(@class,\&goods\&)]//a[@class=\&goods-text\&]//text()&),
price &- sapply(getNodeSet(doc, &//div[contains(@class,\&goods\&)]//span[@class=\&price\&]/text()&),
org_price &- sapply(getNodeSet(doc, &//div[contains(@class,\&goods\&)]//span[@class=\&money\&]/del/text()&),
result &- data.frame(goods_name, goods_text, price, org_price)}
&/code&&/pre&&/div&&h4&循环读取每一页面信息&/h4&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# 获取总页数和第一页内容
total_page &- parseTotalPage(pagesource)pageresults &- parseContent(pagesource)# 生成2-n页urlpage = 1:(total_page - 1)url_list = &&url_list[page] = paste0(&http://shenzhen.lashou.com/cate/meishi/page&, page +
# 循环读取url,并进行下载解析
for (url in url_list) {
pagesource &- getURL(url, httpheader = cust_header, .encoding = &utf-8&)
pageresult &- parseContent(pagesource)
pageresults &- rbind(pageresults, pageresult)}
# 输出结果到文件
write.table(pageresults, &result.txt&, row.names = FALSE)
&/code&&/pre&&/div&&h4&字符编码的改变&/h4&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# 查看encod编码类型
library(stringi)stri_enc_detect(names)
# 转换编码类型names &- iconv(name2, &UTF-8&, &gb2312&)
&/code&&/pre&&/div&&h4&删除冗余信息,字符串清理&/h4&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&to_remove &- paste(c(&\n&, &^\\s+|\\s+$&), collapse = &|&)
faddress &- gsub(to_remove, &&, faddress)
&/code&&/pre&&/div&&h4&最后给出了XML里常用的节点定位方法与代码&/h4&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# XML实例
library(XML)
url = &http://www.w3school.com.cn/example/xmle/books.xml&
doc = xmlTreeParse(url, useInternal = TRUE)
top = xmlRoot(doc)
# 选取所有 title 节点
nodes = getNodeSet(top, &/bookstore/book/title&)
# 选取第一个 book 的 title
nodes1 = getNodeSet(top, &/bookstore/book[1]/title&)
# 选取 price 节点中的所有文本
price = getNodeSet(doc, &/bookstore/book/price/text()&)
# 选取价格高于 35 的 price 节点
price1 = getNodeSet(doc, &/bookstore/book[price&35]/price&)
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()&)
&/code&&/pre&&/div&&h2&运用rvest包提取数据&/h2&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&
Rcurl和XML包进行爬虫,这个组合虽然功能强大,但是经常会出一点意想不到的小问题。于是更便捷的Rvest包登场,它真正的实现了快速爬取数据的目的。
&/code&&/pre&&/div&&h2&运用SelectorGadget插件快速定位&/h2&&h3&安装&/h3&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&
首先安装SelectorGadget插件,点击&https://cran.r-project.org/web/packages/rvest/vignettes/selectorgadget.html& 中的Installation,SelectorGadget链接。或&http://selectorgadget.com/& Chrome 扩展。
&/code&&/pre&&/div&&h3&使用&/h3&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&
点击插件后,在网页最下面会启动对话框,同时会有highlight(黄色)框框随鼠标滑动,当点击需要提取的信息时,选择框会变为绿色,SelectorGadget对话框将产生minimal CSS 选择语句。同时匹配语句的元素也会变黄,当再次点击黄色元素时,选择器变为红色,表示排除所选元素。当点击未标黄元素时,表示增加相应的元素,SelectorGadget对话框会随选择元素而发生变化。点击XPath时,会自动根据选择元素自动转换为xpath语法。
&/code&&/pre&&/div&&h2&rvest爬取数据&/h2&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&以爬取豆瓣数据为例:
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# 查看书的信息
library(rvest)
web &- read_html(&https://book.douban.com/top250?icn=index-book250-all&, encoding = &UTF-8&)
positions &- web %&%
html_nodes(&p.pl&) %&%
html_text()
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# 查看书的题目
position &- web %&%
html_nodes(&.pl2 a&) %&%
html_text()
# 查看encod编码类型
library(stringi)
stri_enc_detect(position)
# 转换编码类型
position &- iconv(position, &UTF-8&, &gb2312&)
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# 字符串清理 去掉多余的空格,“\n”等信息
to_remove &- paste(c(&\n&, &^\\s+|\\s+$&), collapse = &|&)position &- gsub(to_remove, &&, position)
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&
第一行是加载Rvest包。第二行是用“read_html函数读取网页信息(类似Rcurl里的getURL),在这个函数里只需写清楚网址和编码(一般就是UTF-8)即可第三行是获取节点信息。用%&%符号进行层级划分。web就是之前存储网页信息的变量,所以我们从这里开始,然后html_nodes()函数获取网页里的相应节点。在下面代码里我简单的重现了原网页里的一个层级结构。可以看到,实际上我们要爬取的信息在25个class属性为pl的&p&标签里的文本。
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&
[清] 曹雪芹 著 / 人民文学出版社 / 1996-12 / 59.70元
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&
而对于这样的结构,在htmlnodes()函数里的写法就是简单的&p.pl&,其中“.”表示class属性的值,如果是id属性则用“#”,如果大家学过CSS选择器就很好理解了,是完全一致的。
&/code&&/pre&&/div&&p&最后我们用html_text()函数表示获取文本信息,否则返回的是整个&p&&/p&&p&标签。总体上用以下一行代码就可以实现:&br&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&position &- web %&%
html_nodes(&p.pl&) %&%
html_text()
&/code&&/pre&&/div&&p&比较与XML获取节点的方法(如下行代码),其实二者是异曲同工的,只不过将“/”分隔换为了“%&%”,同时个别写法有些许调整。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&node &- getNodeSet(pagetree, &//p[@class='pl']/text()&)
&/code&&/pre&&/div&&p&最终如果我们打印出这个变量的内容,就会发现和上篇文章中的爬取内容是一致的。&/p&&p&Rvest这个包的说明文档里给出了一些其他例子:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&ateam &- read_html(&http://www.boxofficemojo.com/movies/?id=ateam.htm&)
# 两行代码分别获取了ateam这个网页里&center&标签里&td&的全部内容和&center&标签里&font&的全部内容
ateam %&% html_nodes(&center&) %&% html_nodes(&td&)
ateam %&% html_nodes(&center&) %&% html_nodes(&font&)
# 官方例子中还给出了获取特定序位的html标签的方法,用到了magrittr包里的extract2函数;以下两行代码都可以获得该网页中第一个&table&标签(由extract2(1)或`[[`(1)获取)中的所有&img&标签里的内容。
library(magrittr)
ateam %&% html_nodes(&table&) %&% extract2(1) %&% html_nodes(&img&)
ateam %&% html_nodes(&table&) %&% 1[[]] %&% html_nodes(&img&)
# 同理我们也可以获得网页里前两个&table&标签储存的所有&img&标签里的内容。
ateam %&% html_nodes(&table&) %&% 1:2[] %&% html_nodes(&img&)
ateam %&% html_nodes(&table&) %&% extract(1:2) %&% html_nodes(&img&)
&/code&&/pre&&/div&&p&参考资料:&/p&&p&1.知乎:【数据获取】爬虫利器Rvest包 &&a href=&https://zhuanlan.zhihu.com/p/?refer=rdatamining& class=&internal&&【数据获取】爬虫利器Rvest包 - 知乎专栏&/a&&&/p&&p&2.利用RCurl包完成自己感兴趣的团购信息【批量】抓取&&a href=&https://link.zhihu.com/?target=http%3A//blog.csdn.net/jiabiao1602/article/details/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&利用RCurl包完成自己感兴趣的团购信息【批量】抓取 - jiabiao1602的专栏 - 博客频道 - CSDN.NET&/a&&&/p&&p&3. Hadley Wickham,Selectorgadget &&a href=&https://link.zhihu.com/?target=https%3A//cran.rproject.org/web/packages/rvest/vignettes/selectorgadget.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&cran.rproject.org/web/p&/span&&span class=&invisible&&ackages/rvest/vignettes/selectorgadget.html&/span&&span class=&ellipsis&&&/span&&/a&&&/p&&p&4. CRAN其他相关资料&/p&&br&&p&------------------------&/p&&p&作者:余文华&/p&&p&专栏:&a href=&https://link.zhihu.com/?target=https%3A//ask.hellobi.com/blog/datasharing& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&乐享数据DataScientists的博客专栏 &/a&&/p&&p&公众号:乐享数据DataScientists&/p&&p&&b&大家也可以加小编微信:tsbeidou (备注:知乎),进R语言中文社区 交流群,可以跟各位老师互相交流&/b&&/p&
爬虫基础:Rcurl与XML包 爬虫是一种利用代码(例如:R code或Python code)模拟浏览器访问(下载)页面并根据HTML结构筛选获取所需信息的一种工具。在R里面我们通常用Rcurl包实现前一半的功能(模拟浏览器访问页面),用XML包完成后一半功能(通过HTML树结…
&figure&&img src=&https://pic4.zhimg.com/v2-d46a4dc89ac69b_b.jpg& data-rawwidth=&1026& data-rawheight=&597& class=&origin_image zh-lightbox-thumb& width=&1026& data-original=&https://pic4.zhimg.com/v2-d46a4dc89ac69b_r.jpg&&&/figure&&p&&strong&在数据分析过程中最头疼的应该是如何应付脏数据&/strong&,脏数据的存在将会对后期的建模、挖掘等工作造成严重的错误,所以必须谨慎的处理那些脏数据。&/p&&p&脏数据的存在形式主要有如下几种情况:&/p&&p&&strong&1)缺失值&/strong&&/p&&p&&strong&2)异常值&/strong&&/p&&p&&strong&3)数据的不一致性&/strong&&/p&&p&下面就跟大家侃侃如何处理这些脏数据。&/p&&h3&&strong&一、缺失值&/strong&&/h3&&p&缺失值,顾名思义就是一种数据的遗漏,根据CRM中常见的缺失值做一个汇总:&/p&&p&1)会员信息缺失,如身份证号、手机号、性别、年龄等&/p&&p&2)消费数据缺失,如消费次数、消费金额、客单价,卡余等&/p&&p&3)产品信息缺失,如批次、价格、折扣、所属类别等&/p&&p&根据实际的业务需求不同,可以对缺失值采用不同的处理办法,如需要给会员推送短信,而某些会员恰好手机号不存在,&strong&可以考虑剔除&/strong&;如性别不知道,&strong&可以使用众数替代&/strong&;如年龄未知,&strong&可以考虑用均值替换&/strong&。当然还有其他处理缺失值的办法,如&strong&多重插补法&/strong&。下面以一个简单的例子,来说明缺失值的处理。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&#模拟一批含缺失值的数据集
set.seed(1234)
Sex &- sample(c('F','M'), size = 1000, replace = T, prob = c(0.4,0.6))
Age &- round(runif(n = 1000, min = 18, max = 60))
Freq &- round(runif(n = 1000, min = 1, max = 368))
Amount &- rnorm(n = 1000, mean = 134, sd = 10)
ATV &- runif(n = 1000, min = 23, max = 138)
df &- data.frame(Tel = Tel, Sex = Sex, Age = Age, Freq = Freq, Amount = Amount, ATV = ATV)
上面的数据框是一个不含有任何缺失值的数据集,现在我想随机产生100个缺失值,具体操作如下:
#查看原始数据集的概要
summary(df)
&/code&&/pre&&/div&&figure&&img src=&https://pic3.zhimg.com/v2-3b4b20aad9258_b.jpg& data-rawwidth=&652& data-rawheight=&114& class=&origin_image zh-lightbox-thumb& width=&652& data-original=&https://pic3.zhimg.com/v2-3b4b20aad9258_r.jpg&&&/figure&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&#随机参数某行某列的下标
set.seed(1234)
i &- sample(1:6, size = 100, replace = T)
j &- sample(1:1000, size = 100)
#将下标组合成矩阵
index &- as.matrix(data.frame(j,i))
#将原始数据框转换为矩阵
df &- as.matrix(df)
#将随机参数的行列赋值为NA
df[index] &- NA
#重新将矩阵转换为数据框
df2 &- as.data.frame(df)
#变换变量类型
df2$Age &- as.integer(df2$Age)
df2$Freq &- as.integer(df2$Freq)
df2$Amount &- as.numeric(df2$Amount)
df2$ATV &- as.numeric(df2$ATV)
#再一次查看赋予缺失值后的数据框概要
summary(df2)
&/code&&/pre&&/div&&figure&&img src=&https://pic3.zhimg.com/v2-2a2c2b7b346a0bdc850ea_b.jpg& data-rawwidth=&634& data-rawheight=&134& class=&origin_image zh-lightbox-thumb& width=&634& data-original=&https://pic3.zhimg.com/v2-2a2c2b7b346a0bdc850ea_r.jpg&&&/figure&&p&&strong&很明显这里已经随机产生100个缺失值了&/strong&,下面看看这100个缺失值的分布情况。我们使用&strong&VIM包中的aggr()函数&/strong&绘制缺失值的分布情况:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&library(VIM)
aggr(df2, prop = FALSE, numbers = TRUE)
&/code&&/pre&&/div&&p&&figure&&img src=&https://pic1.zhimg.com/v2-05f9561affef7eb45fcfe_b.jpg& data-rawwidth=&657& d

我要回帖

更多关于 xlsx打开内容动不了 的文章

 

随机推荐