'분류 전체보기'에 해당되는 글 803건

  1. 2021.01.08 KOSPI 3,100 돌파에 강제 소환되는 '중앙일보 이정재의 시시각각 - 한 달 후 대한민국' 3
  2. 2021.01.04 [R 지리공간 데이터 분석] sf 패키지와 sp 패키지 간 클래스 변환 (conversion b/w R sf and sp classes)
  3. 2021.01.03 [R 지리공간 데이터 분석] sf 클래스 = sfg 객체 (Geometry) + data.frame 속성 (Non-geometric attributes)
  4. 2021.01.03 [R 지리공간 데이터 분석] 좌표계, 좌표 참조 시스템 (CRS, Coordinate Reference Systems)
  5. 2021.01.02 [R 지리공간 데이터 분석] 벡터 데이터의 단순 지리특성 기하(sfg, Simple feature geometry)를 단순 지리특성 칼럼(sfc, Simple feature columns)으로 합치기: st_sfc()
  6. 2021.01.02 [R 지리공간 데이터 분석] 벡터 데이터의 기하 유형: 점, 선, 면, 다중점, 다중선, 다중면, 기하집합 (Geometry types of Vector data)
  7. 2020.12.31 [R 지리공간 데이터 분석] leaflet 패키지를 이용한 동적 지도 (Interactive Map) 만들기 2
  8. 2020.12.30 [R 지리공간 데이터 분석] sf 패키지를 활용한 벡터 데이터 세계지도 시각화 (vector data map visualization with sf package)
  9. 2020.12.27 검찰, 사법부, 언론, 보수야당, 그들만의 카르텔 (부제: 누가 조국 전 법무부 장관에게 돌을 던진단 말인가?) 2
  10. 2020.12.26 [Python pandas] 그룹별로 전 분기 대비, 전년 동분기 대비 변동률 구하기 (Percentage change between the current and a prior element by Group) 2

오늘 코스피(KOSPI)가 3,100을 돌파했네요!

 

저는 주린이라서 주식 잘 모릅니다만, 그동안 KOSPI 2,000 대 박스권에 있던게 몇 년 되는데, 코로나 사태로 난리도 아닌 상황에서 드디어 사상 최초로 KOSPI 3,100 대를 돌파했다니 정말 놀랍고 또 대한민국이 대단하다 싶습니다.  

 

 

* 출처: 머니투데이, 2021.01.08

 

코스피가 3,100을 돌파한 오늘, 유난히 생각나는 예전 신문 기사가 있어서 포스팅해봅니다. 두둥~

 

바로 2017년 4월 13일, 제 19대 대통령 선거를 한 달여 앞둔 시점에 중앙일보 '이정재의 시시각각' 칼럼 코너에서 이정재씨가 쓴 "한 달 후 대한민국" 칼럼입니다.

 

기자가 팩트에 기반한 기사를 쓰는게 아니라, 마치 무당이 사람을 저주하기 위해 인형을 가져다가 바늘로 쑤셔가면서 저주의 주술을 거는 굿을 하는 듯이 악의적으로 글을 쓴, 명백한 선거개입 행위에 해당하는 칼럼을 썼었지요.

 

문재인 후보가 대통령으로 선출이 된다고 상상을 해서 쓴 칼럼에서 말하길, "주가(KOSPI)는 1000 밑으로 주저앉았고 원화 값은 달러당 2000원을 훌쩍 넘겼다. 사람들은 생수를 사 재고, 라면을 박스째 챙기느라 마트로 몰려들었다." 라고 썼습니다.

 

 

 

 

 

2021.01.08일자 오늘 환율을 확인해보니 미국USD 달러당 환율이 1,092.00 KRW 원 이네요. 문재인 대통령 시대가 열리면 달러 당 2,000원의 환율이 될거라는 예상(? 저주?)과는 많이 다릅니다.

 

* 출처: m.stock.naver.com/marketindex/index.nhn

 

 

2020년도 경제성장률이 OECD 회원국 중에서 한국이 1위라고 하네요. 나라 망하라고 굿을 한 이정재 대기자님의 바램하고는 거리가 멉니다.

 

 

 

기자가 대선을 코 앞에 두고 특정 후보를 떨어뜨리기 위해, 또 특정 후보를 밀어주기 위해 '대한민국 망해라'라는 저주섞인 소설을 쓰는 것도 문제고, 이런걸 칼럼이랍시고 실어주는 '중앙일보'도 문제고, 이런 칼럼 이후에도 아직도 중앙일보에서 계속 '이정재의 시시각각' 코너를 연재하고 있다는 것도 코메디라고 생각합니다.

 

아직도 여전히 문재인 대통령 욕하는 주제로 '이정재의 시시각각' 칼럼을 연재하고 있네요. 부끄럼움도, 염치도 없습니다.

 

 

KOSPI 3,100 돌파 소식을 중앙일보의 이정재 대기자에게 바칩니다!

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
,

지난번 포스팅에서는 R의 sf 패키지를 사용해서 지리공간 벡터 데이터의 기하 유형(geometry types of vector data)로서 단순 지리특성 기하(Simple feature geometry)인 점(Point), 선(LineString), 면(다각형) (Polygon), 다중점(MultiPoint), 다중선(MultiLineString), 다중면(MultiPolygon), 기하집합(GeometryCollection)에 대해서 소개하였습니다 .


이번 포스팅에서는 앞서 소개했던 벡터 데이터의 '단순 지리특성 기하 (Simple feature geometry, sfg)' 들을 sf 패키지의 st_sfc() 함수를 사용하여 '단순 지리특성 칼럼 (Simple feature column, sfc)' 으로 합치는 방법을 소개하겠습니다.


여기서 단순 지리특성 칼럼(Simple feature column, sfc)은 단순 지리특성 기하들의 리스트(a list of sfg) 로서, 두 개의 지리특성(features)를 하나의 칼럼 객체로 합쳐놓은 것입니다. (한국말로 feature, sfc, sfg 용어를 번역하기가 쉽지 않네요.)


-- 동일한 단순 지리특성 기하 유형 합치기

(1) 두개의 단순 지리특성 기하 점(2 sfg points)를 한개의 단순 지리특성 칼럼(1 sfc) 객체로 합치기

(2) 두개의 단순 지리특성 기하 면(2 sfg polygons)를 한개의 단순 지리특성 칼럼(1 sfc) 객체로 합치기


-- 서로 다른 단순 지리특성 기하 유형 합치기

(3) 단순 지리특성 기하 점과 면을 합쳐서 한개의 단순 지리특성 칼럼(1 sfc) 객체로 만들기





  (1) 두개의 단순 지리특성 기하 점(2 sfg points)를 st_sfc() 함수로
      한개의 단순 지리특성 칼럼(1 sfc) 객체로 합치기


R의 sf 패키지를 사용할 것이므로, 먼저 library(sf) 로 패키지를 불러옵니다.


다음으로, 예제로 사용할 점(Point) 두개를 st_point() 함수를 사용해서 만들었습니다.


그리고, st_sfc() 함수를 사용하여, 단순 지리특성 기하(Simple feature geometry, sfg)인 두개의 점을

--> 단순 지리특성 칼럼(Simple feature columns, sfc) 의 하나의 객체로 합쳤습니다.



library(sf)

## Simple feature geometry (sfg)
## Point
point_sfg_1 = st_point(c(1, 2))
point_sfg_1
# POINT (1 2)

point_sfg_2 = st_point(c(3, 4))
point_sfg_2
# POINT (3 4)


## Simple feature columns (sfc)
## st_sfc() function combine two simple features into one object with two features.
## sfc represents the geometry column in sf data frames.
points_sfc = st_sfc(point_sfg_1, point_sfg_2)

points_sfc
# Geometry set for 2 features
# geometry type:  POINT

# dimension:      XY
# bbox:           xmin: 1 ymin: 2 xmax: 3 ymax: 4
# CRS:            NA
# POINT (1 2)
# POINT (3 4)

 



st_geometry_type() 함수를 사용하면 기하 유형을 확인해 볼 수 있습니다. 동일한 기하 유형인 두 개 점을 합쳤으므로 하나의 객체 집합에 두 개의 점(Points)가 들어있습니다.



## check the geometry type of sfc

st_geometry_type(points_sfc)
# [1] POINT POINT
# 18 Levels: GEOMETRY POINT LINESTRING POLYGON MULTIPOINT MULTILINESTRING MULTIPOLYGON ... TRIANGLE

 




  (2) 두개의 단순 지리특성 기하 면(2 sfg polygons)를 st_sfc() 함수로

      한개의 단순 지리특성 칼럼(1 sfc) 객체로 합치기


