[여행 관련 인스타그램 해시태그 추출 및 관련 국가 지도출력]

 (클릭하시면 해당 게시글로 넘어갑니다.)



1. 해시 태그가 포함된 명사 추출(정제) (바로가기)


2. 복수 데이터 간의 교집합 추출 (바로가기)


3. 지도 출력을 위해 'geocode'로 위도, 경도 얻어오기 (바로가기)


4. 'ggplot', 'maps'를 이용한 지도 출력 (바로가기)


(참고) [비교용 데이터] 위키피디아 자료로 국가 리스트 csv파일 만들기 (바로가기)


(참고) ggplot, 한국어 출력 가능한 폰트 확인 (바로가기)




# 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",..





# 2-1. (비교용) 국제공항이 위치한 도시 리스트 데이터 불러오기


airport <- read.csv("airport_mini.csv", stringsAsFactors = FALSE)

str(airport)


> airport <- read.csv("airport_mini.csv", stringsAsFactors = FALSE)

> str(airport)

'data.frame':  143 obs. of  3 variables:

 $ X      : int  1 2 3 4 5 6 7 8 9 10 ...

 $ city   : chr w/ 143 levels " "," 마카오",..: 72 101 106 57 13 6 103 ...

 $ airport: chr w/ 143 levels " 싱가포르 창이 국제공항",..: 7 89 91 8 15 79 ...


이전 포스팅에서 완성한 데이터 프레임에서 국제공항이 있는 도시 이름만 추출하기 위하여 모든 도시 이름(과 국제공항)이 담긴 csv 파일을 불러옵니다. 해당 파일은 위키피디아의 정보를 이용해 R로 제작한 파일이며 제작 과정이 궁금하신 분들은 아래 링크를 참조해 주세요.


(참고) [비교용 데이터] 위키피디아 자료로 국가 리스트 csv파일 만들기 (바로가기)




# 2-2. 도시명 최대, 최소 길이 구하기


min(nchar(airport$city))

max(nchar(airport$city))


> min(nchar(airport$city))

[1] 1

> max(nchar(airport$city))

[1] 8


두 데이터를 비교하기 전에 확실하게 비교 대상이 아닌 값, 즉 도시명이 될 수 없는 데이터를 미리 제거해줍니다. 이 과정을 거치면 데이터 처리량이 줄어 소요 시간이 줄어들 것 입니다. 'nchar'와 'min', 'max'를 이용하여 도시 이름의 최소, 최대 길이를 구해 활용하겠습니다. 




# 2-3. 도시명 최대, 최소 길이 맞춰 필터링 전처리


travel_ht08 <- travel_ht07 %>% filter(nchar(tag) >= 1 & nchar(tag) <= 8)

str(travel_ht07)

str(travel_ht08)


> travel_ht08 <- travel_ht07 %>% filter(nchar(tag) >= 1 & nchar(tag) <= 8)

> str(travel_ht07)

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

 $ tag: chr  "그라나다" "Granada" "스페인" "Spai" ...

> str(travel_ht08)

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

 $ tag: chr  "그라나다" "Granada" "스페인" "Spai" ...


2-2. 처리에 의하면 도시명의 길이는 1글자 이상 8글자 이하이므로 'filter' 함수에 해당 조건을 넣어 필터링을 실행합니다. 결과 220개에서 175개로 분석 대상이 줄었음을 알 수 있습니다. 소량의 데이터라 거의 차이가 없지만, 데이터가 많아진다면 분석 시간 등의 차이를 체감하게 될 것입니다.




# 2-4. 도시명 리스트에 있는 단어(도시명)만 추출


travel_ht09 <- intersect(airport$city, travel_ht08$tag)

travel_ht10 <- as.data.frame(travel_ht09, stringsAsFactors = FALSE)

travel_ht11 <- travel_ht10 %>% rename(city = travel_ht09)

travel_ht12 <- travel_ht11 %>% group_by(city) %>% summarise(n())


> travel_ht12

# A tibble: 8 x 2

  city       `n()`

  <chr>      <int>

1 리마               1     

2 밀라노            1      

3 부다페스트      1     

4 브리즈번      1  

양곤               1 

취리히            1

