Search
🗺️

[R] R을 활용한 국가별 지도 이미지 생성

어떤 서비스를 통해 국가별 지도 이미지를 간단히 생성할 수 있는 방법을 알고 계시다면 이 글이 유용성이 다소 부족하게 느껴질 수 있습니다.

배경

보고서, 특히 PPT 형식의 보고서를 작성하다보면 이따금씩 특정 국가의 이미지가 필요합니다. 제가 재직 중인 부서에서는 정말 다양한 국가의 회사, 사람들과 함께 일하기 때문에 지도를 활용하는 일이 빈번합니다. 2~3개 국가의 지도만 필요하다면 구글에서 검색해서 붙여 넣으면 그만이지만, 만약 보고서에 20개 이상의 이미지가 필요하다면 어떻게 해야 할까요?
각 국가의 이미지를 구글에서 하나씩 찾을 수 있겠지만 이미지의 일관성이 부족하거나 무료 사용이 가능하지 않은 이미지가 대부분일 것입니다.
이런 상황에서 R은 우리에게 한 줄기 빛이 되어줄 수 있습니다. 단순 반복 작업을 줄이고 우리가 필요로 하는 국가들의 지도 이미지들을 일관된 스타일과 포맷으로 빠르게 생성할 수 있습니다.
R을 활용하여 20개가 넘는 국가들의 이미지를 후딱 추출하는 방법을 알아보겠습니다.

maps 패키지

maps 패키지는 다양한 지리 데이터를 제공하고 간단한 지도를 그릴 수 있는 함수를 제공합니다.(click). library 함수를 통해 maps 패키지를 불러오겠습니다.
library(maps)
R
복사
국가명을 정확히 지정해주어야 지도를 생성할 수 있습니다.
대한민국도 South Korea, Republic of Korea와 같이 기관에 따라 달리 부르는 것처럼 R에서 제공되는 데이터들 역시 같은 국가여도 다른 명칭을 붙여서 사용합니다. 따라서 항상 사전에 국가 명칭에 대한 사전(dictionary)를 확인하는 것이 필수입니다.
maps 데이터의 map 함수를 활용하여 국가명을 살펴보겠습니다.
library(maps) all_regions <- map('world', plot = FALSE)$names #데이터프레임으로 만들기 all_regions_df <- data.frame(region = all_regions) head(all_regions_df) #> region #> 1 Aruba #> 2 Afghanistan #> 3 Angola #> 4 Angola:Cabinda #> 5 Anguilla #> 6 Albania
R
복사
map 함수의 첫번째 인자에는 활용할 데이터베이스 명칭을 작성합니다.
‘world’는 Natural Earth에서 제공하는 무료 벡터 및 래스터 지도 데이터입니다. Natural Earth에 관한 상세한 내용은 후술 하겠습니다.
all_region_df라는 이름으로 생성한 데이터프레임의 region 변수에서 자신이 생성하고자 하는 국가들의 명칭을 찾아봅니다.
R studio 환경에서는 View(all_region_df) 코드를 통해 데이터프레임을 직접 조회하여 검색하는 것이 가장 간편합니다.

국가별 지도 이미지 생성

우리나라 지도

regions 인자에 “South Korea”로 우리나라만 불러올 수 있고, c() 함수를 통해 국가를 여러 개 지정하여 여러 개 국가의 지도를 1개의 이미지로 생성할 수 있습니다.
library(maps) #대한민국 지도 그리기 map("world", regions = "South Korea", fill = TRUE, col = "gray80") #대한민국, 북한 각각 색상 다르게 지정 map("world", regions = c("South Korea", "North Korea"), fill = TRUE, col = "darkblue")
R
복사

유로 2024 진출국