이번에는 동일한 기하 형태인 두개의 단순 지리특성 기하 면 (2 Simple feature geometry polygons) 을 st_polygon() 함수로 만들어보겠습니다.


그리고 이를 st_sfc() 함수를 사용해서 하나의 단순 지리특성 칼럼(Simple feature column) 객체로 합쳐보겠습니다.



## Polygon using list of matrices of points
polygon_list_1 = list(rbind(c(1, 1), c(1, 3), c(3, 5), c(3, 1), c(1, 1)))
polygon_sfg_1 = st_polygon(polygon_list_1)
polygon_sfg_1
# POLYGON ((1 1, 1 3, 3 5, 3 1, 1 1))

polygon_list_2 = list(rbind(c(4, 1), c(4, 5), c(5, 5), c(5, 1), c(4, 1)))
polygon_sfg_2 = st_polygon(polygon_list_2)
polygon_sfg_2
# POLYGON ((4 1, 4 5, 5 5, 5 1, 4 1))

## sfc (Simple feature columns)
polygon_sfc = st_sfc(polygon_sfg_1, polygon_sfg_2)

polygon_sfc
# Geometry set for 2 features
# geometry type:  POLYGON
# dimension:      XY
# bbox:           xmin: 1 ymin: 1 xmax: 5 ymax: 5
# CRS:            NA
# POLYGON ((1 1, 1 3, 3 5, 3 1, 1 1))
# POLYGON ((4 1, 4 5, 5 5, 5 1, 4 1))




st_geometry_type()함수로 기하 유형을 확인해보면 2개 면의 집합인 하나의 객체임을 확인할 수 있습니다.



st_geometry_type(polygon_sfc)
# [1] POLYGON POLYGON
# 18 Levels: GEOMETRY POINT LINESTRING POLYGON MULTIPOINT MULTILINESTRING MULTIPOLYGON ... TRIANGLE

 




  (3) 단순 지리특성 기하 점과 면을 st_sfc() 함수로 합쳐서

      한개의 단순 지리특성 칼럼(1 sfc) 객체로 만들기


이번에는 (1)번에서 만들었던 점(Point)과 (2)번에서 만들었던 면(Polygon)을 st_sfc() 함수를 사용해서 하나의 단순 지리특성 칼럼 객체로 합쳐보겠습니다. 


이처럼 서로 다른 기하 형태도 st_sfc() 함수로 하나의 단순 지리특성 칼럼 객체로 합칠 수 있습니다.



## combining different geometry types
point_polygon_sfc = st_sfc(point_sfg_1, polygon_sfg_1)


point_polygon_sfc
# Geometry set for 2 features
# geometry type:  GEOMETRY
# dimension:      XY
# bbox:           xmin: 1 ymin: 1 xmax: 3 ymax: 5
# CRS:            NA
# POINT (1 2)
# POLYGON ((1 1, 1 3, 3 5, 3 1, 1 1))




st_geometry_type(point_polygon_sfc)
# [1] POINT   POLYGON
# 18 Levels: GEOMETRY POINT LINESTRING POLYGON MULTIPOINT MULTILINESTRING MULTIPOLYGON ... TRIANGLE

 



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

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



728x90
반응형
Posted by Rfriend
,
이번 포스팅에서는 지리공간 데이터 중에서 실제 세계를 도형으로 표현(graphical representation) 하는 벡터 데이터 모델 (Vector data model)에서 사용하는 기하 유형 (geometry types)에 대해서 소개하겠습니다.

(* 참고로 레스터 데이터는 실제 세계를 픽셀로 이루어진 그리드 안에 지리특성 값을 가지는 형태라고 하였습니다.)

벡터 데이터의 기하 유형에는 총 17개가 있는데요, 이번 포스팅에서는 그중에서도 많이 사용되는 아래의 7개의 대표적인 유형에 대해서만 설명을 하겠습니다.

(1) 점 (Point)
(2) 선 (LineString)
(3) 면 (다각형) (Polygon)
(4) 다중점 (MultiPoint)
(5) 다중선 (MultiLineString)
(6) 다중면 (MultiPolygon)
(7) 기하집합 (GeometryCollection)