파리               1

8 프라하            1


해시태그 중 국제공항이 있는 도시의 이름에 해당하는 값은 위의 8개입니다. ('intersect' 함수를 사용하여 [추출한 해시태그들이 담긴 데이터 프레임]과 [도시명이 담긴 데이터 프레임]의 교집합을 추출하였습니다) 추가로 'summarise(n())'를 이용하여 단어의 개수도 확인해보았습니다. 한 계정에서 한국어 도시명만 추출하였기에 카운팅을 한 의미는 크게 없지만(...) 추출된 데이터가 많을 때 가장 많이 출력된 값을 찾아내는 데 사용할 수 있을 것 같습니다.



# 3-1. 지도 출력 위해 위도, 경도 받아오기


travel_add01 <- geocode(travel_ht12$city, source="google")


> travel_add01 <- geocode(travel_ht12$city, source="google")

Information from URL : http://maps.googleapis.com/maps/api/geocode/json?address=%EB%A6%AC%EB%A7%88&sensor=false

Information from URL : http://maps.googleapis.com/maps/api/geocode/json?address=%EB%B0%80%EB%9D%BC%EB%85%B8&sensor=false

Information from URL : http://maps.googleapis.com/maps/api/geocode/json?address=%EB%B6%80%EB%8B%A4%ED%8E%98%EC%8A%A4%ED%8A%B8&sensor=false

Information from URL : http://maps.googleapis.com/maps/api/geocode/json?address=%EB%B8%8C%EB%A6%AC%EC%A6%88%EB%B2%88&sensor=false

Information from URL : http://maps.googleapis.com/maps/api/geocode/json?address=%EC%96%91%EA%B3%A4&sensor=false

Information from URL : http://maps.googleapis.com/maps/api/geocode/json?address=%EC%B7%A8%EB%A6%AC%ED%9E%88&sensor=false

Information from URL : http://maps.googleapis.com/maps/api/geocode/json?address=%ED%8C%8C%EB%A6%AC&sensor=false

Information from URL : http://maps.googleapis.com/maps/api/geocode/json?address=%ED%94%84%EB%9D%BC%ED%95%98&sensor=false


'ggmap' 패키지의 'geocode'를 사용하면 구글을 통해 위도, 경도를 받아올 수 있습니다. 한 군데를 받아올 때에는 아래와 같이 장소명이나 주소를 문자열로 넣어주면 됩니다.


test <- geocode("seoul", source="google")

test


> test <- geocode("seoul", source="google")

Information from URL : http://maps.googleapis.com/maps/api/geocode/json?address=seoul&sensor=false

> test

      lon      lat

1 126.978 37.56654


한 번에 복수의 위도, 경도를 받아오고 싶으면 문자열 부분에 벡터 이름을 넣어주면 됩니다. 위도, 경도를 얻어오는 데 성공한 경우 information from URL : ...... =false 라고 뜨는 것을 확인할 수 있습니다. 종종 에러가 뜨기도 하는 데 저는 성공한 값을 따로 저장해놓고 실패한 행만 다시 "geocode"에 넣어주는 방법을 사용하고 있습니다. 에러 원인은 인터넷이 원활하지 않은 경우, 요청 제한(쿼리 2,500개)을 넘어선 경우 등이 있다고 알고 있습니다.


* 참고: 에러 발생 시

test <- geocode("seoul", source="google")

test


> test <- geocode("seoul", source="google")

Information from URL : http://maps.googleapis.com/maps/api/geocode/json?address=seoul&sensor=false

Warning message:

geocode failed with status OVER_QUERY_LIMIT, location = "seoul"


> test

      lon      lat

1     NA       NA




# 3-2. 값 확인


travel_add02 <- travel_add01 %>% mutate(city = travel_ht12$city)

head(travel_add02, 8)


> travel_add02 <- travel_add01 %>% mutate(city = travel_ht12$city)

> head(travel_add02, 8)

        lon lat       city

1 -77.042754 -12.04637       리마

2   9.189982  45.46420   밀라노

3  19.040235  47.49791 부다페스트

4 153.025124 -27.46977   브리즈번

5  96.195132  16.86607    양곤

6   8.541694  47.37689   취리히

