R 정규표현식에서 정규표현식을 이해했으니, 이를 활용하여 텍스트 데이터를 R에서 처리해본다.

1 R Base 문자열 처리 1 2

1.1 시작환경 설정

stringr 팩키지를 설치하지 않았다면 설치하고 관련된 팩키지를 불러온다.

1.2 nchar - 각 문자열 길이를 센다.

[1] 19  7

1.3 substr 문자벡터 부분집합

1번에서 7번째까지 문자열 요소를 뽑아내자.

[1] "Tidyver" "Wooooo!"

1번에서 7번째까지 문자열 요소를 SCIENCE로 바꾼다.

[1] "SCIENCEse is great!" "SCIENCE"            

1.4 paste - 문자열을 붙이거나 조합

다소 복잡한 함수라, 일반적인 사용례를 살펴보자. sep 매개변수가 구분문자를 정의한다. (기본디폴트 설정으로 한칸 공백).

[1] "abc efg"
[1] "abcefg"

paste0 함수는 paste(..., sep="") 을 줄여놓은 함수다.

[1] "abcefg"

다수 값을 갖는 벡터를 조합하려면, collapse 매개변수로 명세한다:

[1] "abchijefgklm"

1.5 strsplit - 문자열을 문자열 리스트로 쪼갬

예를 들어, 콤마로 구분된 벡터를 다음과 같이 쪼갠다:

[[1]]
[1] "abc" "cbe"

[[2]]
[1] "cb"  "gb"  "aaa"

strsplit 함수는 리스트를 반환한다. 그래서 하나처럼 다뤄진다. 만약 두번째 요소를 뽑아낸다면 다음과 같이 코딩한다:

[[1]]
[1] "cbe"

[[2]]
[1] "gb"

2 R 정규표현식

앞서 문자데이터 처리 기초를 학습했다. 강력한 문자데이터 처리를 위해서, R 기초 문자데이터 처리기술을 정규표현식과 함께 사용하는 방법을 살펴보자.

2.1 R 정규표현식 초간단 정리

  1. POSIX 클래스를 사용해서 \w, \d, \s 문자 클래스를 참조한다. 이들 문자클래스는 함수에도 동일하지만, 좀더 가독성이 좋다고 일부 개발자는 생각한다. ?regex 도움말을 타이핑해서 전체를 볼수 있다. 다음에 일부 예제가 나와있다.

    • \w = [[:alnum:]]
    • \d = [[:digit:]]
    • \s = [[:space:]]
  2. 특수문자를 탈출시키거나 문자클래스를 사용하는 경우, 문자 앞에 이중 확장기호를 사용한다. 예를 들어, * 대신에 \w**.

2.2 news_tweets 데이터 불러오기

4개 방송사(CBC, CNN, Al Jazeera, Reuters)에서 나온 지난주 트위터 데이터를 불러 읽어들이는 예제가 준비되었으나, 드롭박스 데이터가 더이상 제공되지 않아서 … Free Twitter Datasets 공개된 데이터나 Tweet Sentiment to CSV 웹사이트에서 다운로드 받아 사용한다.

몇년전에는 twitteR 팩키지를 사용해서 트위터 트윗을 수집했는데, twitteR은 트위터 REST API 인터페이스다.

Observations: 98
Variables: 3
$ sentiment <chr> "neutral", "neutral", "neutral", "positive", "neutral"…
$ text      <chr> "@liberal_party @cathmckenna https://t.co/sI605lryvU",…
$ user      <chr> "EagleeyeJbp", "ColdH2OSurfer", "Ugorjuss", "hs_UofTok…
  • sentiment = 감성
  • text = 트윗 텍스트 원문
  • user = 트위터 사용자명(축약)

2.3 grep - 텍스트에서 패턴 찾아내기

가장 기초적인 작업은 정규표현식으로 문자벡터를 검색하는 것이다.

grep은 정규표현식과 문자벡터를 입력값으로 받아 매칭되는 인덱스를 반환한다.

정규표현식을 사용해서 senti_tweets에 해쉬태그를 포함한 트윗을 찾아보자. 해쉬태그는 # 다음에 알파벳숫자가 하나 이상 따라온다. 예를 들어, #rstats, #Canada 등

 [1]  6  7 12 13 15 17 18 24 25 34 36 38 40 52 59 61 68 70 74 75 78 80 86
[24] 91 94 95