총 17개의 기하 유형 중에서 위에서 설명한 7개 이외에 나머지 유형에 대해서는 PostGIS 사이트를 참고하시기 바랍니다. ( http://postgis.net/docs/using_postgis_dbmanagement.html )

[ 벡터 데이터의 기하 유형 (Geometry Types of Vector data) ]



  (1) 점 (Point), 다중점 (MultiPoint)


점은 2D (위도, 경도), 3D (위도, 경도, 해발고도), 또는 4D (위도, 경도, 고도, 측정 정확도) 공간 상의 하나의 위치 좌표에 해당합니다.

예: Point (3 3)

(Point)은 0 차원으로서, 각 기하도형의 가장 기본이 되는 형태입니다. 여러개의 점을 이어주면 선이 되고, 선을 닫아주면 면이 되는 식이니깐요. 이렇게 점 --> 선 --> 면 혹은 점 --> 다중점, 선 --> 다중선, 면 --> 다중면 방향으로 기하도형을 변환하는 것을 구성(composition) 한다고 하며, 그 반대 방향으로의 변환을 해체(Decompostion) 한다고 합니다.

점은 우물, 랜드마크, 관심지역(Point of Interest) 등의 지리특성을 정의할 때 사용합니다.

R에서 점(point)을 만들 때 st_point() 함수를 사용합니다. st_point(dim="XYM") 에서 dim 은 차원(dimension)을 의미하고, M은 보통 Measurement 의 M (측정 정확도, measurement accuracy)을 의미합니다. 점의 2D, 3D, 4D 좌표는 c() 로 묶어줍니다.(concatenate)

참고로, 접두사 'ST_' 는 PostGIS의 함수에서도 동일하게 사용되며, 'standard Spatial Type (ST)' 의 앞글자를 딴 것입니다.


install.packages("sf")

library(sf)


##----------------
## point

## XY point
st_point(c(3, 3))
# POINT (3 3)

## XYZ point
st_point(c(3, 3, 2))
# POINT Z (3 3 2)

## XYM point
st_point(c(3, 3, 1), dim = "XYM")
# POINT M (3 3 1)

## XYZM point
st_point(c(3, 3, 2, 1))
# POINT ZM (3 3 2 1)





  (2) 선 (LineString)


선(LineString) 은 점들을 직선으로 연결한, 여러개 점들의 연속적인 집합입니다. 선은 아래의 예처럼 몇 개 점들의 집합으로 표현할 수 있습니다(이들 점을 순서대로 직선으로 연결).

예: LineString (1 1, 1 3, 3 5)

선은 1차원(dimension of 1)이며 길이(length)가 있습니다. (반면, 점은 0 차원이고 길이가 없음)
선은 길, 철도, 강, 전선 등과 같이 선형 특성을 가진 지형지물을 정의하는데 사용합니다.

R에서 선(LineString)은 st_linestring() 함수를 사용하여 만들 수 있습니다. 선을 이루는 여러개 점들의 좌표는 rbind()로 행렬을 만들어서 사용합니다.


##----------------
## LineString using matrices
linestring_matrix = rbind(c(1, 1), c(1, 3), c(3, 5))


st_linestring(linestring_matrix)
# LINESTRING (1 1, 1 3, 3 5)





  (3) 면 (다각형) (Polygon)


(Polygon)은 2차원의 표면을 가지는 형태로 점들이 연결된 것으로서, 안에 구멍(hole)이 있을 수도 있고 또는 없을 수도 있습니다. (위의 그림 예에서는 면 안에 구멍이 없음).  면이 되기 위해서는 시작점과 끝점이 동일해야 하며, 이를 닫혀있어야 한다(closed, not open)고 말합니다. 아래 예의 경우 면의 시작점과 끝점이 (x=1, y=1) 로서 동일하며, 즉 닫혀있습니다.


예: Polygon ((1 1, 1 3, 3 5, 3 1, 1 1))


면(Polygon)은 육지, 저수지, 건물 등과 같이 공간적인 외곽 (spatial extent)과 면적(area)을 가진 지리지형을 나타내는데 사용할 수 있습니다.


R의 st_polygon() 함수를 사용해서 면(Polygon)을 만들 수 있습니다. 면을 만들 때는 점 행렬의 리스트(list of matrices of points)를 입력값으로 사용합니다.



## Polygon using list of matrices of points
polygon_list = list(rbind(c(1, 1), c(1, 3), c(3, 5), c(3, 1), c(1, 1)))


st_polygon(polygon_list)
# POLYGON ((1 1, 1 3, 3 5, 3 1, 1 1))





  (4) 다중점 (MultiPoint)


다중점(MultiPoint)은 점을 여러개 모아놓은 것(a collection of points)입니다.

예: MultiPoint (1 1, 3 3, 3 5)

R에서 점은 st_point() 함수로 만들었다면, 다중점(MultiPoint)은 st_multipoint() 로 만들 수 있습니다. 이때 st_point() 에서는 점의 좌표를 c()로 묶어주기만 했다면, 다중점(MultiPoint)을 만들 때는 rbind()로 묶어서 점의 행렬(matrices)을 만들어서 st_multipoint() 함수를 사용합니다.


## MultiPoint using matrices of points
multipoint_matrix = rbind(c(1, 1), c(3, 3), c(3, 5))


st_multipoint(multipoint_matrix)
# MULTIPOINT ((1 1), (3 3), (3 5))





  (5) 다중선 (MultiLineString)


다중선(MultiLineString)은 선(LineString)을 여러개 모아놓은 것(a collection of LineStrings)입니다.


예: MulLineString ((1 1, 1 3, 3 5), (2 2, 5 2))

R에서 선(LineString)은 st_linestring()으로 만들었다면, 다중선(MultiLineString)은 st_multilinestring() 함수로 만듭니다. 여러개의 선(LineSting)을 리스트(list)로 묶어서 st_multilinestring() 함수에 넣어주면 됩니다.


## MultiLineString
multilinestring_list = list(rbind(c(1, 1), c(1, 3), c(3, 5)),
                            rbind(c(2, 2), c(5, 2)))

st_multilinestring((multilinestring_list))
# MULTILINESTRING ((1 1, 1 3, 3 5), (2 2, 5 2))





  (6) 다중면 (MultiPolygon)


다중면(MultiPolygon)은 면(Polygon)을 여러개 모아놓은 것(a collection of Polygons)입니다.


예: MultiPolygon (((1 1, 1 3, 3 5, 3 1, 1 1), (4 1, 4 5, 5 5, 5 1, 4 1)))


R에서 면(Polygon)은 st_polygon() 함수로 만들었다면, 다중면(MultiPolygon)은 st_multipolygon() 함수로 만들 수 있습니다. 면(Polygon)을 만들 때 점 행렬의 리스트를 st_polygon() 함수에 넣어주었다면, 다중면(MultiPolygon)을 만들 때는 여러개의 면이 모인 것이므로 점 행렬 리스트들의 리스트 (list of lists)를 st_multipolygon() 함수에 넣어줍니다.


## MultiPolygon
multipolygon_list = list(
  list(rbind(c(1, 1), c(1, 3), c(3, 5), c(3, 1), c(1, 1))),
  list(rbind(c(4, 1), c(4, 5), c(5, 5), c(5, 1), c(4, 1)))
  )

st_multipolygon(multipolygon_list)
# MULTIPOLYGON (((1 1, 1 3, 3 5, 3 1, 1 1)), ((4 1, 4 5, 5 5, 5 1, 4 1)))





  (7) 기하집합 (GeometryCollection)


기하(도형)집합(GeometryCollection)은 위에서 설명한 점(Point), 선(LineString), 면(다각형)(Polygon), 다중점(MultiPoint), 다중선(MultiLineString), 다중면(MultiPolygon) 중에서 여러개의 기하 유형을 모아놓은 것이며, 어떤 조합(any combination of geometries)도 가능합니다.


아래 예에서는 점(Point), 다중선(MultiLineString), 면(Polygon)이 혼합된 조합의 기하집합(GeometryCollection) 입니다.




R의 st_geometrycollection() 함수를 사용해서 기하집합(GeometryCollection)을 만들 수 있습니다. 이때 각 기하 유형을 리스트(list)로 묶어서 넣어주면 됩니다.


## GeometryCollection using list of combination of geometries
point_coord = c(3, 3)
multilinestring_list = list(rbind(c(1, 1), c(1, 3), c(3, 5)),
                            rbind(c(2, 2), c(5, 2)))
polygon_list = list(rbind(c(4, 3), c(4, 5), c(5, 5), c(5, 3), c(4, 3)))

gemetrycollection_list = list(
  st_point(point_coord),
  st_multilinestring((multilinestring_list)),
  st_polygon(polygon_list)
  )

st_geometrycollection(gemetrycollection_list)
# GEOMETRYCOLLECTION (POINT (3 3),
#                     MULTILINESTRING ((1 1, 1 3, 3 5), (2 2, 5 2)),
#                     POLYGON ((4 3, 4 5, 5 5, 5 3, 4 3)))

## plot GeometryCollection
plot(st_geometrycollection(gemetrycollection_list))





이번 포스팅이 많은 도움이 되었기를 바랍니다.
행복한 데이터 과학자 되세요!  :-)



728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 R의 leaflet 패키지Open Street Map 활용하여 RStudio 또는 Jupyter Notebook R kernel IDE 에서 Interactive Map 을 그리는데 있어,


(1) 기본 상호작용하는 지도 생성하기 (create a basic interactive map)

(2) 지도 스타일 추가하기 (add map styles)

(3) 지도 좌표에 표시 풍선 추가하기 (add marker popup at latitude/longitude coordinates)

(4) 상호작용하는 동적 지도를 웹 페이지로 저장하기 (save an interactive map as web page)


하는 방법을 소개하겠습니다.


아래의 포스팅 예시는 RStudio IDE 에서 진행하였습니다. (Jupyter Notebook R kernel 에서도 가능)



  (1) 기본 상호작용하는 지도 생성하기 (create a basic interactive map)


먼저 R의 leaflet 패키지를 설치하고 불러오기를 해보겠습니다.



# install and importing leaflet package
install.packages("leaflet")
library(leaflet)




다음으로 leaflet 패키지의 leaflet() 함수를 사용하여, 기본 OpenStreetMap 타일을 추가하고 (add default OpenStreetMap map tiles), 대한민국의 위도(latitude), 경도(longitude) 위치에 zoom = 6 의 축소/확대 비율로 설정해서 동적인 지도(interactive map)를 그려보겠습니다.


마우스 커서로 좌측 상단의 '+'를 클릭하면 지도가 'zoom in' 확대되어 더 상세하게 볼 수 있으며, 반대로 좌측 상단의 '-' 를 클릭하면 지도가 'zoom out' 축소되어 더 넓은 지역을 볼 수 있게 됩니다. (마우스 휠을 사용해서 zoom in, zoom out 할 수도 있습니다.)



# creat a basic map
leaflet() %>%
  addTiles() %>% # add default OpenStreetMap map tiles
  setView( lng=127.063, lat=37.513, zoom = 6) # korea, zoom 6





애초에 기본 지도를 생성할 때 지도의 zoom 수준을 setView(zoom = xx) 에서 숫자로 설정해줄 수도 있습니다. 바로 위에서 생성했던 지도가 zoom = 6 이었다면, 아래 지도는 zoom = 8, zoom = 16 으로 기본 지도를 생성하게 해보겠습니다. 아래에 보면, 지도가 좀더 zoom in 으로 확대되어 더 상세하게 볼 수 있습니다.

(물론 interactive map 이기 때문에 마우스를 이용해서 언제든지 자유롭게 지도를 동적으로 zoom in, zoom out 할 수 있습니다.)



# zoom = 8

leaflet() %>%
  addTiles() %>% # add default OpenStreetMap map tiles
  setView( lng=127.063, lat=37.513, zoom = 8) # korea, zoom 8




# zoom = 16  (zoom in)

leaflet() %>%
  addTiles() %>%
  setView( lng=127.063, lat=37.513, zoom = 16) # korea, COEX






  (2) 지도 스타일 추가하기 (add map styles)


addProviderTiles("Tile Name Here") 를 이용하여 외부 지도 타일을 추가할 수 있습니다.


아래는 NASA에서 제공하는 우주의 인공위성에서 바라본 2012년 밤의 지도 타일("NASAGIBS.ViirsEarthAtNight2012") 입니다. 별도의 파일을 미리 다운로드 하거나 할 필요는 없구요, 그냥 타일 이름을 addProviderTiles() 메소드 안에 큰 따옴표로 해서 적어주기만 하면 됩니다. (물론, 외부와 통신할 수 있는 인터넷망에 접속해 있어야 합니다.)


