Tistory 의 코드 블록에 'R' 언어도 사용할 수 있게 해달라고 며칠전에 제안 문의를 드렸었는데요, 드디어 'R' 언어가 추가되었네요. 잘 사용하겠습니다. Tistory, 감사합니다. 꾸벅~!  

 

지리공간 벡터 데이터는 (a) 점(point), 선(linestring), 면(polygon) 등의 리스트로 이루어진 지리공간 데이터(geographic data)와, 지리공간 데이터를 제외한 (b) 속성 데이터(attribute data)로 구성이 됩니다. 속성 데이터(attritubes)를 사용해서 각 지리공간 별 특성 (예: 지역 이름, 면적, 인구, 예상수명 등)을 표현하게 됩니다. 

 

이번 포스팅에서는 벡터 데이터에서 속성 정보를 가져오는 여러가지 방법을 소개하겠습니다.  'sf' 객체는 R data.frame 에서 사용하는 클래스를 지원(!!!)하므로 Base R 이나 혹은 dplyr 패키지를 사용하여 데이터 전처리하는 작업에 이미 능숙한 분이라면 이번 포스팅은 특별한 것 없이 매우 쉽게, 복습하는 기분으로 보실 수 있을 거예요. 

 

 

(1) 'sf' 객체에서 속성 정보만 가져오기: st_drop_geometry()

(2) Base R 구문으로 벡터 데이터 속성 정보의 행과 열 가져오기
    (subsetting attributes from geographic vector data using Base R)

(3) dplyr 로 벡터 데이터 속성 정보의 행과 열 가져오기
    (subsetting attributes from geographic vector data using dplyr)

(4) 한개 칼럼만 가져온 결과를 벡터로 반환하기 (extracting a single vector)

 

 

 

먼저, 지리공간 데이터 객체를 다루기 위한 sf 패키지와 데이터 전처리에 사용할 dplyr 패키지를 불러오고, 예제로 사용할 세계 나라 데이터 ('world') 를 spData 패키지로 부터 가져오겠습니다. 

'world' 벡터 데이터셋은 10개의 속성 데이터 (10 attributes) 와 1개의 지리기하 칼럼 (1 geometry column) 으로 구성이 되어 있으며, 총 177개의 행 (즉, 국가) 에 대한 정보가 들어 있습니다. 

 

## ==============================
## R GeoSpatial data analysis
## - Vector Attribute data operations
## - reference: https://geocompr.robinlovelace.net/attr.html
## ==============================

library(sf)
library(dplyr)
library(spData)

## vector dataset 'world': 10 attritubes and 1 geometry column
str(world)
# tibble [177 x 11] (S3: sf/tbl_df/tbl/data.frame)
# $ iso_a2   : chr [1:177] "FJ" "TZ" "EH" "CA" ...
# $ name_long: chr [1:177] "Fiji" "Tanzania" "Western Sahara" "Canada" ...
# $ continent: chr [1:177] "Oceania" "Africa" "Africa" "North America" ...
# $ region_un: chr [1:177] "Oceania" "Africa" "Africa" "Americas" ...
# $ subregion: chr [1:177] "Melanesia" "Eastern Africa" "Northern Africa" "Northern America" ...
# $ type     : chr [1:177] "Sovereign country" "Sovereign country" "Indeterminate" "Sovereign country" ...
# $ area_km2 : num [1:177] 19290 932746 96271 10036043 9510744 ...
# $ pop      : num [1:177] 8.86e+05 5.22e+07 NA 3.55e+07 3.19e+08 ...
# $ lifeExp  : num [1:177] 70 64.2 NA 82 78.8 ...
# $ gdpPercap: num [1:177] 8222 2402 NA 43079 51922 ...
# $ geom     :sfc_MULTIPOLYGON of length 177; first list element: List of 3
# ..$ :List of 1
# .. ..$ : num [1:8, 1:2] 180 180 179 179 179 ...
# ..$ :List of 1
# .. ..$ : num [1:9, 1:2] 178 178 179 179 178 ...
# ..$ :List of 1
# .. ..$ : num [1:5, 1:2] -180 -180 -180 -180 -180 ...
# ..- attr(*, "class")= chr [1:3] "XY" "MULTIPOLYGON" "sfg"
# - attr(*, "sf_column")= chr "geom"
# - attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA NA NA NA NA NA NA NA NA NA
# ..- attr(*, "names")= chr [1:10] "iso_a2" "name_long" "continent" "region_un" ...

dim(world)
# [1] 177  11


 

 

 

(1) 'sf' 객체에서 속성 정보만 가져오기: st_drop_geometry()

 

지리공간 'sf' 객체에는 항상 점(points)/선(lines)/면(polygons) 등의 지리기하 데이터를 리스트로 가지고 있는 geometry 칼럼이 항상 따라 다닙니다. 만약 'sf' 객체로 부터 이 geometry 칼럼을 제거하고 나머지 속성 정보만으로 DataFrame 을 만들고 싶다면 sf 패키지의 st_drop_geometry() 메소드를 사용합니다. geometry 칼럼의 경우 지리기하 점/선/면 등의 리스트 정보를 가지고 있기 때문에 메모리 점유가 크기 때문에, 사용할 필요가 없다면 geometry 칼럼은 제거하고 속성 정보만 dataframe 으로 만들어서 분석을 진행하는게 좋겠습니다. 

(아래의 (2)번 부터 소개하는 부분 가져오기(subset) 방법을 사용하면 여전히 geometry 칼럼이 그림자차럼 같이 따라와서 여전히 달라붙어 있을 것입니다.) 

 

 

## Extracting the attribute data of an 'sf' object
world_df <- st_drop_geometry(world)
class(world_df)
# [1] "tbl_df"     "tbl"        "data.frame"

names(world_df)
# [1] "iso_a2"    "name_long" "continent" "region_un" "subregion" "type"      "area_km2"  "pop"        
# [9] "lifeExp"  "gdpPercap

 

 

 

(2) Base R 구문으로 벡터 데이터 속성 정보의 행과 열 가져오기
    (subsetting attributes from geographic vector data using Base R)

 

R data.frame 에서 i 행(row)과 j 열(column)을 가져올 때는 df[i, j] , subset(), $ 구문을 사용합니다.  이때  (a) i 행과  j 열에는 정수로 위치(subset rows and columns by position) 을 사용하거나, (b) j 행의 이름 (subset columns by name)을 사용할 수 있으며, (c) 논리 벡터 (logical vector)를 사용해서 i 행의 부분집합(subset rows by a logical vector) 을 가져올 수 있습니다. 

 

여기서 다시 한번 짚고 넘어갈 점은, 특정 행과 열의 부분집합을 가져오면 제일 끝에 geometry 칼럼이 꼭 껌딱지처럼 달라붙어서 같이 따라온다는 점입니다.

 

 

(2-a-1) 위치를 지정해서 지리공간 벡터 데이터로 부터 부분 행 가져오기 (subset rows by position)

 

## -- Vecter arrtibute subsetting
## subsetting columns returns results with geometry column as well.

## -- subset rows by position
world[1:3, ]