다음 달 개최될 유로 2024에는 총 24개 국가가 참가합니다. 진출국들의 지도를 생성해보죠.
folder_path : 이미지 파일들을 저장할 경로를 지정합니다.
cuntries : 24개국 진출국에 대한 벡터를 생성합니다.
for : 반복문을 통해 24개국을 차례로 이미지를 생성하고 png 파일로 저장합니다.
png : PNG 파일을 생성하고 크기와 배경색에 대한 옵션을 지정할 수 있습니다.
dev.off : png, jpeg, pdf 등의 함수를 사용하여 열린 그래픽 디바이스를 종료합니다. 그래픽 디바이스를 종료하지 않으면 파일이 완전히 생성되지 않습니다.
countries의 국가 순서대로 국가명 앞에 “01. ”, “02. ”, “03.”, “04. ” … 와 같은 텍스트를 넣어 윈도우 폴더에서도 숫자에 따라 오름차순 정렬이 될 수 있도록 합니다.
파일명, 이미지 크기 등은 필요에 따라 옵션을 달리 지정하면 됩니다.
library(maps) # 폴더 경로 설정 folder_path <- "C:/Users/wschoi/Desktop/유로2024" #축구 유로 2024 24개국 진출국 A~F조 순서 countries <- c("Germany", "UK:Scotland", "Hungary", "Switzerland", "Spain", "Croatia", "Italy", "Albania", "Slovenia","Denmark", "Serbia", "UK:England", "Poland", "Netherlands", "Austria", "France", "Belgium", "Slovakia", "Romania", "Ukraine", "Turkey", "Georgia", "Portugal", "Czech Republic") # 각 국가별로 지도 이미지 저장 for (i in seq_along(countries)) { country <- countries[i] # 파일 이름 생성, 콜론과 공백을 처리 file_name <- sprintf("%s/%02d. %s.png", folder_path, i, gsub("[: ]", "_", country)) # PNG 파일 생성, 배경을 투명하게 설정 png(file_name, width = 800, height = 600, bg = "transparent") # 지도 그리기, fill 파라미터로 채우기 색상 지정 map(database = 'world', regions = gsub(":.+$", "", country), fill = TRUE, col = "gray80") # 디바이스 종료 dev.off() print(paste("Saved:", file_name)) #파일이 잘 생성되는지 확인 }
R
복사
경로를 지정하여 위 코드를 실행한 결과는 아래와 같습니다.
PPT, Word 등 MS Office에 첨부할 수 있는 png 파일들이 생성되었습니다!

주의할 국가

미국
뉴질랜드
싱가포르
홍콩
미국의 경우 하와이 주 때문에 map 함수에서 regions 인자를 단순히 “USA”로 하는 경우 이미지가 작게 출력 됩니다. 뉴질랜드도 마찬가지로 작게 출력 됩니다.
싱가포르, 홍콩과 같은 도시 국가의 경우 면적이 작아 해상도가 떨어져 국경선이 직선으로 나타납니다.
다른 방법으로 이 같은 문제를 해결하는 방법을 알아보겠습니다.

미국

데이터베이스를 ‘world’ → ‘usa’로 변경하면 주(state)간 경계가 없고, ‘state’로 변경하면 주 간 경계를 나타낼 수 있습니다.
map('usa', fill = TRUE, col = "gray80") map('state', fill = TRUE, col = "gray80")
R
복사
특정 주만 골라서 나타낼 수도 있습니다.
map('state', regions = "florida", fill = TRUE, col = "gray80")
R
복사
앞서 유로 2024에 참가하는 국가와 함께 미국을 호출하기 위해선 다음과 if else문을 활용해 USA의 경우 데이터베이스를 ‘usa’를 활용하도록 지정해줍니다.
library(maps) # 국가 목록에 미국 추가 countries <- c("Germany", "UK:Scotland", "Hungary", "Switzerland", "Spain", "Croatia", "Italy", "Albania", "Slovenia","Denmark", "Serbia", "UK:England", "Poland", "Netherlands", "Austria", "France", "Belgium", "Slovakia", "Romania", "Ukraine", "Turkey", "Georgia", "Portugal", "Czech Republic", "USA") # 폴더 경로 설정 folder_path <- "C:/Users/wschoi/Desktop/글" # 각 국가별로 지도 이미지 저장 for (i in seq_along(countries)) { country <- countries[i] file_name <- sprintf("%s/%02d. %s.png", folder_path, i, gsub("[: ]", "_", country)) # PNG 파일 생성, 배경을 투명하게 설정 png(file_name, width = 800, height = 600, bg = "transparent") # 미국일 경우 하와이 제외하고 지도 그리기 if (country == "USA") { map('usa', fill = TRUE, col = "gray80") } else { map(database = 'world', regions = gsub(":.+$", "", country), fill = TRUE, col = "gray80") } # 디바이스 종료 dev.off() print(paste("Saved:", file_name)) }
R
복사

