윈도우 기반 Geopandas 설치 및 좌표 변환
Geopandas 설치
윈도우 기반 Geopandas 설치 및 좌표 변환
Pandas를 많이 이용하게 되면서 분석 결과를 시각화할 때 차트는 파이썬에서, 공간시각화는 QGIS에서 주로 처리하는데 Geopandas 등 파이썬 기반의 공간시각화 사례들을 보면서도 모른 척 했던 건 Geopandas 등에서 지원되는 공간분석이나 시각화 방식이 아직은 QGIS나 PostGIS를 다 커버해주는 수준은 안되는 걸로 보였기 때문입니다. 하지만 지난 10월에 OSGeo 부산 세미나에서 전상환님의 Geopandas 실습 강좌를 듣고 나서 이후로도 몇 곳의 글들을 보고 기본적인 공간시각화 및 좌표계 변환은 물론 간단한 공간분석까지 가능한 것을 알고는 이제 더 미룰 수 없겠다는 생각이 들었습니다.
Geopandas 설치
하지만 나는 윈도우에서 Pycharm 기반으로 쓰고 있었는데 여기에 설치하는 것 자체가 쉽지 않았습니다. Geopandas와 관련된 라이브러리들을 설치하려니 일부는 WHL이라는 형태로 다운받아서 설치해야 하고, 의존하는 라이브러리들이 꽤 많고 버전도 맞아야 해서 반나절 하고 포기했습니다. 세미나에서의 실습은 Colaboratory에서 했는데 머신러닝 등을 이용해볼 수 있는 등 임시적인 가상머신 용도로도 좋고 구글드라이브 등과의 연동도 잘 되어 있으나, VM의 스토리지가 12시간 후에 초기화되는 제약이 있어 지속적으로 활용하기에는 조금 불편하다고 생각되어 아직 활용을 잘 못하고 있는 중입니다.
그런데 OSGeo 전임 회장님인 유병혁님이 또 Geopandas 글을 올린 것을 보면서 다시 한 번 도전해보기로 하고 Anaconda를 설치한 후 Anaconda Prompt에서 아래 구문 하나 실행했는데 너무나 쉽게 설치가 되어버렸습니다.....혹시나 바로 geopandas 실행이 잘 안되는 경우는 Anaconda 및 라이브러리 패키지들을 업데이트 해보시면 좋을 것 같습니다.
conda install -c conda-forge geopandas