# Simple feature collection with 6 features and 10 fields
# geometry type:  MULTIPOLYGON
# dimension:      XY
# bbox:           xmin: -180 ymin: -18.28799 xmax: 180 ymax: 83.23324
# geographic CRS: WGS 84
# # A tibble: 6 x 11
# iso_a2 name_long  continent  region_un subregion type   area_km2     pop lifeExp gdpPercap                           geom
# <chr>  <chr>      <chr>      <chr>     <chr>     <chr>     <dbl>   <dbl>   <dbl>     <dbl>    <MULTIPOLYGON [arc_degree]>
#   1 FJ     Fiji       Oceania    Oceania   Melanesia Sover~   1.93e4  8.86e5    70.0     8222. (((180 -16.06713, 180 -16.555~
#   2 TZ     Tanzania   Africa     Africa    Eastern ~ Sover~   9.33e5  5.22e7    64.2     2402. (((33.90371 -0.95, 34.07262 -~
#   3 EH     Western S~ Africa     Africa    Northern~ Indet~   9.63e4 NA         NA         NA  (((-8.66559 27.65643, -8.6651~

 

 

(2-a-2) 위치를 지정해서 지리공간 벡터 데이터로 부터 부분 열 가져오기 (subset columns by position)

 

## -- subset columns by position
world[, 1:3]

# Simple feature collection with 177 features and 3 fields
# geometry type:  MULTIPOLYGON
# dimension:      XY
# bbox:           xmin: -180 ymin: -90 xmax: 180 ymax: 83.64513
# geographic CRS: WGS 84
# # A tibble: 177 x 4
# iso_a2 name_long        continent                                                                                   geom
# <chr>  <chr>            <chr>                                                                <MULTIPOLYGON [arc_degree]>
# 1 FJ     Fiji             Oceania       (((180 -16.06713, 180 -16.55522, 179.3641 -16.80135, 178.7251 -17.01204, 178.5968~
# 2 TZ     Tanzania         Africa        (((33.90371 -0.95, 34.07262 -1.05982, 37.69869 -3.09699, 37.7669 -3.67712, 39.202~
# 3 EH     Western Sahara   Africa        (((-8.66559 27.65643, -8.665124 27.58948, -8.6844 27.39574, -8.687294 25.88106, -~
# 4 CA     Canada           North America (((-122.84 49, -122.9742 49.00254, -124.9102 49.98456, -125.6246 50.41656, -127.4~
# 5 US     United States    North America (((-122.84 49, -120 49, -117.0312 49, -116.0482 49, -113 49, -110.05 49, -107.05 ~
# 6 KZ     Kazakhstan       Asia          (((87.35997 49.21498, 86.59878 48.54918, 85.76823 48.45575, 85.72048 47.45297, 85~
# 7 UZ     Uzbekistan       Asia          (((55.96819 41.30864, 55.92892 44.99586, 58.50313 45.5868, 58.68999 45.50001, 60.~
# 8 PG     Papua New Guinea Oceania       (((141.0002 -2.600151, 142.7352 -3.289153, 144.584 -3.861418, 145.2732 -4.373738,~
# 9 ID     Indonesia        Asia          (((141.0002 -2.600151, 141.0171 -5.859022, 141.0339 -9.117893, 140.1434 -8.297168~
# 10 AR     Argentina        South America (((-68.63401 -52.63637, -68.25 -53.1, -67.75 -53.85, -66.45 -54.45, -65.05 -54.7,~
# # ... with 167 more rows

 

 

(2-b) 칼럼 이름을 사용해서 지리공간 벡터 데이터로 부터 부분 열 가져오기 (subset columns by name)

## -- subset columns by name
world[, c("name_long", "area_km2")]

# Simple feature collection with 177 features and 2 fields
# geometry type:  MULTIPOLYGON
# dimension:      XY
# bbox:           xmin: -180 ymin: -90 xmax: 180 ymax: 83.64513
# geographic CRS: WGS 84
# # A tibble: 177 x 3
# name_long         area_km2                                                                                    geom
# <chr>                <dbl>                                                             <MULTIPOLYGON [arc_degree]>
# 1 Fiji                19290. (((180 -16.06713, 180 -16.55522, 179.3641 -16.80135, 178.7251 -17.01204, 178.5968 -1...
# 2 Tanzania           932746. (((33.90371 -0.95, 34.07262 -1.05982, 37.69869 -3.09699, 37.7669 -3.67712, 39.20222 ...
# 3 Western Sahara      96271. (((-8.66559 27.65643, -8.665124 27.58948, -8.6844 27.39574, -8.687294 25.88106, -11....
# 4 Canada           10036043. (((-122.84 49, -122.9742 49.00254, -124.9102 49.98456, -125.6246 50.41656, -127.4356...
# 5 United States     9510744. (((-122.84 49, -120 49, -117.0312 49, -116.0482 49, -113 49, -110.05 49, -107.05 49,...
# 6 Kazakhstan        2729811. (((87.35997 49.21498, 86.59878 48.54918, 85.76823 48.45575, 85.72048 47.45297, 85.16...
# 7 Uzbekistan         461410. (((55.96819 41.30864, 55.92892 44.99586, 58.50313 45.5868, 58.68999 45.50001, 60.239...
# 8 Papua New Guinea   464520. (((141.0002 -2.600151, 142.7352 -3.289153, 144.584 -3.861418, 145.2732 -4.373738, 14...
# 9 Indonesia         1819251. (((141.0002 -2.600151, 141.0171 -5.859022, 141.0339 -9.117893, 140.1434 -8.297168, 1...
# 10 Argentina         2784469. (((-68.63401 -52.63637, -68.25 -53.1, -67.75 -53.85, -66.45 -54.45, -65.05 -54.7, -6...
# # ... with 167 more rows

 

 

(2-c) 논리 벡터를 사용해서 지리공간 벡터 데이터로 부터 부분 행 가져오기 (subset rows by a logical vectors)

 

## -- subset using 'logical vectors'
small_area_bool <- world$area_km2 < 10000
summary(small_area_bool)
#    Mode   FALSE    TRUE 
# logical     170       7

small_countries <- world[small_area_bool, ]
nrow(small_countries)
# [1]  7

## or equivalently above
small_countries <- world[world$area_km2 < 10000, ]

## -- using base R subset() function
small_countries <- subset(world, area_km2 < 10000)

 

 

 

(3) dplyr 로 벡터 데이터 속성 정보의 행과 열 가져오기
    (subsetting attributes from geographic vector data using dplyr)

 

R의 dplyr 패키지를 사용해서 지리공간 벡터 데이터의 속성 정보를 처리하면 Base R 대비 코드의 가독성이 좋고, 속도가 빠르다는 장점이 있습니다.  dplyr 패키지에서 체인('%>%')으로 파이프 연산자 (pipe operator) 를 사용하면 작업 흐름 (work flow) 를 자연스럽게 따라가면서 코딩을 할 수 있어서 코드의 가독성이 상당히 좋습니다.  그리고 dplyr 은 소스코드가 C++로 되어 있어 속도도 상당히 빠른 편입니다.  

dplyr 의 select(), slice(), filter(), pull() 함수를 사용해서 지리공간 벡터 데이터의 속성 정보의 부분 행과 열을 가져와 보겠습니다

 

 