7   2.352222  48.85661     파리

8  14.437800  50.07554  프라하


'head'로 출력해보니 위도(lat), 경도(lon)가 제대로 들어와 있었습니다. 이를 이용해서 다음 포스팅에서는 해당 지역을 지도에 마킹하여 출력해보겠습니다.







# 4-1. 지도 그리기


world <- map_data("world")


'qmap' 등으로 간단하게 지도를 출력하는 방법도 있지만, 라벨을 사용하고 싶어 지도와 마킹을 다른 함수를 사용해 출력하겠습니다. 우선 'ggplot2' 패키지에 있는 함수 'map_data'를 이용해 세계 지도의 레이아웃(.... 테두리?)을 world로 저장해줍니다.




# 4-2. 마커 출력하기


ggplot(travel_add02, aes(x=lon, y=lat)) +

    geom_polygon(data=world, aes(x=long, y=lat, group=group), fill="white", color="grey95") +

    geom_point(color="grey", alpha=.55, aes(), size=3) +

    geom_point(color="grey", alpha=.75, shape=1, aes(), size=3) +

    geom_label_repel(aes(fill=factor(city), label=city), fontface="bold", color="white", 

box.padding=0.35, point.padding=0.5, segment.color="grey70", fontface="bold",

size=09, family="AppleGothic") +

    theme(legend.position = 'none')


> ggplot(travel_add02, aes(x=lon, y=lat)) +

      geom_polygon(data=world, aes(x=long, y=lat, group=group), fill="white", color="grey95") +

      geom_point(color="grey", alpha=.55, aes(), size=3) +

      geom_point(color="grey", alpha=.75, shape=1, aes(), size=3) +

      geom_label_repel(aes(fill=factor(city), label=city), fontface="bold", color="white", 

  box.padding=0.35, point.padding=0.5, segment.color="grey70", fontface="bold",

  size=09, family="AppleGothic") +

      theme(legend.position = 'none')




'ggplot'을 이용해 지도와 라벨을 출력했습니다. 단계를 나누어 진행해보겠습니다.


우선 위도, 경도가 저장되어있는 데이터 프레임(travel_add02)을 넣고 축 이름을 지정해줍니다. 다음으로 'geom_polygon'을 이용해 'map_data'로 그렸던 지도에 위도, 경도 값을 주고 바탕 색(fill)과 테두리 색(color)을 지정해줍니다. 참고로 grey 뒤에 붙은 숫자가 낮을수록 진한 회색입니다. 여기까지 진행하면 다음과 같은 기본 지도가 만들어집니다.




다음으로 출력 대상의 위도, 경도에 동그란 점을 찍어주기 위하여 'geom_point'를 사용해보겠습니다. 원을 연한 색으로 채우고 진한 테두리를 출력해주기 위해 두 개로 나누어 썼습니다. 색, 투명도(alpha), 크기(size)를 입력해주고 원을 사용하기 위해 shape 값을 1로 주었습니다. (2=삼각형, 3=더하기 기호, 4=엑스표, 5=마름모, ...) 여기까지 진행한 결과는 다음과 같습니다. 공항의 위치에 제대로 마킹이 되었음을 확인할 수 있었습니다.




마지막으로 라벨 출력 단계입니다. 'geom_text'나 'geom_label'로 간단하게 출력해도 되지만, 붙어있는 경우 오버랩되는 단점이 있습니다. 유럽에만 5개의 마크가 찍혔으므로 'ggrepel'패키지에 있는 'geom_label_repel'을 이용해 출력하겠습니다. 우선 축(aes)에 출력 텍스트가 담긴 벡터(사용된 자료는 이전 포스팅을 참조해주세요.)를 넣어주었습니다. 이후 라벨 채우기 색(color), 박스 크기(box.padding), 폰트 사이즈(size), 사용 폰트(family) 등도 설정해주었습니다. 이를 이용해 출력한 최종 결과는 [그림 1]과 같습니다. 혹시 위의 과정 그대로 출력했는데 라벨에 글자(리마, 파리...)가 제대로 출력되지 않는 분들은 아래의 포스팅을 참고해주세요.



