Python에 CARTOframes를 더해, 분석의 시너지 효과를 경험해보세요!

이 포스팅은 CARTOframes을 사용하여 공간 분석을 구현하는 방법을 안내합니다. 

 

CARTOframes에서는 분석을 수행하고 결과를 pandas 데이터 프레임으로 리턴하기위한 CartoContext.query 메소드와 분석을 맵 계층으로 시각화하기위한 QueryLayer 클래스를 제공합니다. 두 방법 모두 PostGIS를 사용하여 PostgreSQL 데이터베이스에 대해 쿼리를 실행합니다.

또한, 좀 더 다양한 시각효과를 낼 수 있는 cartoframes.viz package 또한 제공하므로 분석결과를  더욱 효과적으로 전달할 수 있습니다.

 

이 포스팅에서는 CARTO의 공간 분석 기능과 시각화 기능을 사용하여 서울에서 1인가구가 살기 좋은 동네의 위치를 분석해보겠습니다.

 

분석 방향 , 방법 

먼저, 1인 가구의 삶의 질에 영향을 줄 수 있는 8가지  요소(편의 시설 등)들을 선정하였습니다.

서울시를 300m의 그리드(Grid)로 나눈 뒤, 해당 요소가 그리드 내에 존재하면 1 그렇지 않으면 0으로 표시하여 합산 후,  그리드내에 1인가구 삶의 질에 영향을 주는 요소가 가장 많은 그리드를 가장 살기 좋은 동네로 선정하였습니다. 그렇다면 총점은 8점이 되겠죠?

 

준비물 

– 서울시 Grid 데이터

– 서울시 대형마켓, 무인택배함 , 우체국과 주민센터, 패스트푸드점과 카페, 도서관, 지하철역, 공원 위치 데이터 

( 패스트푸드점과 카페를 제외한 항목은 상대적으로 데이터 수가 적기 때문에  500m 버퍼 데이터를 사용할 예정입니다.)

– ( 위의 데이터를 미리 카토 계정에 업로드 해 주세요 ! ) 

 

시작하기

계정생성

분석에 앞서, 만든 데이터나 map을 불러들이고 내보낼 계정을 설정하기위해 CartoContext를 생성해주세요.

데이터 불러오기

계정을 연결했다면, 계정에 존재하는 데이터를 불러와야할 차례네요.

카토 계정에 미리 업로드 해놓은 서울 그리드 데이터를 CartoContext의 read 함수로 불러 올 수 있습니다.

SQL문 시행시키기

그리드에 요소 데이터의 위치가 포함되는지 확인 해보도록 하죠.

CARTOContext.query 메소드를 사용하여 CARTO 계정의 데이터에 대한 SQL 쿼리를 실행하고, 

 PostGIS의 공간 분석 기능 중 하나인 ST_Intersects 활용해 봅시다.

ST_Intersects는 두 공간 데이터가 겹치는 부분이 있으면 1을 반환하는 함수입니다.

따라서, 결과 데이터는 위와 같이 해당 그리드의 공간정보와 우체국이나 주민센터(ins)를 포함하고 있는지를 나타내게 됩니다.

 

위와 동일한 방식으로 무인택배함 데이터와 그리드 데이터를 병합한 데이터를 만들어 줍니다!

 

가중치부여

카페와 패스트푸드점과 같이 그리드 안에 갯수가 많을 가능성이 있는 항목의 경우, 가중치를 줄 수도 있겠죠?

그럴 경우, 존재 여부 대신 해당 그리드에 존재하는 갯수를 구하는 SQL문을 한번 더 작성해주시면 아래와 같은 결과를 얻게됩니다.

이 컬럼을 한 그리드 당 존재하는 가장 많은 카페수로 나눠주면,  가장 많은 카페수를 가지고 있는 그리드는 1점을 가지게 되겠죠?

이 count 컬럼을 아래에서 설명하는 과정에 따라 병합해주시면 됩니다.

확인해보니, 한 그리드안에 존재하는 가장 많은 카페 수는 7개네요.

앞서 설명드린 방식으로 사용자 여러분께서 원하는 요소의 가중치를 직접 줘보시면 어떨까요?

( 본 포스팅에서는 존재 여부를 기준으로 점수를 계산하였습니다 )

 

 

Pandas를 이용한 데이터 병합