뉴질랜드

뉴질랜드 역시 map 함수에서 단순히 regions 인자에 “New Zealand” 값을 부여하면 “Chatham Island” 때문에 본토 이미지가 작게 출력 됩니다.
채텀섬은 좌측 사진처럼 본래 뉴질랜드의 동쪽에 위치하지만 map 함수에서 지도를 생성했을 때는 좌측 끝에 잡힙니다.
출처: Google Map
map 함수를 통해 생성하는 지도는 대서양을 중심으로 하고 있습니다. 대서양 중심의 지도에서는 뉴질랜드 본토가 최우측 최하단에 위치해서 뉴질랜드 본토보다 우측에 위치한 채텀섬이 지도의 왼쪽으로 옮겨가고 거리가 멀게 출력 되는 문제가 있습니다.
이런 문제를 해결하기 위해 다음과 같이 남섬, 북섬만을 지정해서 따로 출력하는 방법이 있습니다.
library(maps) # 파일 저장 경로 설정 file_path <- "C:/Users/wschoi/Desktop/글/New_Zealand.png" # PNG 파일 생성, 배경을 투명하게 설정 png(file_path, width = 800, height = 600, bg = "transparent") # 지도 그리기, 남섬과 북섬 포함 map("world", regions = c("New Zealand:South Island", "New Zealand:North Island"), fill = TRUE, col = "gray80") # 디바이스 종료 dev.off() #> png #> 2
R
복사
그러나 TRUE 자동화를 이루기 위한 코드는 아래와 같습니다. 24개국에 미국과 뉴질랜드를 추가하여 국가별 이미지를 생성하는 코드입니다.
위에서 본 미국과 마찬가지로 if else 문을 통해 regions가 “New Zeland”인 경우 다른 옵션으로 실행하는 코드를 추가했습니다.
# 국가 목록에 미국과 뉴질랜드 추가 countries <- c("Germany", "UK:Scotland", "Hungary", "Switzerland", "Spain", "Croatia", "Italy", "Albania", "Slovenia","Denmark", "Serbia", "UK:England", "Poland", "Netherlands", "Austria", "France", "Belgium", "Slovakia", "Romania", "Ukraine", "Turkey", "Georgia", "Portugal", "Czech Republic", "USA", "New Zealand") # 경로 설정 folder_path <- "C:/Users/wschoi/Desktop/글" for (i in seq_along(countries)) { country <- countries[i] file_name <- sprintf("%s/%02d. %s.png", folder_path, i, gsub("[: ]", "_", country)) png(file_name, width = 800, height = 600, bg = "transparent") # 국가별 조건에 따라 지도 그리기 if (country == "USA") { map('usa', fill = TRUE, col = "gray80") } else if (country == "New Zealand") { map('world', regions = c("New Zealand:North Island", "New Zealand:South Island", "New Zealand:Stewart Island", "New Zealand:Auckland Island", "New Zealand:Rangitoto Island", "New Zealand:Great Barrier Island", "New Zealand:Resolution Island"), fill = TRUE, col = "gray80") } else { map(database = 'world', regions = gsub(":.+$", "", country), fill = TRUE, col = "gray80") } dev.off() print(paste("Saved:", file_name)) }
R
복사

rnaturalearth

도시국가: 홍콩과 싱가포르

