楼主: kk22boy
18776 8

[程序分享] 在R语言中使用正则表达式 [推广有奖]

  • 8关注
  • 95粉丝

一叶知秋

已卖:9095份资源

学科带头人

51%

还不是VIP/贵宾

-

TA的文库  其他...

计量经济与统计

SSCI、权威 论文写作及投稿经验

威望
1
论坛币
57240 个
通用积分
130.1721
学术水平
437 点
热心指数
492 点
信用等级
393 点
经验
68023 点
帖子
1586
精华
0
在线时间
2192 小时
注册时间
2005-3-10
最后登录
2025-5-25

初级热心勋章 初级信用勋章

楼主
kk22boy 发表于 2013-3-6 16:13:55 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
有时候我们要处理的是非结构化的数据,例如网页或是电邮资料,那么就需要用R来抓取所需的字符串,整理为进一步处理的数据形式。R语言中有一整套可以用来处理字符的函数,在之前的博文中已经有所涉及。但真正的要用好字符处理函数,则不得不用到正则表达式。正则表达式(Regular Expression、regexp)是指一种用来描述一定数量文本的模式。熟练掌握正则表达式能使你随心所欲的操作文本来达成目标。其实学习正则表达式并没有想像中的那么困难。最好方法是从例子开始,然后多练习,多使用。网络上已经有许多不错的参考资料,例如这篇那篇。本文假设你对正则表达式有了基本的了解,下面我们来看看如何在R里面来使用它。


假设我们有一个字符向量,包括了三个字符串。我们的目标是从中抽取电邮地址。R语言中很多字符函数都能识别正则表达式,而最重要的函数就是gregexpr()。该函数的第一个参数是正则表达式,前后需要用引号,对元字符进行转义时要用\\。第二个参数是等待处理的文本。那么用如下三行代码,我们从word字符向量中得到一个列表,其中第一项元素中的5表示电邮地址从第5个字符位置开始,24表示电邮地址长度为24。

word <- c('abc noboby@stat.berkeley.edu','text with no email','first me@mything.com also you@yourspace.com')
pattern <- '[-A-Za-z0-9_.%]+@[-A-Za-z0-9_.%]+\\.[A-Za-z]+'
(gregout <- gregexpr(pattern,word))
[[1]]
[1] 5
attr(,"match.length")
[1] 24

[[2]]
[1] -1
attr(,"match.length")
[1] -1

[[3]]
[1]  7 27
attr(,"match.length")
[1] 14 17

下一步我们需要将电邮地址抽取出来,此时配合substr函数,即可根据需要字符串的位置来提取子集。

substr(word[1],gregout[[1]],gregout[[1]]+attr(gregout[[1]],'match.length')-1)
[1] "noboby@stat.berkeley.edu"

更方便的使用方式是根据上述方法建立一个自定义函数getcontent,参数s表示待处理的文本,参数g表示的是通过gregexpr函数处理后的结果。这个函数我们在后面还会用到。

getcontent <- function(s,g) {
    substring(s,g,g+attr(g,'match.length')-1)
}
getcontent(word[1],gregout[[1]])
下面我们用一个较大的例子来说明在实际的数据抓取工作中,如何使用正则表达式。豆瓣电影是博主经常去的地方。此次任务目标是要抓取豆瓣电影中250部最佳电影的资料。R代码如下:
url <-'http://movie.douban.com/top250?format=text'
# 获取网页原代码,以行的形式存放在web变量中
web <- readLines(url,encoding="UTF-8")
# 找到包含电影名称的行编号
name <- web[grep('<td headers="m_name">',web)+1]
# 用正则表达式来提取电影名
gregout <- gregexpr('>\\w+',name)
movie.names = 0
for (i in 1:250) {
    movie.names <-getcontent(name,gregout[])
}
movie.names <- sub('>','',movie.names)
# 找到包含电影发行年份的行编号并进行提取
year <- web[grep('<span class="year">',web)]
movie.year <- substr(year,36,39)
# 找到包含电影评分的行编号并进行提取
score <- web[grep('<td headers="m_rating_score">',web)+1]
movie.score <- substr(score,21,23)
# 找到包含电影评价数量的行编号并进行提取
rating <- web[grep('<td headers="m_rating_num">',web)+1]
movie.rating <- sub(' *','',rating)
# 合成为数据框
movie <- data.frame(names=movie.names,year=as.numeric(movie.year),
                    score=as.numeric(movie.score),rate=as.numeric(movie.rating))
# 绘散点图
library(ggplot2)
p <- ggplot(data=movie,aes(x=year,y=score))
p+geom_point(aes(size=rate),colour='lightskyblue4',
             position="jitter",alpha=0.8)+
  geom_point(aes(x=1997,y=8.9),colour='red',size=4)


用散点图来观察数据,可以看到前250名电影中大部分是1980年之后发行的。1997年和2010年发行的电影有不少精品。而其中红色点所代表的是哪部电影你知道吗?那就是Titanic。

参考资料:Concepts in Computing with Data
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:正则表达式 表达式 R语言 Expression express 语言 表达式

已有 3 人评分经验 论坛币 学术水平 热心指数 信用等级 收起 理由
李会超 + 40 + 20 精彩帖子
ltx5151 + 20 + 20 根据规定进行奖励
epoh + 5 + 5 + 5 精彩帖子

总评分: 经验 + 60  论坛币 + 40  学术水平 + 5  热心指数 + 5  信用等级 + 5   查看全部评分

如果该贴对您有些许帮助,希望你能回复一下或者评一下热心指数!谢谢!

沙发
complicated 在职认证  发表于 2013-4-20 09:28:47
顶!想学习正则的从这个例子开始最好了
密码被盗??

藤椅
tokey001 在职认证  发表于 2014-5-4 13:33:28
按照代码运行,names为空,???

> name
character(0)

板凳
七彩空气 学生认证  发表于 2014-9-4 10:29:26
速速膜拜大神

报纸
yzhlinscau 发表于 2014-9-4 14:47:04
顶!学习正则!!

地板
诸葛山下 发表于 2014-9-6 14:17:01
学习了,好贴!另外也推荐一篇关于正则表达式的资料贴http://www.jb51.net/tools/zhengze.html

7
blackgcm 发表于 2015-6-9 16:50:24
for循环的时候,为啥会下标越界?

8
小猫咪517 发表于 2015-9-5 12:05:56
tokey001 发表于 2014-5-4 13:33
按照代码运行,names为空,???

> name
可能网页代码变了

9
allenmo 发表于 2017-5-9 16:12:43
感谢分享教程,愿在学习中共勉

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2025-12-29 04:47