(由 R客 轉(zhuǎn)載自 數(shù)據(jù)科學(xué)與R語言 )
有時(shí)候我們要處理的是非結(jié)構(gòu)化的數(shù)據(jù),例如網(wǎng)頁或是電郵資料,那么就需要用R來抓取所需的字符串,整理為進(jìn)一步處理的數(shù)據(jù)形式。R語言中有一整套可以用來處理字符的函數(shù),在之前的 博文 中已經(jīng)有所涉及。但真正的要用好字符處理函數(shù),則不得不用到正則表達(dá)式。 正則表達(dá)式(Regular Expression、regexp) 是指一種用來描述一定數(shù)量文本的模式。熟練掌握正則表達(dá)式能使你隨心所欲的操作文本來達(dá)成目標(biāo)。其實(shí)學(xué)習(xí)正則表達(dá)式并沒有想像中的那么困難。最好方法是從例子開始,然后多練習(xí),多使用。網(wǎng)絡(luò)上已經(jīng)有許多不錯(cuò)的參考資料,例如 這篇 或 那篇 。本文假設(shè)你對正則表達(dá)式有了基本的了解,下面我們來看看如何在R里面來使用它。
假設(shè)我們有一個(gè)字符向量,包括了三個(gè)字符串。我們的目標(biāo)是從中抽取電郵地址。R語言中很多字符函數(shù)都能識別正則表達(dá)式,而最重要的函數(shù)就是gregexpr()。該函數(shù)的第一個(gè)參數(shù)是正則表達(dá)式,前后需要用引號,對元字符進(jìn)行轉(zhuǎn)義時(shí)要用\\。第二個(gè)參數(shù)是等待處理的文本。那么用如下三行代碼,我們從word字符向量中得到一個(gè)列表,其中第一項(xiàng)元素中的5表示電郵地址從第5個(gè)字符位置開始,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
下一步我們需要將電郵地址抽取出來,此時(shí)配合substr函數(shù),即可根據(jù)需要字符串的位置來提取子集。
substr(word[1],gregout[[1]],gregout[[1]]+attr(gregout[[1]],'match.length')-1)
[1] “noboby@stat.berkeley.edu”
更方便的使用方式是根據(jù)上述方法建立一個(gè)自定義函數(shù)getcontent,參數(shù)s表示待處理的文本,參數(shù)g表示的是通過gregexpr函數(shù)處理后的結(jié)果。這個(gè)函數(shù)我們在后面還會用到。
getcontent <- function(s,g){ substring(s,g,g+attr(g,'match.length')-1)}getcontent(word[1],gregout[[1]])
下面我們用一個(gè)較大的例子來說明在實(shí)際的數(shù)據(jù)抓取工作中,如何使用正則表達(dá)式。豆瓣電影是博主經(jīng)常去的地方。此次任務(wù)目標(biāo)是要抓取豆瓣電影中250部最佳電影的資料。R代碼如下:
url<-'http://movie.douban.com/top250?format=text'# 獲取網(wǎng)頁原代碼,以行的形式存放在web變量中web <- readLines(url,encoding="UTF-8")# 找到包含電影名稱的行編號name <- web[grep('<td headers="m_name">',web)+1]# 用正則表達(dá)式來提取電影名gregout <- gregexpr('>\\w+',name)movie.names = 0for(i in1:250){ movie.names[i]<-getcontent(name[i],gregout[[i]])}movie.names <- sub('>','',movie.names)# 找到包含電影發(fā)行年份的行編號并進(jìn)行提取year <- web[grep('<span class="year">',web)]movie.year <- substr(year,36,39)# 找到包含電影評分的行編號并進(jìn)行提取score <- web[grep('<td headers="m_rating_score">',web)+1]movie.score <- substr(score,21,23)# 找到包含電影評價(jià)數(shù)量的行編號并進(jìn)行提取rating <- web[grep('<td headers="m_rating_num">',web)+1]movie.rating <- sub(' *','',rating)# 合成為數(shù)據(jù)框movie <- data.frame(names=movie.names,year=as.numeric(movie.year), score=as.numeric(movie.score),rate=as.numeric(movie.rating))# 繪散點(diǎn)圖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)
用散點(diǎn)圖來觀察數(shù)據(jù),可以看到前250名電影中大部分是1980年之后發(fā)行的。1997年和2010年發(fā)行的電影有不少精品。而其中紅色點(diǎn)所代表的是哪部電影你知道嗎?那就是Titanic。
參考資料:Concepts in Computing with Data
聯(lián)系客服