Geopandas 설치시 함께 설치되는 라이브러리 패키지들
2020년 7월 기준 업데이트
geopandas나 관련된 패키지들이 업데이트되어서 그런지 최근에 새로운 장비에 설치하면서 한 번에 설치 못하고 시행착오를 겪었습니다. 정답은 아니나 관련된 내용을 적어 봅니다.
기존 패키지를 강제로 재설치할 경우
pip install — force-reinstall pyproj
구글링하다가 아래 URL의 설치 구문으로 성공
pip install wheel pip install pipwin
pipwin install numpy pipwin install pandas pipwin install shapely pipwin install gdal pipwin install fiona pipwin install pyproj pipwin install six pipwin install rtree pipwin install geopandas
공간데이터 로딩
Geopandas 홈페이지(http://geopandas.org/io.html)의의) Reading and Writing Files 메뉴를 보면 GDAL/OGR 기반이라서 Shape, GeoJson, GeoPackage(.gpkg) 등의 대부분의 Vector 공간데이터를 읽고 쓸 수 있다고 합니다. 이제 예제 Shp을 불러보겠습니다.
# Import geopandas
import geopandas as gpd
import fiona
# shapefile 읽기
gdf = gpd.read_file('../geodata/sido.shp', encoding='utf-8') #euc-kr, euckr, utf-8, cp949 중 한글이 보이는 것으로
# 정보 확인
#gdf.info()
gdf.head(2)

위의 속성에서 한글이 깨진 경우 read_file 코드에서 encoding을 uft-8과 euc-kr로 번갈아 시도해봅니다. 이제 데이터의 좌표계를 확인해보겠습니다.
좌표계 정의 및 변환
"좌알못"을 위한 좌표계 관련 설명
좌표계에 대한 설명은 여기를 참조해 주세요.
좌표계 확인
gdf.crs
{'init': 'epsg:5179'}
이 공간데이터는 다행히 좌표계가 잘 부여되어 있습니다. 이제 좌표계가 없는 경우에 정의하거나, 변환하는 방법을 알아보겠습니다.
좌표계 정의
데이터를 새로 하나 열어 보겠습니다.
gdf2 = gpd.read_file('../geodata/af0022_2016.shp', encoding='euc-kr') #euc-kr, euckr, utf-8, cp949 중 한글이 보이는 것으로
gdf2.crs
{'proj': 'tmerc',
'lat_0': 38,
'lon_0': 128,
'k': 0.9999,
'x_0': 400000,
'y_0': 600000,
'ellps': 'GRS80',
'units': 'm',
'no_defs': True}
뭔가 좌표계가 정의되어 있는데, EPSG 공식좌표계가 아닌 것 같습니다. 하나씩 찬찬히 살펴보면 tmerc는 TM도법, 128-38도를 원점으로, 40만-60만 미터를 가상이동시킨 좌표계라는 것을 알 수 있습니다. 위 링크의 좌표계 목록에서 찾아보면 KOTI에서 쓰고 있는 KATECH 좌표계임을 알 수 있습니다. 이 데이터는 세계측지계이므로 좌표변환을 해서 써도 문제가 없겠습니다.
데이터를 하나 더 열어 보겠습니다.
gdf3 = gpd.read_file('../geodata/F_FAC_BUILDING_11110_201911.shp', encoding='euc-kr') #euc-kr, euckr, utf-8, cp949 중 선택
gdf3.crs
{}
좌표계 정보가 없습니다. 기본 정보와 일부 데이터를 확인해보겠습니다.
len(gdf3)
25171
gdf4 = gdf3.sample(frac=0.1) #10% 샘플링
#gdf4.to_file('../geodata/bldg_sample.shp', encoding='euc-kr') #로딩시 인코딩을 동일하게 적용
gdf4.info()
gdf4.tail()
<class 'geopandas.geodataframe.GeoDataFrame'>
Int64Index: 2517 entries, 8949 to 14017
Data columns (total 27 columns):
UFID 2517 non-null object
BLD_NM 210 non-null object
DONG_NM 188 non-null object
GRND_FLR 2517 non-null int64
UGRND_FLR 2517 non-null int64
PNU 2517 non-null object
ARCHAREA 2517 non-null float64
TOTALAREA 2517 non-null float64
PLATAREA 2517 non-null float64
HEIGHT 2517 non-null float64
STRCT_CD 2196 non-null object
USABILITY 2196 non-null object
BC_RAT 2517 non-null float64
VL_RAT 2517 non-null float64
BLDRGST_PK 2196 non-null object
USEAPR_DAY 1671 non-null object
REGIST_DAY 1907 non-null object
GB_CD 2191 non-null object
VIOL_BD_YN 2196 non-null object
GEOIDN 2517 non-null object
BLDG_PNU 0 non-null object
BLDG_PNU_Y 0 non-null object
BLD_UNLICE 0 non-null object
BD_MGT_SN 2517 non-null object
SGG_OID 2517 non-null int64
COL_ADM_SE 2517 non-null object
geometry 2517 non-null geometry
dtypes: float64(6), geometry(1), int64(3), object(17)
memory usage: 550.6+ KB

Geometry 항목의 폴리곤 좌표를 보면 20만 50만 가상원점을 쓰면 TM좌표로 보여지만 이중 정확히 어느 것인지 알 수 없습니다.
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
mpl.rc('font', family='NanumGothic') #한글 폰트 적용시
plt.rcParams["figure.figsize"] = (20,10)
minx, miny, maxx, maxy = gdf4.geometry.total_bounds
#레이어 전체 boundary envelope 좌표
plt.rcParams["figure.figsize"] = (6,3)
f, ax = plt.subplots()
ax.set_xlim(minx - .1, maxx + .1) #X축
ax.set_ylim(miny - .1, maxy + .1) #Y축
print( round(minx + (maxx - minx)) , round(miny + (maxy - miny)) ) #레이어 중심좌표
#plt.plot([minx, maxx], [miny, maxy])
#plt.plot([maxx, minx], [miny, maxy])
#plt.show()
201965.0 458250.0
#%matplotlib inline
plt.rcParams["figure.figsize"] = (20,10)
gdf4.iloc[0]['geometry']

위의 과정에서 "The descartes package is required for plotting polygons in geopandas" 등과 같은 에러가 발생할 수 있습니다. 폴리곤 데이터를 표출(plotting)할 때 발생할 수 있고, 이 때에는 descartes(데카르트) 라이브러리를 설치한 후 다시 진행하면 됩니다.
conda install descartes
폴리곤의 모양과 좌표 범위, 속성 항목으로 유추해보면 건물정보로 보여지고, 건물에 건축물대장 속성을 결합하여 층수, 주차, 집합건물 등의 정보를 활용하거나 지적과 결합하여 이용할 수 있는 건물통합정보 또는 건물융합정보로 예상되며 이는 예전 한국좌표계인 EPSG 5174를 좌표계로 쓰고 있습니다. 해당 좌표계로 정의하고, 배경지도와 함께 띄워서 위치가 맞는지 확인해보겠습니다. EPSG 5174의 경우 한국좌표계이므로 EPSG 5174로 바로 정의하면 안되고, OSGeo에서 제공하는 매개변수를 붙인 커스텀 좌표계를 적용해야 합니다.
관련 자료 https://www.osgeo.kr/17
#좌표계를 부여. 좌표계 정보는 https://www.osgeo.kr/17 참조
import pyproj
from fiona.crs import from_epsg
gdf4.crs = '+proj=tmerc +lat_0=38 +lon_0=127.0028902777778 +k=1 +x_0=200000 +y_0=500000 +ellps=bessel +units=m +no_defs +towgs84=-115.80,474.99,674.11,1.16,-2.31,-1.63,6.43'
gdf4.crs
'+proj=tmerc +lat_0=38 +lon_0=127.0028902777778 +k=1 +x_0=200000 +y_0=500000 +ellps=bessel +units=m +no_defs +towgs84=-115.80,474.99,674.11,1.16,-2.31,-1.63,6.43'
**위에서 에러가 나는 경우, 저는 pyproj가 원인이었습니다. 깃허브의 pyproj를 통째로 내려받아 폴더명을 pyproj로 바꾸고(뒤의 -4801bc~를 지움), Anaconda3\Lib\site-packages에 덮어씌워줬더니 해결되었습니다. https://github.com/pyproj4/pyproj
%matplotlib inline
mpl.rc('font', family='NanumGothic') #한글 폰트 적용시
plt.rcParams["figure.figsize"] = (15,10)
gdf4.plot()

좌표계 변환
공간데이터의 좌표계를 4326으로 변환한 후, 배경지도 상에 띄워서 위치가 맞는지 보겠습니다.
gdf4_4326 = gdf4.to_crs(epsg=4326) #EPSG 4326 좌표계로 좌표 변환
minx, miny, maxx, maxy = gdf4_4326.geometry.total_bounds #바운더리 좌표 받기
print( (minx + (maxx - minx)) , (miny + (maxy - miny)) ) #레이어 중심좌표 확인
gdf4j = gdf4_4326.to_json() #Folium에서 쓰기 위해 geojson으로 변환
127.02303006749183 37.62659365705864
#배경맵을 뿌리기 위한 라이브러리 호출
import folium
#conda intall folium으로는 못찾고, pip install folium으로는 설치가 됩니다.
#%matplotlib inline
#mpl.rc('font', family='NanumGothic') #한글 폰트 적용시
plt.rcParams["figure.figsize"] = (10,5)
#맵 객체 설정
mymap = folium.Map(location=[37.628, 127.023], zoom_start=11, tiles='CartoDB positron', attr='Carto') #11은 서울시 전체가 보일 정도
folium.GeoJson(gdf4j).add_to(mymap) #맵에 geojson을 추가
#folium.LayerControl().add_to(mo) #맵에 레이어 컨트롤 추가
mymap #맵 표시 #display(mymap)

#만약 바로 지도가 표시되지 않는 경우 html로 저장 - 저장했다가 활용하고 싶은 경우에도
import webbrowser
url = './html/mymap01.html'
#webbrowser.open_new("./html/mymap01.html") 윈도우에서 익스플로러로 띄워짐
chrome_path = 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s'
webbrowser.get(chrome_path).open(url)
inline상에서는 ctrl 키를 누른 상태로 마우스 휠을 스크롤하면 지도가 확대/축소됩니다. (좌측 상단의 + / - 버튼을 이용해도 됩니다) 건물 형상이 보일 때까지 확대해보면 건물 위치가 맞는 것을 알 수 있어 좌표계 정의 및 변환이 잘 되었음을 알 수 있습니다.
공간연산, Dissolve, 단계구분도 등의 공간분석 및 시각화는 아래의 사이트를 참조하시면 좋습니다.
전상환님의 Geopandas 실습 코드
https://github.com/rollinstar/gpd_example
데이터 사이언스 스쿨 > 지리정보 데이터 처리
https://datascienceschool.net/view-notebook/ef921dc25e01437b9b5c532ba3b89b02/#Geoplot
메타데이터
- post_id
- e9b9ef16d9f9
- slug
- 윈도우-기반-geopandas-설치-및-좌표-변환-e9b9ef16d9f9
- url
- https://medium.com/@thlee33/%EC%9C%88%EB%8F%84%EC%9A%B0-%EA%B8%B0%EB%B0%98-geopandas-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%A2%8C%ED%91%9C-%EB%B3%80%ED%99%98-e9b9ef16d9f9
- canonical_url
- https://medium.com/@thlee33/%EC%9C%88%EB%8F%84%EC%9A%B0-%EA%B8%B0%EB%B0%98-geopandas-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%A2%8C%ED%91%9C-%EB%B3%80%ED%99%98-e9b9ef16d9f9
- author_url
- https://medium.com/@thlee33
- status
- ok
- fetched_at
- 2026-06-24 04:09:36