홍콩과 싱가포르와 같이 면적이 작은 도시국가들의 지도를 생성하기 위해선 고해상도의 지리 데이터를 제공하는 rnaturalearth 패키지를 활용해야 합니다. 그러나 그렇게 가져온 지리 데이터가 maps 패키지와는 호환되지 않기 때문에 ggplot 을 활용하여 지도를 별도로 생성합니다.
우선 ne_download 함수를 사용하여 rnaturalearth 패키지로부터 sf(Simple Features) 포맷의 고해상도 지리 데이터를 가져옵니다.
dplyrfilter 함수를 활용하여 admin 변수에서 “Hong Kong S.A.R.” 값만 필터링합니다.
2024년 5월 2일 기준 데이터셋에서 홍콩은 18개 지역으로 나뉘어져 있습니다.
sf 패키지의 st_union 함수를 통해 18개 지역 데이터를 단일 객체로 합쳐 홍콩 국토 전체를 나타내는 데이터로 만듭니다.
생성된 hong_kong_data을 활용하여 ggplot으로 지도를 그립니다. PPT에 들어갈 최대한 깔끔한 지도가 필요했기 때문에 경계선 색상을 투명하게 하고 그리드, 축 등을 모두 제거했습니다. 필요에 따라 옵션을 조정하여 사용하면 됩니다.
plot_sf_map 함수를 활용하여 지정된 국가의 이름을 받아 해당 국가의 sf 데이터를 다운로드하고 지오메트리 데이터를 결합하여 지도를 생성합니다.
library(rnaturalearth) library(sf) library(dplyr) library(ggplot2) # 지도 생성 함수 정의 plot_sf_map <- function(country_name, admin_region) { # 고해상도의 지역 데이터 가져오기 region_data <- ne_download(scale = 10, type = 'states', category = 'cultural', returnclass = "sf") %>% filter(admin == admin_region) %>% st_union() # 지역을 단일 객체로 합치기 # 지도 생성 ggplot(data = region_data) + geom_sf(fill = "gray80", color = "transparent") + # 경계선 색상을 투명하게 설정 theme_void() + theme( plot.background = element_blank(), # 플롯 배경 투명 처리 panel.grid.major = element_blank(), # 주요 그리드 제거 panel.grid.minor = element_blank(), # 보조 그리드 제거 panel.border = element_blank(), # 패널 경계선 제거 axis.text = element_blank(), # 축 텍스트 제거 axis.title = element_blank(), # 축 제목 제거 axis.ticks = element_blank() # 축 눈금 제거 ) }
R
복사
# 홍콩 지도 생성 plot_sf_map("Hong Kong", "Hong Kong S.A.R.")
R
복사
글 서두에 말씀 드렸듯 그냥 Hong Kong이 아닌 “Hong Kong S.A.R.” (Special Administrative Region) 명칭을 사용하고 있습니다. 따라서 ne_download로 다운로드 받은 데이터의 admin 변수의 명칭을 잘 살펴보시길 바랍니다.
#싱가포르 지도 생성 plot_sf_map("Singapore", "Singapore")
R
복사

rnaturalearth 저작권

maps 패키지에서 활용하는 'world' 데이터 베이스는 'Natural Earth'의 데이터를 기반으로 합니다.'Natural Earth'의 이용약관에서는 다음과 같이 설명하고 있습니다.
 The primary authors, Tom Patterson and Nathaniel Vaughn Kelso, and all other contributors renounce all financial claim to the maps and invites you to use them for personal, educational, and commercial purposes
패키지의 주 제작자인 톰 패터슨, 나다니엘 본 켈소 그리고 모든 컨트리뷰터들은 지도에 대한 모든 재정적 권리를 포기하고 개인, 교육, 상업적 목적으로 사용을 허가한다고 명시하고 있습니다.
따라서 위 R 코드를 통해 생성한 이미지를 회사에서 사용하는 데 저작권의 문제는 없겠습니다.

마무리

R을 활용하여 국가별 이미지를 생성하는 방법을 알아보았습니다.
더 세부적인 옵션을 조정하여 다양한 것들을 보여드릴 수도 있었으나 글이 너무 길어질 것으로 보아 많이 줄이게 되었습니다.
실무에서 R을 활용할 수 있는 곳은 생각보다 정말 많습니다.
모든 문과 계열의 직무에서 R을 활용하는 날까지 열심히 활동하겠습니다.
감사합니다.
Main Page | Category |  Tags | About Me | Contact