(3-1) dplyr::select(sf, name) 함수를 사용하여 이름으로 특정 열 선택하기 (selects columns by name)

 

이때, select() 함수는 dplyr 패키지 뿐만 아니라 raster 패키지에도 존재하므로 dplyr::select() 처럼 select() 함수 이름 앞에 패키지 이름을 명시적으로 같이 표기해 줌으로써 불명확성을 없앨 수 있습니다. dplyr::select(data.frame 이름, 칼럼1, 칼럼2, ...) 의 구문으로 원하는 열의 속성 정보만 가져올 수 있습니다. (지리공간 벡터 데이터라고 해서 select() 구문에는 특별한 것이 없으며, subset 결과의 끝에 geometry 칼럼이 달라 붙어서 따라와 있다는 점이 다릅니다.)

 

## -- using 'dplyr' package
## : select(), slice(), filter(), pull()

## select(): selects columns by name
## : "geom" column remains. 
world1 = dplyr::select(world, name_long, area_km2)

names(world1)
# [1] "name_long" "area_km2"  "geom"

 

 

(3-2) dplyr::select(sf, position) 함수를 사용하여 위치로 특정 열 선택하기 (select columns by position)

 

## select() columns by position
world1 = dplyr::select(world, 2, 7)

names(world1)
# [1] "name_long" "area_km2"  "geom"

 

 

(3-3) dplyr::select(sf, name1:name2) 함수를 사용하여 범위 내의 모든 열 선택하기 (a range of columns by ':')

 

':' 연산자를 사용하여 두개의 위치(position1:position2)나 칼럼 이름(name1:name2)들의 범위 사이에 들어있는 모든 열을 한꺼번에 가져올 수 있습니다. 선택해서 가져오고 싶은 열이 많고 범위로 표현할 수 있을 경우 유용합니다. 

 

## select() also allows subsetting of a range of columns with the help of the : operator
world2 = dplyr::select(world, name_long:area_km2)

names(world2)
# [1] "name_long" "continent" "region_un" "subregion" "type"   "area_km2"  "geom"

 

 

(3-4) dplyr::select(sf, -name) 으로 특정 열을 제거하기 (omit specific columns with the - operator)

 

## Omit specific columns with the - operator
# all columns except subregion and area_km2 (inclusive)
world3 = dplyr::select(world, -region_un, -subregion, -area_km2, -gdpPercap)

names(world3)
# [1] "iso_a2"    "name_long" "continent" "type"      "pop"       "lifeExp"   "geom" 

 

 

(3-5) dplyr::select(sf, name_new = name_old) 로 선택해서 가져온 열 이름을 바꾸기 (subset & rename columns)

 

## select() lets you subset and rename columns at the same time
world4 = dplyr::select(world, name_long, population = pop)

names(world4)
# [1] "name_long"  "population" "geom"

 

 

(3-6) dplyr::select(sf, contains(string)) 로 특정 문자열을 포함한 칼럼을 선택하기

 

dplyr 의 select() 함수는 contains(), starts_with(), ends_with(), num_range() 와 같은 도우미 함수 (helper functions) 를 사용해서 매우 강력하고 편리하게 특정 칼럼을 선택해서 가져올 수 있습니다. 

 

## select() works with ‘helper functions’ for advanced subsetting operations, 
## including contains(), starts_with() and num_range()
## contains(): Contains a literal string
world5 = dplyr::select(world, contains('Ex'))

names(world5)
# [1] "lifeExp" "geom"

 

 

(3-7) dplyr::select(sf, starts_with(string)) 로 특정 문자열로 시작하는 칼럼을 선택하기

 

## starts_with(): Starts with a prefix
world6 = dplyr::select(world, starts_with('life'))

names(world6)
# [1] "lifeExp" "geom"

 

 

(3-8) dplyr::select(sf, ends_with(string)) 로 특정 문자열로 끝나는 칼럼을 선택하기

 

## ends_with(): Ends with a suffix
world7 = dplyr::select(world, ends_with('Exp'))

names(world7)
# [1] "lifeExp" "geom"

 

 

(3-9) dplyr::select(df, matches(regular_expression)) 으로 정규 표현식을 만족하는 특정 칼럼을 선택하기

 

아래 예는 정규 표현식(regular expression) "[p]" 를 matches() 도움미 함수 안에 사용해서, 칼럼 이름에 대/소문자 'p' 문자열이 들어있는 칼럼을 선택해서 가져온 것입니다.  

## matches(): Matches a regular expression.
world8 = dplyr::select(world, matches("[p]"))

names(world8)
# [1] "type"      "pop"       "lifeExp"   "gdpPercap" "geom"

 

 

(3-10) dplyr::select(df, num_range("x", num1:num2)) 으로 숫자 범위 안의 모든 칼럼 선택하기

 

만약 칼럼 이름이 "x1", "x2", "x3", "x4", "x5" 처럼 접두사(prefix)가 동일하고 뒤에 순차적인 정수가 붙어있는 형태라면 특정 정수 범위의 칼럼들을 선택해서 가져올 때 num_range() 도우미 함수를 select() 함수 안에 사용할 수 있습니다.  "world" sf 객체의 데이터셋은 칼럼 이름이 특정 접두사로 동일하게 시작하지 않으므로, 아래에는 간단한 data.frame 을 만들어서 예를 들어보였습니다. 

 

## -- num_range(): Matches a numerical range like x01, x02, x03. 

x1 = c(1:5)
x2 = c(6:10)
x3 = c(11:15)
x4 = c(16:20)
x5 = c(21:25)

df = data.frame(x1, x2, x3, x4, x5)
df
# x1 x2 x3 x4 x5
# 1  1  6 11 16 21
# 2  2  7 12 17 22
# 3  3  8 13 18 23
# 4  4  9 14 19 24
# 5  5 10 15 20 25

## subset using num_range()
df2 = dplyr::select(df, num_range("x", 1:3))
df2
# x1 x2 x3
# 1  1  6 11
# 2  2  7 12
# 3  3  8 13
# 4  4  9 14
# 5  5 10 15

 

 

(3-11) dplyr::slice(sf, position1:position2) 으로 특정 행 잘라서 가져오기 (slice rows by position)

 

## -- slice(): is the row-equivalent of select()
dplyr::slice(world, 3:5)

# Simple feature collection with 3 features and 10 fields
# geometry type:  MULTIPOLYGON
# dimension:      XY
# bbox:           xmin: -171.7911 ymin: 18.91619 xmax: -8.665124 ymax: 83.23324
# geographic CRS: WGS 84
# # A tibble: 3 x 11
# iso_a2 name_long continent region_un subregion type  area_km2     pop lifeExp gdpPercap
# <chr>  <chr>     <chr>     <chr>     <chr>     <chr>    <dbl>   <dbl>   <dbl>     <dbl>
#   1 EH     Western ~ Africa    Africa    Northern~ Inde~   9.63e4 NA         NA         NA 
# 2 CA     Canada    North Am~ Americas  Northern~ Sove~   1.00e7  3.55e7    82.0    43079.
# 3 US     United S~ North Am~ Americas  Northern~ Coun~   9.51e6  3.19e8    78.8    51922.
# # ... with 1 more variable: geom <MULTIPOLYGON [arc_degree]>

 

 

