# 1-1. 파일 불러오기


travel_ht <- readLines("travelproject1_travelholic.txt")

head(travel_ht, 3)

str(travel_ht)


> head(travel_ht, 3)

 [1] "<div><div class=\"_havey\" style=\"padding-top: 0px; padding-bottom: 5294.9px;\"><div class=\"_6d3hm _mnav9\"><div class=\"_mck9w _gvoze _tn0ps\"><a href=\"/p/Bf5wpmgBIKh/?taken-by=travelholic_insta\"><div class=\"_e3il2\"><div class=\"_4rbun\"><img alt=\"." [2] "#그라나다, #Granada, #스페인, #Spain" [3] "."


> str(travel_ht)

chr [1:335] "<div><div class=\"_havey\" style=\"padding-top: 0px; padding-bottom: 5294.9px;\"><div class=\"_6d3hm _mnav9\"><"| __truncated__ ...


'instaR'이라는 패키지를 이용하면 API를 이용하여 해시태그(#)를 바로 받아올 수 있습니다. 하지만 간단한 자연어 처리 연습을 위하여 분석 대상 계정의 html 소스 중 해시태그(#)가 포함된 부분을 텍스트 파일로 저장해서 불러왔습니다.




# 1-2. 전처리


html_rm <- c("class", "alt", "h1", "img", "div", "sizes",

             "srcset", "span", "header", "jpg", "style",

             "css", "com", "http", "tagged", "javascript", "src", "script")

travel_ht01 <- str_replace_all(travel_ht, "[<>,.?/=\"\':;*&^%$@!~]", " ")

travel_ht02 <- str_replace_all(travel_ht01, html_rm, " ")


> str(travel_ht03)

chr [1:335] "divdiv  _havey stylepadding-top  px padding-bottom  pxdiv  _ d hm _mnav div  _mck w _gvoze _tn psa hrefpBf wpmg"| __truncated__ ...


명사를 추출하기 전, 정제 대상이 아닌 것을 제거해주는 과정입니다. 간단하게 html_rm 벡터(html 코드에서 눈에 띄는 태그들을 정리)를 만들어 한꺼번에 제거하였습니다. 또한, 원래대로라면 특수문자를 나타내는 정규표현식 '//W'를 사용하면 되지만 해시태그(#)를 제거하면 안 되기에 다른 특수문자들을 따로 입력하여 제거했습니다. 특정 문자(열) 제거에는 'stringr'패키지에 있는 'str_replace_all'을 이용하여 띄어쓰기 한 칸으로 치환하는 방법을 사용했습니다. (명사 추출을 위한 공백 유지)




# 1-3. 명사 추출


travel_ht03 <- extractNoun(travel_ht02)

str(travel_ht03)


> str(travel_ht03)

List of 335

 $ : chr [1:27] "divdiv" "havey" "stylepadding" "top" ...

 $ : chr [1:5] "#그라나다" "#Granada" "#스페인" "#Spai" ...

 $ : chr ""

 $ : chr [1:6] "헤네랄리페" "정원" "풍경" "동화" ...

 $ : chr [1:5] "여름" "별장" "사용" "" ...

 $ : chr [1:3] "풍경" "이유" ""

 $ : chr ""

 $ : chr ""

 $ : chr [1:2] "dalkom" "j"


한국어 명사를 추출해주는 'koNLP' 패키지를 사용하기 위해서는 JAVA JRE가 설치되어 있어야 합니다. (공식 홈페이지 다운) 해당 패키지에서 'useNIADic'을 로드하여 extractNoun을 사용하면 위와 같이 명사가 추출됩니다. 한국어 스페인의 경우 정상적으로 추출되었는데 Spain의 경우 Spai로 추출된 것을 보면 영어 명사 추출에 적합한 패키지는 아닌 것 같습니다.




# 1-4. 해시태그(#) 포함 단어만 추출


travel_ht04 <- grep("#", travel_ht03)

str(travel_ht04)


> str(travel_ht04)

 int [1:220] 28 29 30 31 52 53 55 206 207 238 ...


본 프로젝트에서 필요한 해시태그(#)를 뽑아내기 위해, 특정 문자(열)가 포함된 단어만 추출해주는 'grep'을 사용했습니다. 해당 함수는 값이 아닌 인덱스를 결과로 내므로 값을 찾아오는 단계를 거쳐야 합니다.




# 1-5. 값 불러오기


travel_ht05 <- travel_ht03[travel_ht04]

head(travel_ht05, 20)


> head(travel_ht05, 20)

 [1] "#그라나다"      "#Granada"      "#스페인"        "#Spai"      

 [5] "#여행에미치"    "#일상을여행으"  "#Travelholic"  "#오만"      

 [9] "#Oma"          "#여행에미치"    "#일상을여행으"  "#Travelholic"

[13] "#타타코아"      "#Tatacoa"      "#콜롬비아"     "#Colombi"   

[17] "#여행에미치"    "#일상을여행으"  "#Travelholic"  "#밀라노"


값을 불러오는 방법은 간단합니다. '원 데이터[결과 데이터]'로 불러와 새로운 변수에 담아주면 됩니다. 'head'로 20개를 출력해보니 'grep'을 이용한 처리가 잘 되어 해시태그(#)가 포함된 단어만 남아있었습니다.




# 1-6. 해시태그(#) 제거


travel_ht06 <- str_replace_all(travel_ht05, "#", "")

head(travel_ht06, 40)


> head(travel_ht06, 40)

 [1] "그라나다"     "Granada"      "스페인"       "Spai"         "여행에미치"

 [6] "일상을여행으" "Travelholic"  "오만"         "Oma"          "여행에미치"

[11] "일상을여행으" "Travelholic"  "타타코아"     "Tatacoa"      "콜롬비아"  

[16] "Colombi"      "여행에미치"   "일상을여행으" "Travelholic"  "밀라노"    

[21] "Milano"       "이탈리아"     "Ital"         "여행에미치"   "일상을여행으"

[26] "Travelholic"  "유후인"       "Yufuin"       "일본"         "Japa"      

[31] "여행에미치"   "일상을여행으" "Travelholic"  "발베크"       "Baalbek"   

[36] "레바논"       "Lebano"       "여행에미치"   "일상을여행으" "Travelholic"


추출된 해시태그를 다른 데이터와 비교하여 교집합을 추출하기 위해 '#'을 제거하고, 아래와 같이 데이터 형태와 열 이름 등을 정리했습니다.




# 1-7. 데이터 프레임으로 내보내기


travel_ht07 <- as.data.frame(travel_ht06, stringsAsFactors = FALSE)

str(travel_ht07)

head(travel_ht07)


> head(travel_ht07, 2)

       travel_ht06

1 그라나다

2  Granada




# 1-8. 열 이름 변경


travel_ht07 <- travel_ht07 %>% rename(tag = travel_ht06)

head(travel_ht07)    


> str(travel_ht07)

'data.frame':  220 obs. of  1 variable:

 $ tag: Factor w/ 120 levels "","Afric","Aruba",..





# 1. 파일 불러오기


test01 <- readLines("airport_raw.txt")

head(test01)


> head(test01)

[1] "모스크바 셰레메티예보 공항의 터미널 구조"

[2] ""

[3] "인천국제공항"

[4] ""

[5] "프랑크푸르트 공항에 있는 루프트한자 항공기"

[6] "공항(空港, 영어: airport)은 상업용 제반 항공기의 발착에 필요한 시설을 갖춘 공개비행장을 말한다. 주로 여객기·화물기 등의 항공기 이착륙에 이용한다. 항공기의 대형화와 항공기 대()수의 증가로 공항시설의 확장이 대부분의 도시에서 요청된다."


국제공항이 있는 도시의 이름과 공항 이름 칼럼이 있는 데이터 프레임을 생성하기 위해 관련 위키피디아 페이지의 정보를 텍스트 파일로 저장해 사용하였습니다.



[그림 1. 위키피디아 '국제공항' 페이지 (https://ko.wikipedia.org/wiki/%EA%B5%AD%EC%A0%9C%EA%B3%B5%ED%95%AD)]




# 2. ':'가 있는 행만 추출하기 (& 값 불러오기, data frame로 추출)


test02 <- grep(":", test01)

head(test02, 10)


> test02 <- grep(":", test01)

> head(test02, 10)

[1]  6 18 19 20 21 22 23 24 25 27


test03 <- as.data.frame(test01[test02], stringsAsFactor = FALSE)

test03 <- test03 %>% rename(city = `test01[test02]`)

head(test03, 5)


> test03 <- as.data.frame(test01[test02], stringsAsFactor = FALSE)

> test03 <- test03 %>% rename(city = `test01[test02]`)

> head(test03, 5)

            city

1 공항(空港, 영어: airport)은 상업용 제반 항공기의 발착에 필요한 시설을 갖춘 공개비행장을 말한다. 주로 여객기·화물기 등의 항공기 이착륙에 이용한다. 항공기의 대형화와 항공기 대(臺)수의 증가로 공항시설의 확장이 대부분의 도시에서 요청된다.

2 서울:김포 국제공항

3 인천:인천 국제공항

4 제주:제주 국제공항

5 부산:김해 국제공항


[그림 1]을 보면 위키피디아 '국제공항' 페이지의 자료가 '국가명:국제 공항 명'으로 되어있음을 알 수 있습니다. 따라서 'grep'을 사용하여 : 를 포함한 행만 추출했습니다.  'grep'은 인덱스를 반환하는 함수이므로 '원 데이터[결과 데이터]'로 값을 불러오는 단계 거쳤고, 'head'로 출력한 값을 보면 원하는 행이 제대로 추출되었음을 알 수 있습니다. 




# 3. 글자수 필터링


test04 <- test03 %>% filter(nchar(city) > 5 & nchar(city) < 30)

head(test04)


> test04 <- test03 %>% filter(nchar(city) > 5 & nchar(city) < 30)

> head(test04, 10)

                       city

1                    서울:김포 국제공항

2                    인천:인천 국제공항

3                    제주:제주 국제공항

4                    부산:김해 국제공항

5                    대구:대구 국제공항

6                    강원:양양 국제공항

7                    전남:무안 국제공항

8                    충북:청주 국제공항

9  도쿄:하네다 국제공항,나리타 국제공항

10               오사카:간사이 국제공항


test03의 1행과 같이 공항 명이 아닌 다른 정보인데 ':' 를 포함하는 값을 제거해주기 위해서 글자수 길이를 이용하여 데이터를 필터링했습니다.




# 4. (도시):(공항) > ':'를 기준으로 열 구분짓기


test05 <- as.data.frame(str_split_fixed(test04$city, ":", 2), stringsAsFactors = FALSE)

head(test05)


> test05 <- as.data.frame(str_split_fixed(test04$city, ":", 2), stringsAsFactors = FALSE)

> head(test05)

   V1          V2

1 서울         김포 국제공항

2 인천         인천 국제공항

3 제주         제주 국제공항

4 부산         김해 국제공항

5 대구         대구 국제공항

6 강원         양양 국제공항


도시와 공항을 각각의 칼럼으로 만들기 위해 'str_split_fixed'를 이용하여 ':' 를 기준으로 단어를 나누었습니다. 'str_split_fixed(string, pattern, n)'는 'stringr' 패키지에 있는 함수로 처리 대상인 stringpattern 기준에 따라 n개로 나누어 줍니다. 




# 5. 공항 2개인 경우 하나만 남기기


test06 <- as.data.frame(str_split_fixed(test05$V2, ",", 2), stringsAsFactors = FALSE)

head(test06, 10)


> test06 <- as.data.frame(str_split_fixed(test05$V2, ",", 2))

> head(test06)

               V1 V2

1    김포 국제공항                

2    인천 국제공항                

3    제주 국제공항                

4    김해 국제공항                

5    대구 국제공항                

6    양양 국제공항                

7    무안 국제공항                

8    청주 국제공항                

9  하네다 국제공항 나리타 국제공항

10 간사이 국제공항       


국제 공항이 2개 이상 있는 경우 ','로 연결되어 있습니다. (예: 하네다 국제공항, 나리타 국제공항) 따라서 ','를 pattern으로 칼럼을 한 번 더 나눠줍니다. 다음으로 이번 프로젝트는 약식으로 진행하는 것이라 도시별로 대표 국제공항 하나만 사용할 예정입니다. 따라서 아래 보이는 것과 같이 'select'를 이용해 첫 번째 칼럼만 남기겠습니다.


test061 <- test06 %>% select(V1)

head(test061, 10)


> test061 <- test06 %>% select(V1)

> head(test061, 10)

            V1

1 김포 국제공항

2 인천 국제공항

3 제주 국제공항

4 김해 국제공항

5 대구 국제공항

6 양양 국제공항

7 무안 국제공항

8 청주 국제공항

9 하네다 국제공항

10 간사이 국제공항




# 6. 필요 없는 문자열 제거


test062 <- as.data.frame(str_split_fixed(test061$V1, "\\(", 2), stringsAsFactors = FALSE)

head(test062)


> test062 <- as.data.frame(str_split_fixed(test061$V1, "\\(", 2), stringsAsFactors = FALSE)

> head(test062)

            V1 V2

1 김포 국제공항   

2 인천 국제공항   

3 제주 국제공항   

4 김해 국제공항   

5 대구 국제공항   

6 양양 국제공항  


국제공항이라는 단어 뒤에 괄호로 부연 설명이 되어있는 행이 있어 국제공항 이후 부분을 제거해주었습니다. 4. ~ 5.에서 진행한 것과 같은 과정이므로 설명은 생략하겠습니다. 참고로 특수문자 '('의 경우 기능을 가진 제어문자이므로, 문자 그대로를 인식시켜 주기 위해 역슬래쉬 두 개(\\)를 앞에 붙여주었습니다.




# 7. 도시-공항 데이터프레임 생성


test07 <- test05 %>% select(V1) %>% mutate(airport=test062$V1)

test08 <- test07 %>% rename(city = V1)

head(test08)

write.csv(test08, file="airport_mini.csv")


> test07 <- test05 %>% select(V1) %>% mutate(airport=test062$V1)

> test08 <- test07 %>% rename(city = V1)

> head(test08)

 city       airport

1 서울     김포 국제공항

2 인천     인천 국제공항

3 제주     제주 국제공항

4 부산     김해 국제공항

5 대구     대구 국제공항

6 강원     양양 국제공항


공항 명을 정제하느라 나뉘어 있던 두 행을 'mutate'를 사용하여 결합해주었습니다. 결과 도시명과 공항 명이 잘 연결되었음을 알 수 있었습니다. 정제 후에는 다시 과정을 거치지 않고 데이터를 불러오기 위해(너무나도 당연한 말이지만...) 'write.csv'를 이용하여 csv 파일로 내보냈습니다.



+ Recent posts