한국의 경우 남한은 밤에 환한 반면에, 북한은 평양 빼고는 어둡네요. 38선 경계도 불빛으로 환하게 구분이 되는 모습을 보노라니 약간 서글프네요.



# map style: NASA
leaflet() %>%
  addTiles() %>%
  setView( lng=127.063, lat=37.513, zoom = 6) %>%
  addProviderTiles("NASAGIBS.ViirsEarthAtNight2012")





아래는 zoom = 16 으로 zoom in 해서 삼성동 COEX 부근을 확대해본 것인데요, 여기에 addProviderTiles("Esri.WorldImagery") 타일을 추가해 보았습니다. 항공사진 모습의 타일이네요.



# map style: Esri.WorldImagery
leaflet() %>%
  addTiles() %>%
  setView( lng=127.063, lat=37.513, zoom = 16) %>%
  addProviderTiles("Esri.WorldImagery")





위의 두 예 외에 leaflet() 에 다른 외부 타일 제공자의 타일 지도를 추가하고 싶으면 아래의 url 의 Leaflet-prodivers preview 에 방문해서 원하는 형태의 지도 스타일을 찾았다면 그 이름을 addProviderTiles("Tile Name Here") 메소드 안에 타일 이름을 큰 따옴표 안에 써주기만 하면 됩니다.


https://leaflet-extras.github.io/leaflet-providers/preview/






  (3) 지도 좌표에 표시 풍선 추가하기

      (add marker popup at latitude/longitude coordinates)


addMarkers() 메소드를 사용하면 위도(latitude), 경도(longitude) 좌표 위치에 풍선 모양의 표식과 커서를 클릭했을 때 팝업으로 나타나는 설명을 추가할 수 있습니다.


아래 예제에서는 대한민국 삼성동의 COEX Mall (코엑스 몰), GBC (현대자동차 Global Business Center), Samsil-Stadium (올림픽 주 경기장) 의 3개 주요 POI (Point Of Interest) 지점에 말풍선 표식을 추가해보았습니다. 마우스 커서를 말풍선 표식에 가져가서 클릭을 해보면 popup 설명이 튀어나옵니다.

(아래 예제는 스크린 캡쳐를 한 이미지 파일이어서 interactive map 기능이 안됩니다. RStudio 나 Jupyter Notebook R kernel 에서 interactive map 기능 사용 가능합니다.)



# adding Popup
popup = c("COEX", "GBC", "JamsilStadium")

leaflet() %>%
  addTiles() %>%
  addMarkers(lng = c(127.059, 127.063, 127.073), # longitude
             lat = c(37.511, 37.512, 37.516), # latitude
             popup = popup)




  (4) 상호작용하는 동적 지도를 웹 페이지로 저장하기

       (save an interactive map as web page)


위에서 만든 Interactive Map 을 HTML 웹 페이지로 저장하여 내보내기를 할 수 있습니다.


RStudio의 우측 하단의 Viewer 화면에서

   > Export

      > Save as Web Page


메뉴를 선택한 후에




아래와 같은 'Save As Web Page' 저장하기 팝업 화면이 나오면 HTML 파일의 이름과 저장할 경로를 지정해주면 됩니다.  나중에 이 HTML 파일을 웹 페이지에 올려서 바로 Interactive Map 을 바로 웹 페이지에 올릴 수 있습니다.




2020년 마지막 포스팅이 되겠네요.

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


행복한 데이터 과학자 되세요.

그리고 2020년 한해 마무리 잘하시고, 2021년 새해에는 건강하시고 복 많이 받으세요.


728x90
반응형
Posted by Rfriend
,