(3-12) dplyr::filter(sf, logical_vector) 로 조건을 만족하는 특정 행 걸러내기 (filter rows with conditions)

 

## -- filter()
# Countries with a population longer than 1 B.
world9 = filter(world, pop > 1000000000)

# world9
# Simple feature collection with 2 features and 10 fields
# geometry type:  MULTIPOLYGON
# dimension:      XY
# bbox:           xmin: 68.17665 ymin: 7.965535 xmax: 135.0263 ymax: 53.4588
# geographic CRS: WGS 84
# # A tibble: 2 x 11
# iso_a2 name_long continent region_un subregion type  area_km2    pop lifeExp gdpPercap
# * <chr>  <chr>     <chr>     <chr>     <chr>     <chr>    <dbl>  <dbl>   <dbl>     <dbl>
#   1 IN     India     Asia      Asia      Southern~ Sove~ 3142892. 1.29e9    68.0     5385.
# 2 CN     China     Asia      Asia      Eastern ~ Coun~ 9409830. 1.36e9    75.9    12759.
# # ... with 1 more variable: geom <MULTIPOLYGON [arc_degree]>

 

 

(3-13)  dplyr 의 체인('%>%')을 사용한 파이프 연산자로 filter(), select(), slice() 의 작업 흐름 만들기 (workflow by pipe operator)

 

아래에는 'world' 의 sf 객체 데이터셋으로 부터 먼저 대륙이 아시아인 국가를 걸러내고 (world %>% filter(continent == "Asia"), 이 결과를 받아서 긴 이름과 인구 칼럼을 선택하고 (%>% dplyr::select(name_long, pop)), 이 결과를 받아서 1행에서 3행까지 잘라서 가져오기(%>% slice(1:3)) 를 체인(chain %>%)으로 연결해서 파이프 연산자(pipe operator)로 작업 흐름에 따라 코딩을 한 것입니다. 

 

두번째 코드는 위와 똑같은 결과를 얻기 위해 함수 안의 함수인 중첩 함수 (nested functions) 로 표현해 본 것입니다. 앞서의 dplyr 의 chain(%>%)을 사용한 파이프 연산자(pipe operator)로 쓴 코드에 비해서 중첩 함수로 쓴 코드는 상대적으로 가독성이 떨어집니다. 

 

##-- pipe operator %>%: It enables expressive code: the output of a previous function 
## becomes the first argument of the next function, enabling chaining.
world10 = world %>%
  filter(continent == "Asia") %>%
  dplyr::select(name_long, pop) %>%
  slice(1:3)

world10
# Simple feature collection with 3 features and 2 fields
# geometry type:  MULTIPOLYGON
# dimension:      XY
# bbox:           xmin: 46.46645 ymin: -10.35999 xmax: 141.0339 ymax: 55.38525
# geographic CRS: WGS 84
# # A tibble: 3 x 3
# name_long        pop                                                                         geom
# <chr>          <dbl>                                                  <MULTIPOLYGON [arc_degree]>
# 1 Kazakhstan  17288285 (((87.35997 49.21498, 86.59878 48.54918, 85.76823 48.45575, 85.72048 47.452~
# 2 Uzbekistan  30757700 (((55.96819 41.30864, 55.92892 44.99586, 58.50313 45.5868, 58.68999 45.5000~
# 3 Indonesia  255131116 (((141.0002 -2.600151, 141.0171 -5.859022, 141.0339 -9.117893, 140.1434 -8.~


## -- The alternative to %>% is nested function calls, which is harder to read:
world11 = slice(
  dplyr::select(
    filter(world, continent == "Asia"),
    name_long, pop),
  1:3)

 

 

 

(4) dplyr::pull(sf, column_name) 으로 한개 칼럼만 가져온 결과를 벡터로 반환하기 (extracting a single vector)

 

일반적으로 dplyr 에서 특정 칼럼을 선택(select)해서 가져오면 data.frame 으로 결과를 반환합니다. 만약, 한개의 특정 칼럼만을 벡터(a single vector)로 가져오고 싶다면 명시적으로 pull() 함수를 사용해줘야 합니다. (혹은 df[ , "column_name"] 도 벡터 반환)

 

## Most dplyr verbs return a data frame. 
## To extract a single vector, one has to explicitly use the pull() command
# create throw-away data frame
d = data.frame(pop = 1:10, area = 1:10)

# (a) -- return data frame object when selecting a single column
d[, "pop", drop = FALSE] # equivalent to d["pop"]
select(d, pop)

# pop
# 1    1
# 2    2
# 3    3
# 4    4
# 5    5
# 6    6
# 7    7
# 8    8
# 9    9
# 10  10


# (b) -- return a vector when selecting a single column
d[, "pop"]
pull(d, pop)

# [1]  1  2  3  4  5  6  7  8  9 10

 

 

아래의 예는 pull() 함수를 명시적으로 사용해서 인구("pop") 한개 열의 1행~5행의 관측치를 가져와서 벡터(vetor objects)로 반환한 것입니다. 

## -- vector objects

world$pop[1:5]
# [1]    885806  52234869        NA  35535348 318622525

pull(world, pop)[1:5]
# [1]    885806  52234869        NA  35535348 318622525

 

다음번 포스팅에서는 지리기하 벡터 데이터에서 속성 정보에 대해 그룹별로 집계(aggregating geographic vector attributes by group)하는 방법을 소개하겠습니다. (rfriend.tistory.com/624)

 

 

[Reference]

* Geo-computation with R - 'Attribute data operations'
  : geocompr.robinlovelace.net/attr.html

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

 

728x90
반응형
Posted by Rfriend
,

지난번 포스팅에서는 R의 sf 패키지를 사용하여 "sf 클래스 (The sf class)"를 만드는 방법을 소개하였습니다.


이번 포스팅에서는 지리공간 벡터 데이터(GeoSpatial Vector data)를 분석할 때 사용하는 "sf 패키지"와 "sp 패키지"의 관계, "sf 클래스"와 "sp 클래스" 간 변환에 대해서 소개하겠습니다.


(1) R의 sf 패키지와 sp 패키지의 관계/ 역사

(2) sf 클래스를 sp 클래스로 전환하기: as(sf_class, Class="Spatial")

(3) sp 클래스를 sf 클래스로 전환하기: st_as_sf(sp_class)



[ R 지리공간 데이터 분석 패키지: sf package와 sp package 클래스 간 전환 ]



  (1) R의 sf 패키지와 sp 패키지의 관계/ 역사


sf 패키지는 {sp 패키지 + R 인터페이스 with (GDAL, GEOS, PROJ) + s2 패키지} 의 패키지 기능들을 승계한 종합 패키지로서, 지리공간 벡터 데이터를 단순 지리특성 (Simple features) 으로 인코딩할 수 있게 해줍니다. [1]



>> sp 패키지 : Classes and Methods for Spatial Data [2], [3]


(sf 패키지의 부모격이 되는) sp 패키지는 2005년 Pebesma 와 Bivand 가 개발해서 처음으로 공개하였습니다. 2005년 전에는 지리적인 좌표가 일반적으로 여느 숫자와 다름없이 처리되었다면, sp 패키지가 나오고 부터는 지리공간 점(Point), 선(LineString), 면/다각형(Polygon), 격자(Grid) 와 속성(Attributes)을 지원하는 클래스(Classes)와 메소드(Methods) 로 처리되는 방식으로 바뀌게 됩니다.


sp 패키지는 테두리 상자(bounding box), 좌표 참조 시스템(CRS, Coordinate Reference System), 속성(Attributes) 등의 정보를 S4 클래스 시스템을 사용해서 "Spatial" 객체안의 슬롯에 저장을 합니다. 이를 통해 지리공간 데이터에 대한 연산 작업을 할 수 있게 해줍니다. 또한, sp 패키지는 지리공간 데이터에 대해 summary()나 plot() 함수와 같은 R 에 내장된 함수도 사용할 수 있게 해줍니다.



>> sf 패키지 : Simple Features for R


sf 패키지는 Edzer Pebesma, Roger Bivand 등이 2016년 10월에 최초로 오픈소스로 공개하였으며, R로 단순 지리특성 기하 (Simple Feature Geometry) 형태로 지리 벡터 데이터를 인코딩하는 표준화된 방법을 지원합니다. sf 패키지는 sp 패키지의 기능을 승계하였으며, 이에 더해 지리공간 데이터를 읽고 쓰는 'GDAL', 지리적 연산을 할 때 사용하는 'GEOS', 지도의 투영 변환(projection conversions)과 데이터 변환(datum transformations)을 위한 'PROJ' 와 R과의 인터페이스를 제공합니다. 그리고 선택적으로 지리적 좌표에 대한 구면 기하 연산 (spherical geometry operations) 을 위해 's2' 패키지를 사용합니다.


단순 지리특성 모델 (Simple Features Model)을 지원하는 "sf 패키지"를 사용하면 좋은 점들로는[4],

  • 지리공간 벡터 데이터를 빠르게 읽고 쓸 수 있음
  • 지리공간 벡터 데이터 시각화 성능의 고도화
    (tmap, leaflet, mapview 지리공간 데이터 시각화 패키지가 sf 클래스 지원)
  • 대부분의 연산에서 sf 객체는 DataFrame 처럼 처리가 가능함
  • sf 함수들은 '%>%' 연산자 (chain operator) 와 함께 사용할 수 있고, R의 tidyverse 패키지들과도 잘 작동함
    (sp 패키지도 spdplyr 패키지를 설치하면 dplyr의  %>% 체인 연산자와 기능을 사용할 수 있음)
  • sf 함수이름은 'st_' 로 시작하여 상대적으로 일관성이 있고 직관적임

등을 들 수 있습니다.


sf 패키지의 장점이 이렇게 많으므로 지리공간 벡터 데이터를 처리하고 분석하고 시각화하는데 있어 sf 패키지를 사용하지 않을 이유가 없습니다!




  (2) sf 클래스를 sp 클래스로 전환하기: as(sf_class, Class="Spatial")


예제로 spData 패키지에 들어있는 'world' 라는 이름의 "sf", "data.frame" 클래스의 데이터셋을 사용하겠습니다.



library(sp) # Classes and methods for spatial data
library(sf) # Support for simple features, a standardized way to encode spatial vector data.
library(spData) # load geographic data

names(world)
# [1] "iso_a2"    "name_long" "continent" "region_un" "subregion" "type"      "area_km2"  "pop"      
# [9] "lifeExp"   "gdpPercap" "geom"

class(world)
# [1] "sf"         "tbl_df"     "tbl"        "data.frame"




"sf" 클래스를 "sp" 클래스로 변환(converting the sf class into the sp class) 할 때는 as(sf_class, Class = "Spatial") 함수와 매개변수를 사용합니다.(sp 패키지는 S4의 Spatial 클래스를 사용)



## Converting sf class into sp's Spatial objects using as(sf_class, Class="Spatial))
world_sp_class = as(world, Class = "Spatial")

class(world_sp_class)
# [1] "SpatialPolygonsDataFrame"
# attr(,"package")
# [1] "sp"

 




  (3) sp 클래스를 sf 클래스로 전환하기: st_as_sf(sp_class)


반대로, "sp" 클래스를 "sf" 클래스로 변환(converting the sp class into sf class) 할 때는 sf 패키지의 st_as_sf() 함수를 사용합니다.



## Converting Spatial objects into sf class using st_as_sf()
world_sf_class = st_as_sf(world_sp_class)


class(world_sf_class)
# [1] "sf"         "data.frame"




[ Reference ]

[1] sf package: https://cran.r-project.org/web/packages/sf/index.html

[2] sp package: https://cran.r-project.org/web/packages/sp/index.html

[3] The history of R-spatial: https://geocompr.robinlovelace.net/intro.html

[4] Why simple features?: https://geocompr.robinlovelace.net/spatial-class.html



이번 포스팅이 많은 도움이 되었기를 바랍니다.

행복한 데이터 과학자 되세요!  :-)