value=TRUE를 설정하면 인덱스에 딸린 벡터 실제값을 반환한다.

[1] "RT @KirkDBorne: This week’s featured articles &amp; resources for #DataScience and #MachineLearning at @DataScienceCtrl https://t.co/eGdYqLbthT…"
[2] "Failed #256times JavaScript bootcamp selection and time to go back original plan;\\nfollowing 2week schedule.\\n1. data… https://t.co/2WdPtFS7Go"
[3] "RT @AIMquarantecinq: A brest le 21 mai pour parler Course au large et Data !\\n https://t.co/b9zMpCHOnn #Meetup #Brest via @MeetupFR\\nAvec @se…"
[4] "RT @KirkDBorne: This week’s featured articles &amp; resources for #DataScience and #MachineLearning at @DataScienceCtrl https://t.co/eGdYqLbthT…"
[5] "RT @AnalyticsVidhya: Here are the top #datascience related GitHub projects and Reddit discussions from April 2019. Some really cool code an…"    

invert = TRUE를 설정해서, 해쉬태그가 없는 검색결과로 반전할 수 있다:

[1] "@liberal_party @cathmckenna https://t.co/sI605lryvU"                                                                                                           
[2] "RT @EstOdek: QUESTION: What makes someone a scientist?\\n\\nI’ll start with one:\\n\\nIf you ‘do’ the science (i.e. generate the data) then you’re…"           
[3] "RT @EstOdek: QUESTION: What makes someone a scientist?\\n\\nI’ll start with one:\\n\\nIf you ‘do’ the science (i.e. generate the data) then you’re…"           
[4] "[Welcome to Japan!!] In Shibuya, You can take a rest for free in happy science church. https://t.co/8kO6omVCKy"                                                
[5] "\U0001f4e3\U0001f4e3 Este será la primer meetup de la comunidad Data Science Research Perú para todos aquellos interesados en acercar… https://t.co/ylFv8h6EXe"

2.4 grepl - 논리 패턴 매칭

grepl (grep logical)은 grep과 유사하지만, 벡터 모든 요소에 대한 TRUE 혹은 FALSE 값을 반환한다.

 [1] FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE

dplyr 팩키지 filtergrepl을 사용해서 정규표현식으로 행을 필터링한다. url을 포함한 트윗을 필터링해서 뽑아낸다:

# A tibble: 6 x 3
  sentiment text                                                user       
  <chr>     <chr>                                               <chr>      
1 neutral   @liberal_party @cathmckenna https://t.co/sI605lryvU EagleeyeJbp
2 positive  [Welcome to Japan!!] In Shibuya, You can take a re… hs_UofTokyo
3 neutral   📣📣 Este será la primer meetup de la comunidad Data… MirinaGonz…
4 neutral   RT @KirkDBorne: This week’s featured articles &amp… asalazarad…
5 negative  "Failed #256times JavaScript bootcamp selection an… keijiuehara
6 positive  "From Digital Media Jobs Network \\nLatest Data Sc… DMJNcom    

2.5 gsub - 찾기와 바꾸기

정규표현식으로 매칭하고, 매칭된 것을 미리 지정한 문자열로 바꾼다.

gsub 함수는 정규표현식, 바꾸기 문자열과, 대상문자열을 입력 인자로 받는다. gsub 함수는 바꾸기 문자열로 교체된 모든 모든 문자열 벡터를 반환한다.

gsub 함수의 일반적인 용도는 텍스트 정제다. 예를 들어, 트윗에서 모든 url을 제거하자:

[1] "Failed #256times JavaScript bootcamp selection and time to go back original plan;\\nfollowing 2week schedule.\\n1. data… https://t.co/2WdPtFS7Go"
[1] "Failed #256times JavaScript bootcamp selection and time to go back original plan;\\nfollowing 2week schedule.\\n1. data… "

gsub 함수를 사용해서 부가되거나 끝에 딸려오는 공백문자를 제거한다:

[1] "Failed #256times JavaScript bootcamp selection and time to go back original plan;\\nfollowing 2week schedule.\\n1. data…"

마지막으로, polit로 시작되는 모든 문자를 ballons으로 바꾸기 한다:

먼저 polit으로 시작되는 관심 패턴을 포함하는 트윗을 뽑아낸다:

[1] "Politics"  "politic"   "politic"   "Political"

이제 이를 조합해서 polit로 시작되는 모든 문자를 ballons으로 바꾼다:

[1] "balloons" "balloons" "balloons" "balloons"

3 stringr 팩키지

R에 다른 모든 것처럼, Hadley Wickham이 문자열처리도 효과적이고 효율적으로 다루고자 많은 기여를 했다. 문자열에 대한 기여결과가 stringr 팩키지로 구현되었다. 기존에 존재하던 많은 함수를 더 멋진 구문으로 구현했다. 문자열 처리 팩키지를 dplyr과 함께 사용해서 트윗데이터에 대한 기본적인 어휘분석을 수행한다!

트윗에서 “단어가 아닌” 모든 텍스트를 정제한다. 정제를 시작해보자:

  • URL: http[s]?://[[:alnum:]].\\/]+
  • 트위터 사용자명 (예를 들어, @CNN): @[\\w]*
  • 해쉬태그(#rstats): #[\\w]*
  • 소유격(’s) : 's
  • 이상한 유니코드/html 태그 (예를 들어, <U008+>): <.*>

먼저 제거하고자 하는 각각에 대한 정규표현식을 작성한다. 그리고 나서 "|" 연산자로 조합한다. (정규표현식에서 “or”, 또는 의미를 갖는다.)

(gsub 같은) str_replace_all 함수를 사용해서 트윗 텍스트를 정제한다.

[1] "RT : Want to learn Data Science with Python and Azure Machine Learning, here is the opportunity, registration is open for 5th…"    
[2] "RT : Ram Guha claims Modi govt has done a surgical strike on science and scholarship, data says otherwise (writes …"               
[3] "RT : We aren't trying to sell you anything. We think that if you're like about 15 million people who have already been tested, yo…"
[4] " Yeah - you are correct. The data/findings need to be robust, but absolutely perfect papers, with extra… "                         
[5] "Interweaving  and  to Unleash Economic Value of Data:   by… "                                                                      
[6] "RT : Hurray for Women in Data Science lunch at !     …"                                                                            

잘 동작되지만, 꼬리부분에 공백문자가 눈에 띈다! 다행히도, stringr 팩키지에는 이런 작업을 위한 전용함수가 존재한다. str_trim 함수는 앞쪽과 뒤쪽 공백문자를 제거한다:

[1] "RT : Want to learn Data Science with Python and Azure Machine Learning, here is the opportunity, registration is open for 5th…"    
[2] "RT : Ram Guha claims Modi govt has done a surgical strike on science and scholarship, data says otherwise (writes …"               
[3] "RT : We aren't trying to sell you anything. We think that if you're like about 15 million people who have already been tested, yo…"
[4] "Yeah - you are correct. The data/findings need to be robust, but absolutely perfect papers, with extra…"                           
[5] "Interweaving  and  to Unleash Economic Value of Data:   by…"                                                                       
[6] "RT : Hurray for Women in Data Science lunch at !     …"                                                                            

다음으로, str_extract_all 함수를 사용해서 전체 데이터셋에서 모든 단어를 추출한다. (grep(...value=TRUE)처럼)

[[1]]
character(0)

[[2]]
 [1] "RT"        "QUESTION"  "What"      "makes"     "someone"  
 [6] "a"         "scientist" "n"         "nI"        "ll"       
[11] "start"     "with"      "one"       "n"         "nIf"      
[16] "you"       "do"        "the"       "science"   "i"        
[21] "e"         "generate"  "the"       "data"      "then"     
[26] "you"       "re"       

[[3]]
 [1] "RT"        "QUESTION"  "What"      "makes"     "someone"  
 [6] "a"         "scientist" "n"         "nI"        "ll"       
[11] "start"     "with"      "one"       "n"         "nIf"      
[16] "you"       "do"        "the"       "science"   "i"        
[21] "e"         "generate"  "the"       "data"      "then"     
[26] "you"       "re"       

[[4]]
 [1] "Welcome" "to"      "Japan"   "In"      "Shibuya" "You"     "can"    
 [8] "take"    "a"       "rest"    "for"     "free"    "in"      "happy"  
[15] "science" "church" 

[[5]]
 [1] "Este"        "ser"         "la"          "primer"      "meetup"     
 [6] "de"          "la"          "comunidad"   "Data"        "Science"    
[11] "Research"    "Per"         "para"        "todos"       "aquellos"   
[16] "interesados" "en"          "acercar"    

[[6]]
 [1] "RT"        "This"      "week"      "s"         "featured" 
 [6] "articles"  "amp"       "resources" "for"       "and"      
[11] "at"       

오키도키! 상위 15개 단어를 뽑아내자.

      word count
1      for    17
2  Science    18
3       in    19
4     Data    20
5     with    20
6      you    26
7      and    28
8       is    29
9       to    33
10       a    39
11    data    40
12       n    40
13 science    40
14     the    41
15      RT    69

흠… 정규표현식으로 사용해서 대문자로 시작되는 문자로 적어도 길이가 4자 이상되는 문자만 잡아내자.

           word count
1       Science    18
2     Telegraph     6
3       Whether     5
4       Blatant     4
5      Concepts     3
6  Introduction     3
7      Learning     3
8        Python     3
9     Analytics     2
10      Curious     2
11    Democrats     2
12      Digital     2
13      Dilbert     2
14    Disproven     2
15        India     2
16       Latest     2
17      Looking     2
18      Machine     2
19        Media     2
20      Network     2
21    President     2
22    Requiring     2
23    Scientist     2
24       Shoddy     2
25       Social     2
26        Trump     2
27        Women     2

거의 작업을 잘 마무리한 것으로 보인다. 재미로 단어 구름(word cloud)을 만들어보자.

3.1 추가 학습교재

4 regexplain Addin

regexplain은 RStudio Addin으로 stringr 팩키지 str_view() 함수의 영감을 받아 개발되었다. 이를 통해서 RStudio 개발환경에서 즉각적으로 정규표현식 개발이 가능하다.

4.1 regexplain Addin 설치

regexplain GitHub 웹사이트를 참조하여 regexplain Addin을 설치한다.

설치하게 되면 Addins에 추가로 설치된 것이 확인된다.

regexplain addin 설치

4.2 ip 주소 사례

인터넷에 공개된 웹로그 데이터 중 하나를 다운로드 받아 데이터를 준비한다.

[1] ""                                                                                                                                                                                                                             
[2] "109.169.248.247 - - [12/Dec/2015:18:25:11 +0100] \"GET /administrator/ HTTP/1.1\" 200 4263 \"-\" \"Mozilla/5.0 (Windows NT 6.0; rv:34.0) Gecko/20100101 Firefox/34.0\" \"-\""                                                 
[3] "109.169.248.247 - - [12/Dec/2015:18:25:11 +0100] \"POST /administrator/index.php HTTP/1.1\" 200 4494 \"http://almhuette-raith.at/administrator/\" \"Mozilla/5.0 (Windows NT 6.0; rv:34.0) Gecko/20100101 Firefox/34.0\" \"-\""
[4] "46.72.177.4 - - [12/Dec/2015:18:31:08 +0100] \"GET /administrator/ HTTP/1.1\" 200 4263 \"-\" \"Mozilla/5.0 (Windows NT 6.0; rv:34.0) Gecko/20100101 Firefox/34.0\" \"-\""                                                     
[5] "46.72.177.4 - - [12/Dec/2015:18:31:08 +0100] \"POST /administrator/index.php HTTP/1.1\" 200 4494 \"http://almhuette-raith.at/administrator/\" \"Mozilla/5.0 (Windows NT 6.0; rv:34.0) Gecko/20100101 Firefox/34.0\" \"-\""    
[6] "83.167.113.100 - - [12/Dec/2015:18:31:25 +0100] \"GET /administrator/ HTTP/1.1\" 200 4263 \"-\" \"Mozilla/5.0 (Windows NT 6.0; rv:34.0) Gecko/20100101 Firefox/34.0\" \"-\""                                                  

아파치 웹로그 중에서 IP를 추출하여 가장 접속이 많은 IP주소가 어디인지 찾아보자. “숫자.숫자.숫자.숫자” 패턴을 갖고 있다보니 ^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+ 을 사용해서 IP 주소를 추출해본다.

# A tibble: 2,067 x 2
   ip                  n
   <chr>           <int>
 1 148.251.50.49    1929
 2 52.22.118.215     734
 3 213.150.254.81    434
 4 37.1.206.196      433
 5 178.191.155.244   284
 6 84.112.161.41     257
 7 195.212.98.190    241
 8 93.83.250.186     219
 9 46.119.125.179    213
10 193.81.43.125     162
# … with 2,057 more rows

다른 방법으로 regexplain Addin “Regular Expressions Library” 기능을 사용해서 정규 표현식을 추출해낸다.

정규표현식 네트워크