(참고) ggplot, 한국어 출력 가능한 폰트 확인 (바로가기)







# 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 파일로 내보냈습니다.




# 1. 지도, 라벨 출력 시 폰트가 깨지는 경우 (네모 박스)


ggplot(travel_add02, aes(x=lon, y=lat)) +

    geom_polygon(data=world, aes(x=long, y=lat, group=group), fill="white", color="grey95") +

    geom_point(color="grey", alpha=.55, aes(), size=3) +

    geom_point(color="grey", alpha=.75, shape=1, aes(), size=3) +

    geom_label_repel(aes(fill=factor(city), label=city), fontface="bold", color="white", 

box.padding=0.35, point.padding=0.5, segment.color="grey70",

fontface="bold", size=09) +

    theme(legend.position = 'none')


> ggplot(travel_add02, aes(x=lon, y=lat)) +

      geom_polygon(data=world, aes(x=long, y=lat, group=group), fill="white", color="grey95") +

      geom_point(color="grey", alpha=.55, aes(), size=3) +

      geom_point(color="grey", alpha=.75, shape=1, aes(), size=3) +

      geom_label_repel(aes(fill=factor(city), label=city), fontface="bold", color="white", 

  box.padding=0.35, point.padding=0.5, segment.color="grey70",

  fontface="bold", size=09) +

      theme(legend.position = 'none')



지도 출력 시 'geom_text', 'geom_label', 'geom_label_repel' 등을 사용하면 위와 같이 네모 박스만 출력되는 때가 있습니다. 이 경우는 코드에서 폰트(family) 지정을 해주지 않았을 때 생기는 경우가 대부분입니다. 폰트 지정을 해주지 않는 경우 (어딘가에서 설정된) 기본 폰트가 디폴트 값으로 사용되어 해당 언어의 문자를 출력할 수 없기 때문입니다. 출력 가능 폰트를 확인하기 위해 우선 'extrafont' 패키지의 'font_import'를 이용해 폰트를 불러옵니다. 그다음에는 'fonts'를 이용하여 사용 가능 폰트를 확인하고 그중 원하는 폰트를 family=에 넣어주면 됩니다.


> library(extrafont)

> font_import()

> fonts()


> fonts()


[1] ".Keyboard"             "System Font"   "Andale Mono"       "Apple Braille"

[5] "AppleMyungjo"      "Arial Black"       "Arial" "Arial Narrow"

[9] "Arial Rounded MT Bold" "Arial Unicode MS" "Bodoni Ornaments" "Bodoni 72 Smallcaps"

[13] "Brush Script MT" "Comic Sans MS" "Courier New"       "DIN Alternate"

[17] "DIN Condensed"         "Georgia" "Impact" "Khmer Sangam MN"

[21] "Lao Sangam MN" "Luminari"          "Microsoft Sans Serif" "Tahoma"

[25] "Times New Roman"       "Trattatello" "Trebuchet MS"          "Verdana"

[29] "Webdings" "Wingdings"         "Wingdings 2" "Wingdings 3"  



ggplot(travel_add02, aes(x=lon, y=lat)) +

    geom_polygon(data=world, aes(x=long, y=lat, group=group), fill="white", color="grey95") +

    geom_point(color="grey", alpha=.55, aes(), size=3) +

    geom_point(color="grey", alpha=.75, shape=1, aes(), size=3) +

    geom_label_repel(aes(fill=factor(city), label=city), fontface="bold", color="white", 

box.padding=0.35, point.padding=0.5, segment.color="grey70",

fontface="bold", size=09, family="AppleGothic") +

    theme(legend.position = 'none')


> ggplot(travel_add02, aes(x=lon, y=lat)) +

     geom_polygon(data=world, aes(x=long, y=lat, group=group), fill="white", color="grey95") +

     geom_point(color="grey", alpha=.55, aes(), size=3) +

     geom_point(color="grey", alpha=.75, shape=1, aes(), size=3) +

     geom_label_repel(aes(fill=factor(city), label=city), fontface="bold", color="white",

 box.padding=0.35, point.padding=0.5, segment.color="grey70",

 fontface="bold", size=09family="AppleGothic") +

     theme(legend.position = 'none')



+ Recent posts