728x90
반응형
Posted by Rfriend
,

지난번 포스팅에서는 R의 sf 패키지를 사용해서


- 벡터 데이터의 기하 유형 (Geometry types of vector data)을 단순 지리특성 기하로 정의하기

- 벡터 데이터의 여러개 단순 지리특성 기하(sfg)를 하나의 단순 지리특성 칼럼(sfc) 객체로 합치기

- st_sfc() 함수로 좌표 참조 시스템(CRS, Coordinate Reference Systems) 을 설정하고 확인하기


에 대해서 소개하였습니다.


이번 포스팅에서는 앞서의 포스팅들에서 소개했던 내용을 모두 포괄하는 sf패키지의 "sf 클래스 (The sf class)" 를 만드는 방법을 소개하겠습니다.


(1) sf 패키지의 "sf 클래스(the sf class)"는 무엇인가?

(2) sf 클래스 만들기: st_sf()

(3) sf 클래스의 클래스, 기하유형, CRS 확인하기: class(), st_geometry_type(), st_crs)






  (1) sf 패키지의 "sf 클래스(the sf class)"는 무엇인가?


R의 sf 패키지의 "sf 클래스(the sf class)"는 위의 그림에서 설명하는 바와 같이,


>> 지리공간 벡터 데이터 (GeoSpatial Vector Data)의 단순 지리특성 기하 (sfg, Simple feature geometry) 객체들을 리스트로 하나의 객체로 합친 단순 지리특성 칼럼 (sfc, Simple feature columns) 과,

>> 지리공간 벡터의 단순 지리특성 기하별로 속성 값 (예: 이름, 용도, 면적, 가격, 인구수, 온도, 습도 등)들을 모아놓은 data.frame 데이터 구조를


하나의 "sf 클래스" ( = sfc + data.frame) 로 합쳐 놓은 것입니다.


실제 지리공간 벡터 데이터를 분석한다고 했을 때는 sfc 객체의 기하 (Geometry) 정보와 data.frame 의 속성 (Non-geometric Attributes) 정보가 모두 있어야지, 기하 유형(점, 선, 면/다각형 등) 별로 속성 값을 분석할 수 있겠지요.


