2026.02.01 - [GIS/01. GIS TIL] - GIS 분석을 위한 환경설정(with conda, uv)
GIS 분석을 위한 환경설정(with conda, uv)
Geospatial 데이터를 다루는 유튜브에서 OpenSource Geospatial 전문가 유튜버의 영상을 자주 시청했다. 몇 달 전에 전자책을 발매하셨는데 이번에 한글판이 배포되어서 25달러를 지불하고 구매해봤다.파
dalleeoppaa.tistory.com
이전 글에서는 파이썬에서 GIS 분석을 위한 환경설정을 알아봤고 이번 글에서는 본격적으로 벡터 데이터를 다루기 위한 GeoPandas에 대해서 알아보자.
1️⃣ GeoPandas란?
1-1. 소개
파이썬에서 Geospatial 데이터를 다루기 위해 개발된 라이브러리인 GeoPandas는 우리가 익히 알고있는 pandas 인터페이스와 비슷하며, 추가로 지리공간 연산을 원활하게 수행할 수 있도록 개발되었다. 주요 기능으로는 다음과 같다.
- 통합 데이터 모델 : 단일 데이터 구조에서 지리공간 처리를 위한 기하학적 모양과 그 속성을 함께 저장
- 공간 연산 : 거리, 교차점, 버퍼 및 기타 기하학적 관계를 계산
- 좌표 시스템 관리 : 다양한 지도 투영과 좌표 참조 시스템 처리
- 다중 형식 지원 : Shapefile, GeoJson, GeoPackage 등 공간정보 데이터의 표준 형식을 읽고 쓰기가 가능
- 시각화 통합 : 간단한 pandas 스타일 플롯 메서드로 Matplotlib을 사용한 지도 시각화
1-2. GeoDataFrame, GeoSeries 차이점
`GeoDataFrame`은 pandas의 DataFrame이라고 생각하면 된다. 테이블 형태로 데이터를 표현하고, 공간 속성을 나타내는 `geometry` 컬럼을 추가로 가지고 있다. 이 `geometry` 컬럼은 point(ex. GPS 좌표), line(ex. 강이나 도로), polygon(ex. 구역, 건물 형상)을 포함할 수 있다.
`GeoSeries`는 GeoDataFrame 내의 기하학적 데이터를 다룬다. GeoDataFrame으로 작업을 수행하지만, 내부적으로는 GeoSeries가 실제 기하학적 연산을 관리한다고 생각하면 된다.

2️⃣ GeoPandas 실습
2-1. GeoPandas 설치, GeoDataFrame 생성
geopandas와 pygis를 설치하고 import 해주면 된다.
pip install geopandas pygis
import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt
점 데이터(좌표 데이터)를 생성해보자. `gpd.points_from_xy()` 함수는 경도(x)와 위도(y) 열에서 기하학을 생성하는 메서드이다.
# 도시의 중심점을 좌표데이터로 생성
data = {
"City" : ["Tokyo", "New York", "London", "Paris"],
"Latitude": [35.6895, 40.7128, 51.5074, 48.8566],
"Longitude": [139.6917, -74.0060, -0.1278, 2.3522]
}
# 일반 pandas dataframe 생성
df = pd.DataFrame(data)
# 좌표에서 Point 기하학을 생성하여 GeoDataFrame으로 변환
gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df.Longitude, df.Latitude))
2-2. 데이터 불러오기
지리공간 데이터 형식에는 대표적으로 3가지가 있습니다.
- `GeoJson` : Json 형식으로 웹페이지에 데이터를 올리거나 사람이 읽기 쉬운 형태
- `Shapefile` : 전통 GIS 형식으로 여러 파일(ex. `.shp`, `.shx`, `.dbf`, `.prj` 등)로 구성됨.
- `GeoPackage` : 현대적이고 단일 파일 형식으로 여러 레이어와 데이터 유형 저장이 가능함
간단하게 GeoJson 파일을 불러오는 실습을 해보자.
# opengeos의 github에 저장된 샘플 벡터데이터 파일 경로
url = "https://github.com/opengeos/datasets/releases/download/vector/nybb.
geojson"
gdf = gpd.read_file(url)
gdf.head()