위의 두 데이터는 같은 그리드에 관한 정보이지만 현재는 따로 존재하죠. 이 두 데이터를 

양쪽에 모두 존재하는 그리드 공간정보(the_geom)를 기준으로  하나로 병합해 봅시다.

Python pandas 라이브러리의 merge 함수를 이용한다면 SQL의 조인문을 사용하듯 두 데이터를 합칠 수 있습니다.

아래와 같이 두 데이터가 병합되었네요.

모든 요소에 대해 위 과정을 반복한 결과 아래와 같은 데이터를 얻을 수 있었습니다.

( 정제과정에서 불필요한 컬럼들은 테이블에서 제외하였습니다.)

아래의 절차대로 모든 요소의 점수를 더한 Sum 컬럼을 추가해주세요.

( pandas Series와 관련된 부분은 python의 관련 문서를 참조해주세요 ! )

잠깐 확인해 보니 가장 높은 점수가 6점 이네요.

SQL문을 지도에 매핑시키기

이제 각 요소의 위치 데이터와, 위에서 완성한 요소 포함 여부를 담고있는 그리드 데이터를 지도에 올려보도록 합시다.

 

요소 위치 데이터의 시각화

저희는  기존의 cartoframes에서 제공하는 기본 Map과 Layer 대신, 

좀 더 다양한 시각 효과를 사용하기 위해 cartoframes의 viz 패키지를 활용할 것이므로 이를 import 해주세요 ! 

먼저, Layer를 생성해야 해야하는데요  카토 계정에 존재하는 무인택배함 데이터의 위치를 yellow 색으로 나타내며, 마우스를 올렸을 때 (hover) 이름 (name컬럼)이 표시되도록 설정해주었습니다.

Map에 위의 Layer를 표시하도록 설정하시면

위와 같이 Map위에 Layer가 잘 올라간 것을 확인할수 있네요.

다른 요소 데이터도 마찬가지로 설정을 달리하여 Layer를 생성 후  Map에 올려주시면 되겠죠?

 

정제된 그리드 데이터의 시각화

위에서 완성한 데이터 프레임을 CartoContext.write 함수를 이용하여 계정에 업로드 해주세요.

성공적으로 완료되면, ‘able successfully written to CARTO: (계정주소)/(데이터명)’ 이라는 메시지를 확인하실수 있습니다!

 

이제, 생성된 데이터 프레임을 이용해서 SUM이 높은 그리드 일수록 색상이 진하게 표시되도록 시각화 해보도록 하죠.

Color 옵션에서 사용된 ramp는 어떤 데이터(어떤 범위로 나누어) 를, 어떤 색상등으로 매핑할 것인지를 지정해줍니다.

예를 들어, 

‘color: ramp(buckets($sum, [1,2]),[ yellow, green] )’

이는 sum 컬럼을 값 1,2인 범위로 나눠 각각을 yellow, green으로 매핑시키겠다는 뜻입니다.

( viz.Layer의 옵션 및 객체는 링크를 이용해서 더 자세히 확인하실수 있습니다! )

 

이를 활용해, 원하는 대로 옵션을 커스터마이징 해주세요.

 

위에서 생성한 Layer를 Map에 올려주면 아래와 같은 결과를 얻을 수 있네요.

 

이제 위의 Grid 레이어와 앞서 생성한 요소 레이어들을 하나의 맵에 올려주면 모든 시각화 과정이 끝나게 됩니다.

 

결론

결과 해석 

( 위 지도는 현재 cartoframes에서 publish 기능이 지원 예정 중이기에, 위의 분석 결과 지도를 토대로 위젯 기능 등을 추가하여 좀 더 편리하게 만든 것 임을 알려드립니다.)  

 

위의  데이터 정제 과정에서 데이터프레임에서 가장 높은 점수인 6점인 것을 확인했었습니다.

분석 지도를 데이터에 올린 결과, 6점에 해당하는 그리드들은 동작구, 송파구, 성북구, 광진구, 강서구에 존재했습니다. 

( 위치가 궁금하다면, 위 지도의 위젯 기능을 이용해서 해당 지역을 확인하실 수 있습니다 ! ) 

 

위의 맵을 통해 내가 살고있는 동네는 몇 점인지 알아보고, 

오늘 분석한 내용처럼 원하는 조건을 선정하여 나만의 맵을 만들어 보는 것은 어떨까요?