R의 sf 패키지로 지리공간 벡터 데이터 분석을 한다고 했을 때 새로운 용어가 자꾸 나오다 보니 위계 체계 (hierarchy), 자료 유형과 구조가 혼란스러울 수 있는데요, 위의 그림의 위계 체계, Input/Output 관계를 참고하시기 바랍니다.




  (2) sf 클래스 만들기: st_sf()



(2-1) 기하 객체 (Geometry object)


아래의 예에서는 먼저, library(sf) 로 sf 패키지를 로딩하고, 지리공간 벡터 데이터(Vector data)의 점 기하 유형 (Point geometry types) 들로 이루어진 단순 지리특성 기하 (sfg, Simple feature geometry) 객체를 만들어 보겠습니다.


다음으로 st_sfc() 함수를 사용하여 앞서 만든 3개의 점(points) 단순 지리특성 기하(sfg) 객체를 하나의 단순 지리특성 칼럼 (sfc, Simple feature columns) 객체로 합치고, 이때 좌표 참조 시스템(CRS, Coordinate Reference Systems) 은 EPSG 코드 정의를 사용해서 WGS84 (World Geodetic System 1984) 인 crs = 4326 을 설정해주겠습니다.



library(sf)

## (1) sfg(Simple feature geometry) object
## points: the coordinate of (longitude, latitude)
seoul_point_sfg_1 = st_point(c(127.059, 37.511))
seoul_point_sfg_2 = st_point(c(127.063, 37.512))
seoul_point_sfg_3 = st_point(c(127.073, 37.516))


## (2) sfc(Simple feature columns) object
seoul_points_sfc = st_sfc(seoul_point_sfg_1, seoul_point_sfg_2, seoul_point_sfg_3,
                          crs = 4326) # EPSG code, WGS84

seoul_points_sfc
# Geometry set for 3 features
# geometry type:  POINT
# dimension:      XY
# bbox:           xmin: 127.059 ymin: 37.511 xmax: 127.073 ymax: 37.516
# geographic CRS: WGS 84
# POINT (127.059 37.511)
# POINT (127.063 37.512)
# POINT (127.073 37.516)

 




(2-2) 비기하 data.frame 속성 (data.frame Non-geometry Attributes)


이번에는 서울의 COEX, GBC(현대자동차 Global Business Center), JansilStadium(잠실 종합 운동장) 의 3개 POI (Point of Interest)별 면적(area)과 가격(price) 속성(Attributes) 정보를 가지는 data.frame을 만들어보겠습니다. (아래 속성 데이터 값은 모두 그냥 가짜로 입력한 예시 값입니다.)



## (3) data.frame object with non-geometric attributes
seoul_df_attrib = data.frame(
  poi = c("COEX", "GBC", "JamsilStadium"), # Point of Interest
  area = c(20, 25, 15),
  price = c(80, 100, 50)
)

seoul_df_attrib
#             poi area price
# 1          COEX   20    80
# 2           GBC   25   100
# 3 JamsilStadium   15    50





(2-3) sf 클래스 = sfc 기하 객체(sfc Geometry) + data.frame 속성 (Non-geometry Attributes)


마지막으로, st_sf() 함수를 사용하여 위의 (2-1)에서 정의한 벡터 데이터의 기하 정보와, (2-2)에서 정의한 비기하 속성값 data.frame (Non-geometry Attributes) 을 합쳐서 sf 클래스 (the sf class) 를 만들어보겠습니다.



## (4) sf object using st_sf() function
## : sfc object (geometry) + data.frame object (non-geometric attributes)
seoul_sf = st_sf(seoul_df_attrib, # data.frame object (non-geometric attributes)
                 geometry = seoul_points_sfc) # sfc object (geometry)

seoul_sf
# Simple feature collection with 3 features and 3 fields
# geometry type:  POINT
# dimension:      XY
# bbox:           xmin: 127.059 ymin: 37.511 xmax: 127.073 ymax: 37.516
# geographic CRS: WGS 84
# poi area price               geometry
# 1          COEX   20    80 POINT (127.059 37.511)
# 2           GBC   25   100 POINT (127.063 37.512)
# 3 JamsilStadium   15    50 POINT (127.073 37.516)





  (3) sf 클래스의 클래스, 기하 유형, CRS 확인하기: class(), st_geometry_type(), st_crs)


sf 클래스의 클래스를 class() 함수를 사용해서 확인해보면, 기하(Geometry) 정보를 가지고 있는 "sf" 클래스 객체와 속성 정보 값을 가지고 있는 "data.frame" 클래스의 두개 클래스 객체로 구성되어 있음을 알 수 있습니다.


## check the class
class(seoul_sf)
# [1] "sf"         "data.frame"




st_geometry_type() 함수를 사용해서 기하 유형을 확인해보면, 이 예제에서는 점(Point) 3개로 구성되어 있음을 알 수 있습니다.



## check the geometry types
st_geometry_type(seoul_sf)
# [1] POINT POINT POINT
# 18 Levels: GEOMETRY POINT LINESTRING POLYGON MULTIPOINT MULTILINESTRING MULTIPOLYGON ... TRIANGLE




좌표 참조 시스템(CRS, Coordinate Reference Systems)은 st_crs() 함수로 확인할 수 있는데요, 위의 (1)번에서 단순 지리특성 칼럼(sfc, Simple feature columns)을 생성할 때 crs = 4326  으로 설정을 해주었기 때문에 User input: EPSG:4326 으로 등록되어 있음을 확인할 수 있습니다.



## check the CRS
st_crs(seoul_sf)
# Coordinate Reference System:
#   User input: EPSG:4326
# wkt:
#   GEOGCRS["WGS 84",
#           DATUM["World Geodetic System 1984",
#                 ELLIPSOID["WGS 84",6378137,298.257223563,
#                           LENGTHUNIT["metre",1]]],
#           PRIMEM["Greenwich",0,
#                  ANGLEUNIT["degree",0.0174532925199433]],
#           CS[ellipsoidal,2],
#           AXIS["geodetic latitude (Lat)",north,
#                ORDER[1],
#                ANGLEUNIT["degree",0.0174532925199433]],
#           AXIS["geodetic longitude (Lon)",east,
#                ORDER[2],
#                ANGLEUNIT["degree",0.0174532925199433]],
#           USAGE[
#             SCOPE["unknown"],
#             AREA["World"],
#             BBOX[-90,-180,90,180]],
#           ID["EPSG",4326]]




이렇게 만든 sf 클래스를 대상으로 leaflet 패키지를 사용하여 웹 기반으로 상호작용하는 동적 지도를 만드는 방법은 https://rfriend.tistory.com/593 를 참조하세요.

이번 포스팅이 많은 도움이 되었기를 바랍니다.

행복한 데이터 과학자 되세요!  :-)


728x90
반응형
Posted by Rfriend
,

지난번 포스팅에서는 R의 sf패키지의 st_sfc() 함수를 사용해서 여러개의 기본 지리특성 기하(sfg, Simple feature geometry)들을 하나의 단순 지리특성 칼럼(sfc, Simple feature columns) 객체로 합치는 방법을 소개하였습니다.

 