2-3. 데이터 저장하기
GeoPandas는 데이터를 간단하게 저장할 수 있도록 설계되었으며 여러 출력 형식을 지원한다.
output_file = "nyc_boroughs.geojson"
gdf.to_file(output_file, driver="GeoJSON")
print(f"GeoDataFrame이 {output_file}에 저장되었습니다")
2-4. 좌표 시스템과 재투영
실세계의 형상은 복잡한 지구 위에 3차원 형태로 존재한다. 이런 형상을 2D 지도에 표현하거나 컴퓨터가 읽을 수 있도록 변환하기 위해서는 좌표시스템을 적용해야 한다.
2025.10.27 - [GIS/01. GIS TIL] - [GIS] 좌표계, 타원체 예제로 쉽게 이해하기(EP.1)
[GIS] 좌표계, 타원체 예제로 쉽게 이해하기(EP.1)
1️⃣ 갑자기..네이버 인턴 합격!네이버 지도 체험형 인턴십 서류를 패스하고, 저번 주 금요일에 화상 면접을 봤다.그리고 주말이 지난 오늘..토익스피킹 수업을 듣고있는데 갑자기 한 통의 메세
dalleeoppaa.tistory.com
2025.10.28 - [GIS/01. GIS TIL] - [GIS] 투영법, EPSG코드 쉽게 이해하기 (EP.2)
[GIS] 투영법, EPSG코드 쉽게 이해하기 (EP.2)
2025.10.27 - [GIS] - [GIS] 좌표계, EPSG코드 예제로 쉽게 이해하기(EP.1) [GIS] 좌표계, 타원체 예제로 쉽게 이해하기(EP.1)1️⃣ 갑자기..네이버 인턴 합격!네이버 지도 체험형 인턴십 서류를 패스하고, 저
dalleeoppaa.tistory.com
좌표계와 EPSG코드에 관련된 내용은 이전에 작성한 글에 자세히 작성했습니다. 이전 글을 참조해주세요
그렇다면 GeoDataFrame에서 좌표계를 확인하는 방법에 대해 알아보자. `.crs`를 사용하면 좌표계를 출력한다.
print(f"현재 CRS: {gdf.crs}")

해당 데이터셋은 뉴욕 지역을 위해 설계된 `EPSG:2263`이다. 측정값이 피트로 되어있기 때문에 다양한 좌표 시스템으로 재투영해보자.
# 전역 호환성을 위해 WGS84 (위/경도)로 재투영
gdf_4326 = gdf.to_crs(epsg=4326)
print(f"Reprojected CRS : {gdf_4326.crs}")
print("="*60)
display(gdf_4326.head())

`EPSG:4326`으로 재투영한 결과 `geometry`컬럼의 값이 도(degree) 단위로 표현된다.
2-5. 공간 측정 및 분석
(1) 면적 계산
GeoPandas를 사용하는 이유 중 하나는 공간 연산이 가능하기 때문이다. `geometry`컬럼을 통해서 공간 연산을 수행해보자.
먼저 미터 단위 계산을 수행하기 위해 다시 투영을 해보자. 이번에는 웹 메르카토르 표준 형식인(EPSG:3857)을 적용한다.
참고로 `EPSG:3867`은 지도 서비스를 하는 대부분의 회사에서 표준으로 사용하는 좌표계 타입이다.
| 서비스 | 사용 여부 | 비고 |
| Google Maps | ✅ 사용 | 웹/모바일 맵에서 기본 좌표계 |
| OpenStreetMap (OSM) | ✅ 사용 | 거의 모든 타일 서버가 Web Mercator를 기본으로 제공 |
| Bing Maps | ✅ 사용 | Microsoft 지도 서비스도 Web Mercator 기반 |
| Mapbox | ✅ 사용 | Web Mercator 기반 타일만 제공 |
| Carto / CartoDB | ✅ 사용 | 주요 웹 맵 좌표계로 채택 |
| 네이버 지도 (Naver Maps) | ✅ 사용 가능 | 세계 지도/타일 타입에서 EPSG:3857 지원 |
| VWorld | ✅ 사용 | Web Mercator 기반 서비스 제공 (국토부 공간정보) |
| ArcGIS Online (Esri) | ✅ 사용 | 기본 베이스맵 Web Mercator 기반 |
| Leaflet 라이브러리 기본 타일들 | ✅ 대부분 Web Mercator | 기본 CRS가 EPSG:3857 |
# 제곱미터 단위의 정확한 면적 계산을 위해 웹 메르카토르로 재투영
gdf = gdf.to_crs(epsg=3857)
# 빠른 연산을 위해 BoroName을 인덱스로 설정
gdf = gdf.set_index("BoroName")
print(f"현재 crs : {gdf.crs}")

먼저 각 BoroName(뉴욕 자치구)별로 면적을 계산한 결과 Queens가 가장 넓었으며, Brooklyn, Staten Island, Bronx, Manhattan 순으로 큰 면적 계산 결과를 확인할 수 있다.
# 제곱미터 단위로 면적 계산
gdf["area"] = gdf.area
# 더 읽기 쉬운 단위로 변환 (제곱킬로미터)
gdf["area_km2"] = gdf["area"] / 1_000_000
# 면적순으로 정렬
gdf[['area', 'area_km2']].sort_values("area_km2", ascending=False)

(2) 거리 계산
GeoPandas는 `geometry` 컬럼에서 다양한 기하학적 표현을 추출할 수 있는 메서드가 포함되어 있다. 폴리곤에서 경계선과 중심점을 추출하고 각 자치구별 중심점과의 거리를 계산해보자
# 폴리곤에서 경계선 추출
gdf['boundary'] = gdf.boundary
# 폴리곤의 중심점 계산
gdf['centroid'] = gdf.centroid
# 경계선과 중심점 확인하기
gdf[['boundary', 'centroid']].head()