지난번 포스팅에서는 지리공간 데이터의 포맷으로서 벡터 데이터(vector data)와 레스터 데이터(raster data) 모델에 대해서 간단하게 소개(https://rfriend.tistory.com/589)를 하였습니다.


이번 포스팅에서는 R의 sf 패키지를 활용해서 spData 에 내장되어 있는 세계지도(world map)를 시각화해보겠습니다.


(1) 지리공간 데이터 처리 및 분석을 위한 R 패키지 설치

(2) 요약통계량 summary() 및 부분 집합 subset 하기

(3) sf 패키지의 plot()으로 기본 지도 시각화하기

(4) 다른 지도 층을 추가하기 (add plots as layers)

(5) 원과 텍스트를 덮어쓰우기 (overlaying circles and texts over the plot)



  (1) 지리공간 데이터 처리 및 분석을 위한 R 패키지 설치


R의 sf 패키지는 지리공간 벡터 데이터(vector data) 분석을 위한 패키지로서, 이전의 sp 패키지를 대체합니다. 그리고 GEOS와 GDAL과 R의 인터페이스를 제공하며 rgeos, rgdal 패키지를 대신합니다.


R의 raster 패키지는 지리공간 레스터 데이터(raster data)를 처리 및 분석하는데 사용합니다.


그리고 spData, spDataLarge 패키지에는 지리공간 데이터 샘플을 내장하고 있습니다. spDataLarge 패키지는 내장 데이터의 크기가 너무 크기 때문에 R CRAN 사이트에 패키지가 올라가 있지 않습니다. 따라서 CRAN에서 설치하려고 하면 에러가 나며, 아래처럼 Github 에서 type = "source" 로 해서 설치를 해주어야 합니다.


(만약 spData 패키지의 개발자 버전을 Github에서 바로 받아서 설치를 하려면 devtools::install_github("nowosad/spData") 로 하면 됩니다.)



# install packages

install.packages("sf")      # for vector data, ‘spatial data frame’
install.packages("raster") # for raster data
install.packages("spData")
install.packages("spDataLarge",
                 repos = "https://nowosad.github.io/drat/",
                 type = "source")


library(sf)
library(raster)
library(spData)
library(spDataLarge)

 



참고로, spData 패키지에는 37개의 지리공간 데이터셋이 내장되어 있으며, https://nowosad.github.io/spData/  깃헙 페이지에 가면 전체 리스트를 확인할 수 있습니다. 아래의 데이터셋 리스트 중에서 'world' (World country polygons) 데이터셋을 가지고 sf 패키지를 사용해서 요약통계량 및 시각화를 예를 들어보겠습니다.





  (2) 요약통계량 summary() 및 부분 집합 subset 하기


spData 패키지에 내장된 'world' 벡터 데이터에는 세계 대륙의 국가별로 10개의 집계데이터 칼럼과 마지막에 geom (지리공간 Polygon 리스트) 으로 구성되어 있습니다.


sf 패키지는 base R의 기본 함수를 그래도 사용할 수 있습니다. names()로 지리공간 데이터의 칼럼를 리스트업 할 수도 있고, summary() 함수로 요약통계량을 계산할 수 있습니다.


summary() 함수로 전세계 국가별 인구("pop")와 예상수명("lifeExp")에 대해 177개 Multipolygon 별로 최소/Q1/중앙값/Q3/최대값/결측값의 요약통계량을 계산해 보겠습니다.



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



##-- summary statistics
summary(world["lifeExp"])
# lifeExp                 geom    
# Min.   :50.62   MULTIPOLYGON :177  
# 1st Qu.:64.96   epsg:4326    :  0  
# Median :72.87   +proj=long...:  0  
# Mean   :70.85                      
# 3rd Qu.:76.78                      
# Max.   :83.59                      
# NA's   :10



summary(world["pop"])
# pop                       geom    
# Min.   :5.630e+04   MULTIPOLYGON :177  
# 1st Qu.:3.755e+06   epsg:4326    :  0  
# Median :1.040e+07   +proj=long...:  0  
# Mean   :4.282e+07                      
# 3rd Qu.:3.075e+07                      
# Max.   :1.364e+09                      
# NA's   :10




world 데이터셋의 제일 마지막 'geom' 칼럼에는 177개 국가에 대한 WGS 84 좌표 시스템의MultiPolygon 정보 (좌표 리스트)가 들어있습니다.



##-- geom
world$geom
# Geometry set for 177 features
# geometry type:  MULTIPOLYGON
# dimension:      XY
# bbox:           xmin: -180 ymin: -90 xmax: 180 ymax: 83.64513
# geographic CRS: WGS 84
# First 5 geometries:
#   MULTIPOLYGON (((180 -16.06713, 180 -16.55522, 1...
#   MULTIPOLYGON (((33.90371 -0.95, 34.07262 -1.059...
#   MULTIPOLYGON (((-8.66559 27.65643, -8.665124 27...
#   MULTIPOLYGON (((-122.84 49, -122.9742 49.00254,...
#   MULTIPOLYGON (((-122.84 49, -120 49, -117.0312 ...




행과 열의 부분집합을 subset 하는 방법도 기본 R 과 동일합니다. 아래 예에서는 1행~2행, 1열~3열까지의 데이터셋을 subset 해보겠습니다.



##-- subset
world_mini = world[1:2, 1:3]
world_mini
# Simple feature collection with 2 features and 3 fields
# geometry type:  MULTIPOLYGON
# dimension:      XY
# bbox:           xmin: -180 ymin: -18.28799 xmax: 180 ymax: -0.95
# geographic CRS: WGS 84
# # A tibble: 2 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.596~
#   2 TZ     Tanzania  Africa    (((33.90371 -0.95, 34.07262 -1.05982, 37.69869 -3.09699, 37.7669 -3.67712, 39.20~




  (3) sf 패키지의 plot()으로 기본 지도 시각화하기


 world 세계지도 데이터 칼럼 중 7열~10열까지 4개 칼럼 별로 177 개 MultiPolygon별 값에 따라 색깔을 달리해서 R의 plot() 함수로 시각화를 해보겠습니다. ('area_km2', 'pop', 'lifeExp', 'gdpPercap' 칼럼의 값에 따라서 'geom' 의 177개 MultiPolygon 별 색깔이 달라짐.)


단 plot() 함수로 시각화를 하면 매우 간단하게 지도를 시각화할 수 있지만, 상호작용하는 동적인 지도(interactive map)가 아니라 그냥 정적인 지도만 그려지게 됩니다. (interactive map 은 다음번 포스팅에서 소개 예정)



##-- making a basic map using sf's plot()
# not interactive plot
plot(world[7:10])




위처럼 여러개의 칼럼에 대해 한꺼번에 여러개의 지도를 시각화하면 색깔이 무엇을 의미하는지 범례가 표시되지 않습니다.


반면에, 아래처럼 특정 한개의 변수에 대해서만 plot() 으로 시각화를 하면 색깔이 의미하는 바에 대한 범례(legend)를 색깔 막대 형태로 표시해줍니다.



## plot of 'lifeExp' per countries
plot(world["lifeExp"])


 



plot() 으로 지리공간 데이터를 시각화할 때 col 매개변수로 특정 색깔을 지정해줄 수도 있습니다. 대신, 특정 색깔을 col 로 지정해주면 위의 지도 시각화처럼 오른쪽에 색깔 막대 범례는 필요가 없으므로, 비록 1개 변수만 시각화한다고 해도 범례는 없습니다.



## no continuous palette legend
plot(world["lifeExp"], col="yellow")






  (4) 다른 지도 층을 추가하기 (add plots as layers)


위의 (3)번 처럼 지도를 먼저 한번 시각화를 하고, add = TRUE 매개변수를 사용하면 나중에 그 위에 다른 지도를 겹쳐서, 즉 층을 추가하여 지도를 덮어쓰기로 그릴 수 있습니다.


단, 첫번째 지도 그래프에 키(key)가 있을 경우에는 reset = FALSE 매개변수를 꼭 설정해준 다음에, 이후에 다음번 plot(add = TRUE)를 사용해주어야 합니다.



# add plots as layers
world_asia = world[world$continent == "Asia", ]
asia = st_union(world_asia) # combining countries in Asia

# if the first plot has a key, reset=FALSE must be used.
plot(world["lifeExp"], reset = FALSE)
plot(asia, add = TRUE, col = "red")






  (5) 원을 덮어쓰우기 (overlaying circles over the plot)


cex 매개변수를 사용하면 시각화한 지도 위에 원을 덮어쓰울 수 있습니다.


아래 예에서는 세계지도 위에 국가별 인구에 비례해서 원을 덮어쓰워보겠습니다. (pop 변수에 제곱근을 취하고 10000 으로 나누어준 것은 시각화한 지도 크기에 맞추어서 너무 크지도, 작지도 않은 원을 덮어쓰우기 위해 숫자를 조정한 것입니다.)



##-- overlaying circles with cex argument
plot(world["continent"], reset = FALSE)
pop_sqrt = sqrt(world$pop) / 10000
world_centroid = st_centroid(world, of_largest = TRUE)
plot(st_geometry(world_centroid), add = TRUE, cex = pop_sqrt)





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

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



728x90
반응형
Posted by Rfriend
,

올 해 크리스마스는 그 어느해보다 우울하고 가슴이 먹먹하게 보냈습니다.  코로나가 기승을 부려서 가족여행을 취소하고 집콕을 해야만 했던 것도 이유 중 하나겠지만, 그보다 연이어 이틀 법원으로 부터 나온 판결 소식에 망치로 뒤통수를 얻어맞은 듯이 어안이 벙벙하고 검찰과 언론, 법원에 화가 났기 때문입니다.


- 2020년 12월 23일, 정경심 교수의 1심 판결 (4년 징역, 5억원 벌금, 법정 구속).

- 그리고, 2020년 12월 24일 윤석열 검찰총장 직무정지 취소 가처분신청의 법원 인용.


저는 법조계나 언론, 정치쪽에서 일하는 사람이 아니고, 또 그쪽 분야 전문가도 아니므로 깊이 있는 통찰이 담긴 글을 쓸 수는 없습니다. 다만, 대한민국의 민주주의가 위협받고 있을 때 "담벼락에 대고 욕이라도 해라"라는 고 김대중 대통령의 말씀처럼, 그래도 뭐라도 해야겠기에, 제가 이해하고 있는 바에 대해서 담벼락에 몇 자 적어봅니다.



1. 위 두 판결 관련 일련의 일들은 왜, 무슨 맥락에서 일어나고 있는가?


현 문재인 정부와 조국 전 법무부 장관이 검찰 개혁을 추진하였기 때문입니다. 그리고 막강한 기득권을 가진 검찰 그리고 사법부, 언론, 보수야당(국민의힘)이 그들만의 카르텔을 형성하고 검찰 개혁을 저지하려고 하기 때문입니다.



아래의 '외국과 우리나라 검사의 권한 비교' 표를 보면, 대한민국 검찰이 가진 권한은 전 세계 최강, 우주 최고 수준입니다. 누군가 그러더군요. 기소권한과 수사권한을 모두 가진 대한민국 검찰은 자기 입맛에 맞게 선택적으로 "기소를 함으로써 명예를 얻고, 기소를 하지 않음으로써 부를 쌓는다"라구요. 기소권과 수사권의 양날은 "전관예우"(라고 쓰고 "전관유착비리"라고 읽어야 겠죠)라는 "검은 돈"의 자양분이니 검사와 판사들 입장에서는 현 정부가 자신들의 미래의 밥통을 없애는 사악한(?) 무리로 보일 것입니다.



* 출처: 2012년 경찰청 연구용역보고서, <국민이 체감할 수 있는 수사권 조정의 효과에 관한 연구>



더 나아가서, "검사와 판사는 죄를 지어도 (거의) 기소되지 않으니" 현재의 체제가 얼마나 좋겠습니까?! 현 정부가 "공수처(고위공직자범죄수사처)"를 설립해서 검사와 판사도 죄를 지으면 그에 상응하는 처벌을 하겠다고 하니 얼마나 현 문재인 정부와 전 조국 법무부 장관, 현 추미애 법무부 장관, 그리고 더불어민주당이 싫겠습니까.






2. 검찰, 법원, 언론은 공평한가?


전혀 공평하지 않으며, 누구를 대상으로 하느냐에 따라 편향된, 완전히 기울어진 운동장입니다.


정경심 교수, 나경원 전 의원, 김건희 검찰총장 배우자의 의혹 사건에 대한 검찰, 법원, 언론의 대응은 천양지차를 보이고 있습니다. 검찰은 유독 조국 전 법무부 장관의 가족에게만 '사냥'을 하듯 수사를 하였고, 법원은 '영장 자판기' 마냥 70여곳의 압수수색 영장을 발부하였으며, 언론은 수 십만건의 기사를 쏟아냈습니다.




아래의 리스트는 MBC PD수첩 '조국 장관과 표창장' 방송에서 나온 2019년 8월27일~9월27일 기간 동안 총 70여곳 압수수색한 곳의 리스트입니다. 대한민국 역사 이래 이렇게 "특정인과 그 가족"을 대상으로 무지막지하고 잔인하게, 인권은 철저히 무시한 채 압수수색과 조사가 이루어진 적이 있던가요?





아래 기사는 더브리핑에서 2020.09.18일에 낸 "한국 언론에게 김건희는 '금단의 존재'인가?"라는 기사에서 보도한 김건희 vs. 추미애 아들 신문 보도량 비교입니다. 뉴스타파가 윤석열 검찰총장 부인 김건희 씨의 주가조작 연루 의혹을 2020.2.17일 보도했고, 4월7일 열린민주당 최강욱 대표가 이 사건을 고발했지만, 검찰은 가만히 있고, 언론은 철저하게 외면하고 있다는 내용입니다.





3. 사문서 위조와 공문서 위조에 대한 검찰의 대응과 법원의 판단은 적절한가?


2015년 부산에서 검사가 "공문서"인 고소장을 위조한 사건이 있었는데, 검찰은 제식구 감싸기에 급급해서 아무것도 안하고, A검사가 사표를 내자 바로 수리를 해주었다고 합니다. 보다못한 시민단체가 A검사를 고발한 후에야 수사를 시작했는데, 경찰이 신청한 압수수색 영장도 검찰이 모두 기각해주고, 자료도 내놓지 않고, 재판에 회부될 때까지 2년 2개월이 걸렸다네요. 법원은 선고유예 판결을 내려주었다고 합니다.

(*출처: https://blog.naver.com/sangsaengstory/221663469439)


"사문서"인 "봉사활동 표창장 위조 의혹"에는 '사법농단' 특검을 제외한 검찰의 단일 수사로는 두 번째로 큰 규모로 인력을 투입하여 70여곳 압수수색, 조사도 없이 기소 먼저 하고, 고소장에는 누가, 언제, 어디서, 어떻게 위조했는지에 대한 내용도 없고, 원본도 없고, 재판 중에 기소장을 변경하고, 법원은 기소장 변경을 받아주고, 결국 1심에서 징역 4년, 벌금 5억원 판결을 내렸습니다.


윤석열 총장 장모 최은순씨의 "347억 은행잔고 위조" 사건은 검찰, 법원이 어떻게 처리하는지 두눈 부릅뜨고 지켜보겠습니다.




그럼, 1심에서 '봉사활동 표창장 위조 의혹 & 죄를 시인하지 않고 반성하지 않는다는 괘씸죄'에 대해 징역 4년, 벌금 5억원, 법정 구속 판결이 나왔는데요, 이 사문서 위조 의혹에 대한 판결 형량은 그동안의 법원 판결에 비추어봤을 때 납득할 만한 수준인가요? ('표창장 위조 의혹'에 대한 재판에서 정경심 교수측에 유리한 증언은 모두 무시되었다고 하니 항소심 결과를 지켜보시죠).


세계 최대 아동성착취 사이트를 운영한 손정우도 징역 1년 6개월, 대전에서 동거녀를 때려 숨지게 하고 콘크리트 암매장한 30대가 징역 3년의 일반인의 상식과는 동떨어진 솜방망이 처벌을 하더니, 지방대 봉사활동 표창장 위조 의혹은 추상같은 호령으로 징역 4년에 벌금 5억원 판결을 내렸습니다. 일반인이 제가 생각하기에는 이건 판사가 사심과 정치적 편향을 가지고 작심하고 '너 한번 죽어봐라'하고 판결했다고 밖에 생각할 수가 없습니다. 상식적으로 납득이 안되잖아요.




그리고 무슨 조선시대 포도청의 사또도 아니고, 2020년도에 법원의 판사가 "네 죄를 네가 알렷다?"를 시전하면서 "단 한번도 반성이 없으니 엄중한 처벌이 불가피하다"고 판결하는게 말이 됩니까?


재판부는 헌법이 보장하는 무죄추정의 원칙과 방어권을 무시했고, 또 검찰이 70여곳을 압수수색했음에도 불구하고 정경심 교수측이 증거인멸을 할 위험이 있으므로 법정구속을 하였습니다.


1심의 임정엽 판사는 검찰쪽 의견은 대부분 반영하고, 피고인 측에 유리한 증언은 대부분 무시하였다고 하니 판사가 공평하게 판결을 한 것인지 의구심이 듭니다. (재판 1심의 임정엽 판사의 과거 '친동생 성폭행한 의사 무죄' 부당한 판결과 이번 '정경심 교수 1심의 문제점'에 대한 'The briefing'의 고일석 기자의 기사는 여기를 참고하세요)




4. 2019년 대한민국 사법부의 신뢰도는?


예상하셨겠지만, 2019년 대한민국 사법부 신뢰도는 OECD 꼴찌입니다!

대법원이 OECD 조사 초안을 받아보고서는 발칵 뒤집혔다는데요, 변명이 궁색합니다. OECD 조사 질문에 "검찰을 포함한 사법시스템도 질문"하였기 때문에 "법원만 콕 집어 물어본 것이 아니므로" 이 조사결과를 인정할 수 없으니 한국에 대한 조사결과는 빼고 발표해달라고 OECD에 요청을 했다는 군요. 대법원의 변명처럼, 한국의 사법시스템 질문에 검찰도 포함이 되어서 OECD 꼴찌일 수도 있겠네요. 검찰과 사법부의 그동안의 자업자득입니다.


* 출처: "사업부 신뢰도 OECD 꼴찌, 대법원 발칵 뒤집혔다는데...", 조선일보, 2019.11.05



OECD 조사 결과 (Government at a Glance 2019 의 36페이지, "Table 1.4. Scorecard on access, responsiveness and quality of the judiciary system")는 여기를 클릭하면 볼 수 있습데요, 한국 대법원의 요청에 따라 한국 사법부에 대한 평가는 n.d. (Data on confidence for Korea are Not Displayed) 로 되어있습니다.





5. 2019년 대한민국 언론의 신뢰도는?


그럼 한국 언론의 신뢰도는 어떨까요? 역시 예상하셨던대로 세계 주요 38개국 대상 4년 연속 부동의 꼴찌입니다.


국경없는 기자회가 발표하는 언론 자유 지수(Press Freedom Index)에서 한국은 2016년 70위였던 것이 2019년 41위까지 상승하였습니다만, 한국의 언론 신뢰도는 4년 연속 부동의 꼴찌를 차지하였습니다. 기자를 보고 '기레기'(기자+쓰레기)를 넘어서 '기더기'(기자+구더기)로 진화발전하는 것은 역시 자업자득입니다.




* 출처: "한국 언론 신뢰도, 4년 연속 부동의 꼴찌", 서울신문, 2019.06.14



윤석열 검찰총장의 오른팔 "한동훈 검사와 채널A 이동재 기자의 검언유착 사건"이 어떻게 처리될지 지켜보겠습니다. 이러니 사법부도 못 및겠고, 언론도 못 믿겠다고 하는거 아닙니까. 자업자득입니다.



[PD수첩 핫클립] 윤석열.한동훈.이동재, 검언유착 사건의 진실은? (MBC 방송) 을 보시려면 여기로 ==>

https://youtu.be/rH2pTkn5nHE



6. 우리는 조국 전 법무부 장관과 그 가족에게 돌을 던질 수 있는가?


1심 재판 결과 나오고 온라인 포털의 댓글란에 보니 조국 전 장관과 그 가족을 욕하는 글들이 여럿 보이는데, 그걸 보면서 가슴이 너무 아팠습니다. 만약 제가 조국 전 장관의 위치에 있다고 가정하고, 검찰 개혁을 추진했다는 이유만으로 검찰과 언론에 "멸문지화"에 이를 정도로 온 가족, 부모, 형제, 친척, 주변 지인들이 도륙을 당하고, 또 뇌종양, 뇌경색을 앓고 있는 배우자가 구속이 되며, 자녀는살아온 인생을 송두리째 모욕당하는 일을 겪는다면 저는 창자가 끊어지는 아픔을 느낄 것 같습니다.


죄를 짓지 않으면 되는것 아니냐구요?  제가 위에 긴 글을 쓴 이유는 검찰이 "비가 올 때까지 기우제를 지내는 인디언 기우제" 마냥 "조국 전 법무부 장관, 그리고 그와 관련된 사람들 중에 죄가 나올 때까지 뒤지고, 안나오면 또 압수수색하고, 안나오면 또 압수수색하고, ... ", 그래서 결국 죄가 나올 때까지 조사하고, 언론 플레이할 것이기 때문에 불가능하다는 것입니다. 예수님, 부처님, 공자님이 와도 검찰이 작심하고 먼지를 털기 시작하면 먼지가 나오게 되어있고 언론은 이를 대서특필할 것이 분명합니다. 왜냐하면 먼지가 나올 때까지 계속 털 것이기 때문입니다.


조국 전 법무부 장관 (전 민정수석)의 소위 "권력형 비리" 관련한 뉴스를 단 한개라도 본적이 있으신가요? 제 기억에는 없습니다. (하다못해 불법 주차딱지 하나 없습니다). 공직자의 권력형 비리에 대해서 철저히 수사하는 것은 당연히 필요하지만, 그 외 별건수사로 가족을 인질로 삼아 인간사냥을 한 검찰의 모든 수사는 비판받아 마땅하고 다시는 이런 일이 벌어지면 안된다고 생각합니다. (이미 추미애 현 법무부 장관의 아들 군복무 휴가 의혹으로 검찰과 언론이 난리 굿을 피웠습니다.)  그리고 언론에서도 조국 전 장관 이외의 가족들 기사로 아직도 상처를 후벼파고 있는데요, 너무 잔인하고 야비합니다. 가족 인질극은 쌩 양아치나 하는 짓거리아닙니까!


(국회의원의 지위를 이용해 3 천억원 가까운 공사를 수주한 국민의힘 박덕흠 의원, 편법증여 의혹에 보도 무마 3천만원 제공 의혹의 국민의힘 전봉민 의원에 대한 기사는 왜 이리 찾아보기 힘듭니까? 권력형 비리 감시하는게 언론의 역할 아닙니까!!!)


만약, 우리가 지금 조국 전 법무부 장관과 그 가족에게 돌을 던진다면 이는 검찰과 언론, 사법부, 보수우익정당(국민의힘)의 카르텔에 일조하는 것이고, 또 앞으로 어느 누구도 조국 전 법무부 장관과 같이 살신성인하며 검찰개혁, 사법개혁을 위해 희생하려고 나서지 않을 것입니다. 공직에 나선 당사자에 대한 검증 절차는 당연히 필요한데요, 가장 가까운 가족을 상대로 검찰과 언론이 인질극과 인신모욕과 사회적 매장의 양아치 짓을 벌이는데 누가 그것을 견딜 수 있겠습니까? 


조국 전 법무부 장관이 바로 항소를 하였으니 항소심 재판 결과를 지켜보겠습니다. 그 결과가 어찌되었든 저는 조국 전 장관과 그 가족에게 돌을 던져서는 안된다고 생각합니다. 우리 사회는 그 가족에게 값지 못할 큰 빚을 졌습니다.




7. 우리는 무엇을 할 수 있을까?


저는 검찰/사법/언론 개혁에 대해서는 전문가가 아니므로 이 부분은 길게 쓸 내용은 없습니다. 다만, 문재인 대통령이 '검찰/사법 개혁'에 대해서는 최고의 전문가요 지휘통솔권자이며, 조국 전 법무부 장관과 현 추미애 법무부 장관이 검찰의 '가족 인질극'이 있을 것임을 알고도 희생하면서 검찰 개혁을 힘있게 추진하는 분들임은 알고 있고 또 믿고 있습니다. 그래서 현 문재인 정부를 지지합니다.


법무부의 윤석열 검창 총장에 대한 '정직 2개월' 징계가 법원의 처분 중단 결정이 내려졌습니다. 행정부의 견제에 사법부가 검찰 손을 들어줬으니, 이제 법을 입안하는 국회가 제 역할을 해줘야 하는 시간 같네요. (검찰이 판사들 사찰했다는데 검찰 총장 손들어준 판사들, 참 대단합니다. 에휴, 배알도 없는 판사들...)


더불어민주당이 추진하려고 하는 "검찰 개혁 입법"과 "공수처 설치"를 적극 지지합니다. 민주당에서는 국민의힘과의 협치라는 신기루에 빠지지 말고, 검찰 개혁 입법 관련해서는 밀고 나가시기를 응원합니다. 상대방이 "양아치"처럼 싸움을 하고 있는데 당하는 이쪽에서는 "양반"처럼 체면차리고 있다가는 다 죽습니다. 이번에 180석의 국회의원 의석수로 못해내면 앞으로 대한민국 역사에서 "검찰과 사법부와 언론의 카르텔"에 대항해서 "국민을 무서워하고 국민을 섬기는 검찰과 사법부"로 거듭날 수 있도록 제도적인 체계를 마련하는 것은 영영 불가능할 것입니다.


역사는 "견제받지 않는 권력은 반드시 부패한다"는 것을 말해주고 있습니다. 이번에 반드시 우주최강의 검찰 권력이 견제와 감시, 민주적 통제를 받을 수 있도록 제도적인 체제가 개혁되기를 소망합니다.


더불어민주당에 온라인으로 입당하고자 하는 분은 https://theminjoo.kr/mypage/partyFjoin 에 가서 바로 하실 수 있습니다. 당비는 최소 월 1천원 이상 납부하시면 권리당원으로 가입할 수 있습니다.


권력을 감시해야할 언론이 권력과 카르텔을 형성해 악의적인 기사, 오보, 허위기사를 남발할 때면 시민들의 언론 감시가 중요할 것입니다. 뭔가 시민들이 자발적으로 참여해서 기레기들의 기사를 모니터링하고 평가하고 역사의 기록으로 남겨놓을 수 있는, 그래서 기레기가 두고 두고 부끄러움을 느끼게 할 수 있는 플랫폼이 있으면 좋겠다는 바램도 가져봅니다.


리고 국회에서는 언론의 무책임하고 악의적인 기사에 대해 '징벌적 손해배상제도'를 도입하면 좋겠습니다. 팩트 체크 없이 검찰이 불러주는 대로 받아쓰기만 하는 한국의 언론이 자발적으로 변화하는 것은 기대하기 어려울 것이기 때문입니다.


마지막으로, 대한민국 헌법 1조를 다시 한번 되뇌어 보는 것으로 포스팅을 마치겠습니다.


대한민국은 검찰공화국도 아니요, 사법부공화국도 아니며, 언론공화국도 아닙니다!


대한민국 헌법 1조:


대한민국은 민주공화국이다.

대한민국의 주권은 국민에게 있고, 모든 권력은 국민으로부터 나온다.


* 카툰 출처: by o_deng96, https://www.instagram.com/o_deng96/

728x90
반응형
Posted by Rfriend
,

pandas의 Series나 DataFrame 자료구조로 저장된 시계열 데이터에 대해서 이전 값 대비 현재 값의 변동율(change percentage)을 구하고 싶을 때 pandas 의 pct_change() 메소드를 사용하면 매우 편리하게 계산할 수 있습니다. 


이번 포스팅에서는 Python pandas 패키지의 pct_change() 메소드를 사용하여 


pandas Series에서

- (1) 이전 원소 대비 변동률 

       (Percentage change between the current and a prior element)

- (2) 이전 2개 원소 대비 변동률 

       (Percentage change between the current and 2 periods prior element)

- (3) 결측값을 이전 원소 값으로 대체 후 이전 원소 대비 변동률 

       (Percentage change between the current and a prior element after filling the missing values using the 'forward fill' method)


pandas DataFrame에서

- (4) 그룹별 이전 분기 대비 변동률 

      (Percentage change between the current and a prior quarter by Group)

- (5) 그룹별 전년 동분기 대비 변동률  

       (Percentage change between the current and a year before by Group)




* pandas의 pct_change() 메소드는 Series와 DataFrame 자료구조 모두에서 동일하게 사용 가능합니다. 



-- pandas Series 에서


  (1) 이전 원소 대비 변동률 

       (Percentage change between the current and a prior element)


pandas의 pct_change() 메소드는 기본 설정이 이전 원소 대비 현재 원소의 변동 비율(percentage change)을 계산해줍니다. 아래 pandas Series의 경우, 


첫번째 값은 이전 값이 없으므로 NaN

두번째 값의 첫번째 값 대비 변동률 = (20-10)/10 = 1.0

세번째 값의 두번째 값 대비 변동률 = (50-20)/20 = 1.5

네번째 값의 세번째 값 대비 변동률 = (55-50)/50 = 0.1

다섯번째 값의 네번째 값 대비 변동률 = (70-55)/55 = 0.27



In [1]: import pandas as pd


In [2]:

s = pd.Series([10, 20, 50, 55, 70])

s.pct_change()


Out[2]:

0 NaN

1 1.000000

2 1.500000

3 0.100000

4 0.272727

dtype: float64





  (2) 이전 2개 원소 대비 변동률 

       (Percentage change between the current and 2 periods prior element)


변동률을 구할 때 이전 값의 이동 기간을 periods 매개변수를 사용하면 자유롭게 설정해줄 수 있습니다. 가령, 위의 s Series 예에서 이전 2개 원소 대비 변동률은 s.pct_change(periods=2) 로 해주면 됩니다. 


첫번째와 두번째 값은 이전 2개 원소 값이 없으므로 NaN

세번째값의 이전 2개 원소 값 대비 변동률 = (50-10)/10 = 4.0

네번째값의 이전 2개 원소 값 대비 변동률 = (55-20)/20 = 1.75

다섯번째값의 이전 2개 원소 값 대비 변동률 = (70-50)/50 = 0.4



In [3]:

s = pd.Series([10, 20, 50, 55, 70])

s.pct_change(periods=2)


Out[3]:

0 NaN

1 NaN

2 4.00

3 1.75

4 0.40

dtype: float64





  (3) 결측값을 이전 원소 값으로 대체 후 이전 원소 대비 변동률 

       (Percentage change between the current and a prior element
        after filling the missing values using the 'forward fill' method
)


만약 데이터셋 안에 결측값(missing value)가 있다면 pct_change() 메소드에 pandas의 결측값 처리 매개변수를 그대로 차용하여 결측값을 처리한 후에 이전 원소 대비 변동률을 구할 수 있습니다. 


결측값을 처리하는 방법으로는, 

fill_method='ffill' or 'pad'       : 이전 값으로 결측값을 대체하여 채우기 (앞방향으로 채워나가기)

fill_method='bfill' or 'backfill'  : 이후 값으로 결측값을 대체하여 채우기 (뒤방향에서 채워나가기)



In [4]:

s2 = pd.Series([10, 20, 50, None, 70])

s2.pct_change(fill_method='ffill')


Out[4]:

0 NaN

1 1.0

2 1.5

3 0.0

4 0.4

dtype: float64

 




-- pandas DataFrame 에서


  (4) 그룹별 이전 분기 대비 변동률 

      (Percentage change between the current and a prior quarter by Group)


예제로 사용할 '제품(product)' 그룹을 가진 연도(year)/ 분기(quarter)  기간 별 판매량(sales) 칼럼으로 구성된 DataFrame을 만들어보겠습니다. 



In [5]:

# input data sale = pd.DataFrame( {'product': ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b'], 'year': [2018, 2018, 2018, 2018, 2019, 2019, 2019, 2019, 2020, 2020, 2020, 2020, 2018, 2018, 2018, 2018, 2019, 2019, 2019, 2019, 2020, 2020, 2020, 2020], 'quarter': [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4], 'sales': [5, 6, 6, 8, 10, 20, 30, 40, 12, 25, 38, 50, 60, 65, 80, 95, 100, 125, 130, 140, 110, 130, 132, 144]})


sale

Out[5]:

product year quarter sales

0 a 2018 1 5

1 a 2018 2 6

2 a 2018 3 6

3 a 2018 4 8

4 a 2019 1 10

5 a 2019 2 20

6 a 2019 3 30

7 a 2019 4 40

8 a 2020 1 12

9 a 2020 2 25

10 a 2020 3 38

11 a 2020 4 50

12 b 2018 1 60

13 b 2018 2 65

14 b 2018 3 80

15 b 2018 4 95

16 b 2019 1 100

17 b 2019 2 125

18 b 2019 3 130

19 b 2019 4 140

20 b 2020 1 110

21 b 2020 2 130

22 b 2020 3 132

23 b 2020 4 144

 



이제 '제품(product)' 그룹별로 '이전 분기 대비 현재 분기의 변동율(change percentage between the current and the prior quarter)' 을 구해보겠습니다. 


물론 이번 예제 데이터는 년(year)/ 분기(quarter) 를 기준으로 이미 정렬이 되어 있기는 합니다만, 정렬이 안되어 있는 경우도 있을 수 있으므로 명확하게 시간 기준으로 정렬될 수 있도록 sort_values(by=['year', 'quarter'] 로 명시적으로 먼저 정렬을 해주었습니다.  다음으로 groupby(['product']) 메소드로 '제품(product)' 별로 그룹을 분할(split) 하여 그룹별로 이후 연산이 이루어지도록 하였습니다. 마지막으로 sales.pct_change() 메소드로 '판매량(sales)' 칼럼에 대해 '이전대비 변동률(pct_change)'을 '제품' 그룹별로 구해주었습니다. 



In [6]:

sale['sales_pct_change_by_1q'] = sale.\ sort_values(['year', 'quarter']).\ groupby(['product']).\ sales.pct_change()


sale

Out[6]:

product year quarter sales pct_change_by_1q

0 a 2018 1 NaN

1 a 2018 2 6 0.200000

2 a 2018 3 6 0.000000

3 a 2018 4 8 0.333333

4 a 2019 1 10 0.250000

5 a 2019 2 20 1.000000

6 a 2019 3 30 0.500000

7 a 2019 4 40 0.333333

8 a 2020 1 12 -0.700000

9 a 2020 2 25 1.083333

10 a 2020 3 38 0.520000

11 a 2020 4 50 0.315789

12 b 2018 1 60 NaN

13 b 2018 2 65 0.083333

14 b 2018 3 80 0.230769

15 b 2018 4 95 0.187500

16 b 2019 1 100 0.052632

17 b 2019 2 125 0.250000

18 b 2019 3 130 0.040000

19 b 2019 4 140 0.076923

20 b 2020 1 110 -0.214286

21 b 2020 2 130 0.181818

22 b 2020 3 132 0.015385

23 b 2020 4 144 0.090909

 




  (5) 그룹별 전년 동분기 대비 변동률  

       (Percentage change between the current and a year before by Group)


만약 이전 분기가 아니라 '전년 동일 분기' 대비 변동률을 구하고 싶다면 pct_change(periods=4) 처럼 periods=4 매개변수를 설정해주어서 4분기 이전 (즉, 전년 동일 분기)의 값 대비 변동률을 구해주면 됩니다. (만약 월 단위로 데이터가 집계되어 있다면 pct_change(periods=12) 로 해주면 됩니다.)



In [7]:

 sale['pct_change_by_1y'] = sale.sort_values(['year', 'quarter']).\

  groupby(['product']).\

  sales.pct_change(periods=4)


In [8]: sale.sort_values(by=['product', 'quarter', 'year'])

Out[8]:

product year quarter sales pct_change_by_1q pct_change_by_1y

0 a 2018 1 5 NaN NaN

4 a 2019 1 10 0.250000 1.000000

8 a 2020 1 12 -0.700000 0.200000

1 a 2018 2 6 0.200000 NaN

5 a 2019 2 20 1.000000 2.333333

9 a 2020 2 25 1.083333 0.250000

2 a 2018 3 6 0.000000 NaN

6 a 2019 3 30 0.500000 4.000000

10 a 2020 3 38 0.520000 0.266667

3 a 2018 4 8 0.333333 NaN

7 a 2019 4 40 0.333333 4.000000

11 a 2020 4 50 0.315789 0.250000

12 b 2018 1 60 NaN NaN

16 b 2019 1 100 0.052632 0.666667

20 b 2020 1 110 -0.214286 0.100000

13 b 2018 2 65 0.083333 NaN

17 b 2019 2 125 0.250000 0.923077

21 b 2020 2 130 0.181818 0.040000

14 b 2018 3 80 0.230769 NaN

18 b 2019 3 130 0.040000 0.625000

22 b 2020 3 132 0.015385 0.015385

15 b 2018 4 95 0.187500 NaN

19 b 2019 4 140 0.076923 0.473684

23 b 2020 4 144 0.090909 0.028571

 



또는 아래 방법처럼 분기(quarter)/ 년(year) 를 기준으로 먼저 정렬을 해놓고, 그 다음에 제품/분기 그룹(groupby(['product', 'quarter']) 별로 판매량의 변동률(sales.pct_change())를 구해도 결과는 같습니다. 



# or equvalently

sale['pct_change_by_1y'] = sale.sort_values(by=['quarter', 'year']).\

    groupby(['product', 'quarter']).\

        sales.pct_change()


sale.sort_values(by=['product', 'quarter', 'year'])

 



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

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



728x90
반응형
Posted by Rfriend
,