지리공간 데이터 분석을 할 때 제일 먼저 해야 하고 또 확인해야 하는 것이 좌표계, 좌표 참조 시스템(Coordinate Reference Systems, CRS)을 설정하고 확인하는 것입니다.

 

좌표 참조 시스템(CRS) (또는 좌표계, 공간 참조 시스템, Spatial Reference System, SRS)좌표 기반으로 국소, 지역, 또는 전지구적으로 지리상의 객체를 위치시킬 때 사용되는 참조 시스템입니다. 좌표 참조 시스템은 특정 지도 투영법 (map projection)을 정의하고, 서로 다른 좌표 참조 시스템 간의 변환을 할 수 있도록 해줍니다.

 

위도, 경도 좌표의 기준이 어떻게 되는지, 누가 언제 정의한 좌표 체계인지를 정의해 놓은 것입니다.

 

오픈소스 PostGIS 에서는 Spatial Reference System Table에 SRID 별로 'auth_name', 'auth_srid', 'srtext', 'proj4text' 등의 정보가 저장되어 있는데요, R에서도 좌표계, 좌표 참조 시스템(CRS)이 있어서 좌표계 간에 변환을 할 수 있게 해줍니다.

 

 

 

참고로, 전세계를 한번에 나타내야 할 때 많이 사용하는 전지구 좌표계로는 WGS84(EPSG:4326), Bessel 1841(EPSG:4004, EPSG:4162), GRS80(EPSG)4019, EPGS:4737), Google Mercator(EPSG:3857) 등이 있습니다.

 

 

[전지구 좌표계]
*WGS84 경위도: GPS가 사용하는 좌표계EPSG:4326, EPSG:4166 (Korean 1995)+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs 
*Bessel 1841 경위도: 한국과 일본에 잘 맞는 지역타원체를 사용한 좌표계EPSG:4004, EPSG:4162 (Korean 1985)+proj=longlat +ellps=bessel +no_defs +towgs84=-115.80,474.99,674.11,1.16,-2.31,-1.63,6.43
*GRS80 경위도: WGS84와 거의 유사EPSG:4019, EPSG:4737 (Korean 2000)+proj=longlat +ellps=GRS80 +no_defs
*Google Mercator: 구글지도/빙지도/야후지도/OSM 등 에서 사용중인 좌표계EPSG:3857(공식), 

EPSG:900913(통칭)

+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs

출처: https://www.osgeo.kr/17 [OSGeo(Open Source GeoSpatial) 한국어 지부 - OSGeo Korean Chapter]

 

한국 주요 좌표계 EPSG 코드 및 proj4 인자 정리는 https://www.osgeo.kr/17 를 참고하세요.

 

 

이번 포스팅에서는 R의 sf패키지를 사용해서 단순 지리특성 칼럼(sfc, Simple feature columns)에서

 

(1) 특정 좌표 참조 시스템(CRS, Coordinate Reference Systems) 지정해주기

(2) 좌표 참조 시스템(CRS, Coordinate Reference Systems) 확인: st_crs()

(3) raw proj4string 을 사용해서 좌표 참조 시스템 지정해주기

 

를 소개하겠습니다.

 

 

  (1) 특정 좌표 참조 시스템(CRS, Coordinate Reference Systems) 지정해주기

 

기본 지리특성 칼럼(sfc, Simple feature columns)의 좌표 참조 시스템의 기본 값은 NA (Not Available) 입니다.

 

 

library(sf)

## Coordinate Reference Systems (CRS)
## default CRS is NA (Not Available)
point_sfg_1 = st_point(c(1, 2))
point_sfg_2 = st_point(c(3, 4))
points_sfc = st_sfc(point_sfg_1, point_sfg_2)

st_crs(points_sfc)
# Coordinate Reference System: NA

 

 

 

st_sfc() 함수의 crs 매개변수를 사용해서 특정 좌표 참조 시스템(CRS)을 설정해줄 수 있습니다.

가령, 아래 예에서는 EPSG 코드 4326 번으로 좌표 참조 시스템을 설정하여 보았습니다.

 

* EPSG 코드의 EPSG는 European Petroleum Survey Group 의 앞글자를 딴 줄임말입니다. EPSG 그룹은 좌표 시스템 정보 데이터베이스와 지도 투영법과 데이터에 대한 표준 문서 자료를 발행하는 곳입니다.

 

* WGS84 는 World Geodetic System 1984 의 앞글자를 딴 줄임말입니다. WGS84 는 전지구 좌표계로서, 우리가 매일 사용하는 GPS(Global Positioning System), 지도 제작, 측지학 등에서 사용합니다.

 

 

 

## EPSG: European Petroleum Survey Group
## : They publish a database of coordinate system information
##   plus some very good related documents on map projections and datums

## Specify CRS using 'crs' argument
point_sfc_wgs = st_sfc(point_sfg_1, point_sfg_2, crs = 4326) # EPSG code

 

point_sfc_wgs
# Geometry set for 2 features
# geometry type:  POINT
# dimension:      XY
# bbox:           xmin: 1 ymin: 2 xmax: 3 ymax: 4
# geographic CRS: WGS 84
# POINT (1 2)
# POINT (3 4)

 

 

 

 

  (2) 좌표 참조 시스템(CRS, Coordinate Reference Systems) 확인: st_crs()

 

좌표 참조 시스템 확인은 st_crs() 함수를 사용합니다.

 

 

st_crs(point_sfc_wgs)
# Coordinate Reference System:
#   User input: EPSG:4326
# wkt:
#   GEOGCRS["WGS 84",
#           DATUM["World Geodetic System 1984",
#                 ELLIPSOID["WGS 84",6378137,298.257223563,
#                           LENGTHUNIT["metre",1]]],
#           PRIMEM["Greenwich",0,
#                  ANGLEUNIT["degree",0.0174532925199433]],
#           CS[ellipsoidal,2],
#           AXIS["geodetic latitude (Lat)",north,
#                ORDER[1],
#                ANGLEUNIT["degree",0.0174532925199433]],
#           AXIS["geodetic longitude (Lon)",east,
#                ORDER[2],
#                ANGLEUNIT["degree",0.0174532925199433]],
#           USAGE[
#             SCOPE["unknown"],
#             AREA["World"],
#             BBOX[-90,-180,90,180]],
#           ID["EPSG",4326]]

 

 

 

 

  (3) raw proj4string 을 사용해서 좌표 참조 시스템 지정해주기

 

raw proj4string 을 직접 입력해서 좌표 참조 시스템을 지정해주려면 st_sfc() 함수의 crs 매개변수에 직접 따옴표 안에 proj, datum 을 입력해주면 됩니다. 아래 예는 WGS84를 raw proj4string로 해서 좌표 참조 시스템을 등록한 것입니다.

 

 

## to specify CRS using a raw proj4string
point_sfc_wgs_2 = st_sfc(point_sfg_1, point_sfg_2,
                         crs = "+proj=longlat +datum=WGS84 +no_defs")