# 맨하탄의 중심점을 기준점으로 사용
manhattan_centroid = gdf.loc['Manhattan', 'centroid']
# 각 자치구의 중심점에서 맨하탄 중심점까지의 거리 계산
gdf['distance_to_manhattan'] = gdf['centroid'].distance(manhattan_centroid)
# km 단위로 변환
gdf['distance_to_manhattan_km'] = gdf['distance_to_manhattan'] / 1000
gdf[["distance_to_manhattan_km"]].sort_values("distance_to_manhattan_km")

2-6. 통계 분석
geopandas는 pandas와 동일하게 통계 분석을 위한 메서드 사용이 가능하다.
# 요약 통계 계산
mean_distance = gdf["distance_to_manhattan_km"].mean()
max_distance = gdf["distance_to_manhattan_km"].max()
total_area = gdf["area_km2"].sum()
print(f"맨해튼까지의 평균 거리: {mean_distance:.2f} km")
print(f"맨해튼까지의 최대 거리: {max_distance:.2f} km")
print(f"NYC 총 면적: {total_area:.2f} km²")

3️⃣ 지도 시각화
GeoPandas는 Matplotlib과 통합되어 지도 시각화가 가능하다. 분석한 내용을 표현하는 다양한 방법 중에 지도 시각화 표현은 다른 사람의 이해를 돕는데 큰 역할을 하기 때문에 지도 시각화를 잘 표현한다면 의사결정에 큰 도움이 된다.
3-1. 등치 지역도 시각화
import matplotlib.pyplot as plt
# 한국어 깨짐 방지를 위해 폰트 설정(mac os기준)
plt.rc('font', family='AppleGothic')
# - 기호 깨짐 방지
plt.rcParams['axes.unicode_minus'] = False
# 고해상도 설정
plt.rcParams["figure.dpi"] = 150
# 뉴욕 자치구 면적을 보여주는 등치 지역도 생성
fig, ax = plt.subplots(figsize=(10, 6))
gdf.plot(
column='area_km2', # 어떤 컬럼을 기준으로 색상을 표현할지 설정
ax=ax, # ax라는 기본 배경에 해당 지도를 시각화
legend=True, # 범례 생성
cmap='YlOrRd', # 컬러 지정
edgecolor='black', # 테두리 색상 설정
linewidth=0.5 # 테두리 두께 지정
)
plt.title("NYC Boroughs by Area(km2)", fontsize=16, fontweight="bold")
plt.axis("off")
plt.tight_layout()
plt.show()

생성된 등치지역도는 자치구별 면적을 기준으로 색상 표현이 되었으나, 여기서 추가로 각 자치구의 중심점에 자치구 이름을 표현해보자
# 자치구별 면적을 색상으로 구분
fig, ax = plt.subplots(figsize=(4, 4))
gdf.plot(
column='area_km2',
ax=ax,
legend=True,
cmap='YlOrRd',
edgecolor='black',
linewidth=0.5
)
# 중심점을 점 레이어로 추가
gdf['centroid'].plot(
ax=ax,
color='red',
markersize=20,
edgecolor='darkred',
linewidth=1
)
# 자치구 라벨 추가하기
for idx, row in gdf.iterrows():
x = row.centroid.x
y = row.centroid.y
ax.annotate(
idx,
(x, y),
xytext=(3,3),
textcoords="offset points",
fontsize=8,
fontweight="bold",
bbox=dict(boxstyle="round,pad=0.3", facecolor="white", alpha=0.8)
)
plt.title("NYC Boroughs by Area(km2)", fontsize=12, fontweight="bold")
plt.axis("off")
plt.tight_layout()
plt.show()

Folium 맵을 사용하면 정적 지도가 아닌 동적 지도 생성이 가능하다. 줌 인&아웃이 가능하며, 마우스 이동에 따라서 지도 이동도 가능하다.
또한 `tooltip`과 `popup`을 통해서 마우스 커서를 객체에 올리면 팝업창에 정보가 표현된다.
m = gdf.explore(
column='area_km2',
cmap='YlOrRd',
tooltip=['area_km2', 'distance_to_manhattan_km'],
popup=True,
legend=True
)
m


'GIS > 01. GIS TIL' 카테고리의 다른 글
| [GIS] Python에서 TileDB 사용하여 LiDAR 데이터 활용하기 (0) | 2026.03.21 |
|---|---|
| 파이썬에서 Rasterio 기반 래스터 데이터 다루기 (0) | 2026.02.03 |
| GIS 분석을 위한 환경설정(with conda, uv) (0) | 2026.02.01 |
| PostGIS 공간쿼리 기초 연습 (2) (0) | 2026.01.30 |
| PostGIS 공간쿼리 기초 연습 (1) (0) | 2026.01.29 |