st_crs(point_sfc_wgs_2)
# Coordinate Reference System:
#   User input: +proj=longlat +datum=WGS84 +no_defs
# wkt:
#   GEOGCRS["unknown",
#           DATUM["World Geodetic System 1984",
#                 ELLIPSOID["WGS 84",6378137,298.257223563,
#                           LENGTHUNIT["metre",1]],
#                 ID["EPSG",6326]],
#           PRIMEM["Greenwich",0,
#                  ANGLEUNIT["degree",0.0174532925199433],
#                  ID["EPSG",8901]],
#           CS[ellipsoidal,2],
#           AXIS["longitude",east,
#                ORDER[1],
#                ANGLEUNIT["degree",0.0174532925199433,
#                          ID["EPSG",9122]]],
#           AXIS["latitude",north,
#                ORDER[2],
#                ANGLEUNIT["degree",0.0174532925199433,
#                          ID["EPSG",9122]]]]

 

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다.

행복한 데이터 과학자 되세요!  :-)

 

 

728x90
반응형
Posted by Rfriend
,

지리공간 데이터 (GeoSpatial data)를 처리하고 분석하는데 있어서 첫번째 관문이자 큰 도전사항 중에 하나가 지리공간 데이터 포맷이 매우 다양하다는 것입니다. 


아래에 다양한 지리공간 데이터(various GeoSpatial data foramts)의 리스트를 소개하고, 특히 이중에서 점, 선, 다각형으로 구성된 벡터 데이터 포맷의 이미지 시각화를 예시로 보였습니다. 지리공간 데이터 포맷이 상당히 많지요?


이들 지리공간 데이터 포맷별로 데이터를 DB나 R로 불러오기 (importing)할 때 사용하는 DB utility tools 이나 R의 package가 달라지다 보니 번거롭고 또 어려운 점이 있습니다.



[ 다양한 지리공간 데이터 포맷 (various GeoSpatial data formats) ]




R을 활용한 지리공간 데이터의 처리 및 분석, 시각화를 본격적으로 들어가기 전에 먼저, 이들 지리공간 데이터 포맷들 중에서 특히 벡터 데이터(Vector data)와 레스트 데이터 (Raster data) 모델에 대해서 이들이 무엇이고, 어떻게 활용이 되며, 무슨 R 패키지를 사용해서 분석할 수 있는지에 대해서 알아보겠습니다.


[ 지리공간 벡터 데이터(Vector data) vs. 레스터 데이터 (Raster data) ]






  (1) 지리공간 벡터 데이터 (Vector data)


벡터 데이터에는 KML(.kml or .kmz), GML, GeoJSON, Shapefile (.shp), WKT 등의 데이터 포맷이 있습니다.


KML (Keyhole Markup Language), GML (Geography Markup Language) 데이터 포맷은 XML 기반으로 지리공간 데이터를 저장합니다. KML은 OGC(Open Geospatil Consortium)의 공식 표준입니다. KML과 GML 데이터 포맷은 non-GIS 사용자들과 인터넷을 통해 쉽게 지리공간 데이터를 공유하는데 많이 사용됩니다.


GeoJSON 데이터 포맷은 이름에서 짐작할 수 있듯이 JSON 기반으로 간단한 지리공간 데이터와 그 외 일반 데이터를 저장합니다. GeoJSON 데이터는 인터넷으로 지리공간 & 일반 데이터를 공유하는데 역시 많이 사용됩니다.


Shapefile 데이터 포맷은 GIS (Geographic Information System) 소프트웨어를 위한 지리공간 벡터 데이터입니다. Shapefile 은 GIS 의 국제적인 제공사인 Esri(Environmental Systems Research Institute)에서 개발하고 관리하며, GIS 소프트웨어 간 상호운용성(interoperability)를 보장합니다.


WKT 데이터 포맷은 Well-Known Text 의 약자로서, 벡터 지리공간 데이터를 표현하는데 텍스트 마크업 언어(Text Markup Language)를 사용합니다. WKB (Well-Known Bianry)는 WKT와 같은 정보를 저장하는데 있어 이진(binary) 포맷을 사용해 보다 간소하고 컴퓨터가 처리하기에 편리하도록 하며, 대신 사람이 읽을 수는 없습니다.



벡터 데이터는 실제 세상을 그래픽으로 재표현(graphical representation of the real world)한 것으로서, 점, 선, 다각형(points, lines, polygons) 유형의 그래픽을 이용합니다. 벡터 데이터는 지구 표면의 객체나 특징을 일반화하여 표현하는데 사용됩니다.


벡터 데이터는 별개로 분리되고, 경계가 잘 정의되어 있어서 보통 높은 수준의 정밀도 (high level of precision) 을 가지고 있습니다. 이런 이유로 벡터 데이터는 사회 과학 (social sciences) 분야에서 많이 사용됩니다.


R 의 sf 패키지 (spatial data frame) 를 사용하여 벡터 데이터를 불러오고, 처리 및 분석, 시각화를 할 수 있습니다. (다음 포스팅에서 소개) sf 패키지는 이전의 sp 패키지, rgeos, rgdal 패키지를 모두 아우르고 있고, GEOS, GDAL, PROJ 와 R 의 interface를 제공해주어서, R로 지리공간 벡터 데이터를 다루는데 있어 매우 편리하고 강력합니다.




[ 강과 도심 지역을 나타낸 벡터 데이터(vector data)와 레스터 데이터(raster data) 비교 ]


* source: https://blog.rmotr.com/spatial-data-with-python-lets-begin-e29b5c41ead3



  (2) 지리공간 레스터 데이터 (Raster data)


레스터 데이터(Raster data)에는 ESRI Grid, GeoTIFF, JPEG 2000, NITF 등이 데이터 포맷이 있습니다.


레스터 데이터는 픽셀의 격자(grid of pixels) 로 지구의 표면을 표현합니다. 각 픽셀 안에는 색, 측정 단위 등과 같이 질문의 요소에 대한 정보를 전달하는 값이 있습니다.


레스터 데이터는 인공위성이나 항공장비에서 지구 표면을 향해 위에서 아래로 수직으로 찍은 사진으로 생각하면 이해하기가 쉽습니다.(예: NASA에서 제공하는, 인공위성에서 찍은 지구의 야간 사진 등) 이 지구표면을 수직으로 찍은 사진을 픽셀의 격자로 나누어서 각 픽셀(pixel, cell)에 지리특성정보 값을 가지고 있는 것입니다. 


레스터 데이터의 품질은 사진을 찍었던 장비의 해상도의 한계나, 활용하고자 하는 분야의 목적에 따라서 다양합니다. 레스터 데이터는 많은 환경관련 과학 분야 (environmental sciences)에 많이 사용되고 있습니다.


R의 raster 패키지를 사용하면 R에서 레스터 데이터를 처리할 수 있습니다.


위에서 각각 소개한 벡터 데이터와 레스터 데이터는 상호 간에 변환(converting from vector to raster data, from raster to vector data)이 가능하며, 하나의 분석 목적에 두 유형의 데이터 포맷이 동시에 사용되기도 합니다.


다음번 포스팅에서는 R의 spData 패키지에 내장되어 있는 지리공간 벡터 데이터 모델(Vector data model)을 가지고 sf 패키지로 시각화하는 간단한 예를 소개하겠습니다.


이번 포스팅이 많은 도움이 되었기를 바랍니다.

행복한 데이터 과학자 되세요!  :-)


728x90
반응형
Posted by Rfriend
,