데이터 분석에서 거리 계산은 중요한 역할을 합니다. 특히, 지리적 위치를 기반으로 한 분석에서는 정확한 거리 계산이 필수적입니다. 이 글에서는 거리 기반 데이터 병합 방법에 대해 알아봅니다.
주요내용
- 📊 데이터 분석의 필수 요소인 거리 계산에 대해 배웁니다.
- 🌐 지리적 위치 데이터를 활용한 병합 기법을 소개합니다.
- 🛠️ pandas, scipy 등의 라이브러리 사용법을 익힙니다.
이 코드는 필요한 라이브러리를 불러오고, 경고 메시지를 숨기며, 현재 작업 경로를 파일 로드 경로로 설정하는 과정을 담고 있습니다. os와 pandas 라이브러리를 임포트하여 파일 시스템 작업과 데이터 처리 기능을 사용할 수 있게 합니다. warnings.filterwarnings(action = 'ignore')를 사용하여 불필요한 경고 메시지가 표시되지 않도록 설정합니다. 마지막으로, %pwd 매직 커맨드를 사용하여 현재 작업 경로를 얻고, os.chdir() 함수를 사용하여 이 경로를 파일 로드 경로로 설정합니다.
1
2
3
4
5
6
7
8
9
import os
import pandas as pd
# 불필요한 경고 표시를 생략합니다.
import warnings
warnings.filterwarnings(action = 'ignore')
a=%pwd # 현재 작업 경로를 변수 a에 할당합니다.
os.chdir(a) # 현재 작업 경로를 파일 로드 경로로 설정합니다.
-
아파트 가격 예측 등 ‘지역’이 포함되는 데이터 분석에서 주소나 위치 변수 등을 기준으로 거리가 가까운 레코드 및 관련 통계치를 통합해야 하는 경우가 있다.
-
이를 통합하는 방법은 보통 3단계를 거친다.
1) 각 데이터에 포함된 레코드 간 거리를 나타내는 거리 행렬을 생성
2) 거리 행렬의 행 or 열 기준 최소 값을 가지는 인덱스를 바탕으로 이웃한 데이터 탐색
3) 탐색한 이웃 데이터를 기존 데이터에 부착
-
서로 다른 주소값을 가진 2개의 데이터 테이블이 있다. (원본데이터의 주소값= A, B, C)
-
이때 각각 주소 A, B, C에 대응하는 주소 X, Y, Z간의 거리를 계산하는
거리행렬을 생성한다. -
각각의 주소 A, B, C와 가장 인접한
이웃 데이터를 탐색한 뒤, 해당 데이터를 원본데이터에 붙여넣는다.
관련 문법 1 : scipy.spatial.distance.cdist
-
두 개의 행렬을 바탕으로
거리행렬을 반환하는 함수 -
일반적인 머신러닝 모델을 만들 때, 오픈소스로 된 데이터를 쓰지 않고 실용적인 데이터를 만들 때 많이 사용된다.(특히 KNN)
-
데이터가 scipy 함수에 사용할 수 있는
연속형 변수이어야만 사용할 수 있다.
주요 파라미터
-
XA : 거리 행렬 계산 대상인 행렬 (ndarray / DataFrame),
함수의 출력 행이다. -
XB : 거리 행렬 계산 대상인 행렬 (ndarray / DataFrame),
함수의 출력 열이다. -
metric : 거리 척도 방식 선택 (‘cityblock’, ‘correlation’, ‘cosine’, ‘euclidean’, ‘jaccard’, ‘matching’ 등)
관련 문법 2 : ndarray.argsort
-
작은 값부터 순서대로 데이터의
위치(index)를 반환하는 함수입니다. 즉, 각 순위를 매기고 최소값을 갖게 만든 index가 무엇인지 찾게 해주는 함수입니다. -
주로
이웃을 찾을 때많이 활용됩니다. -
axis = 0이면
열 별 위치, axis = 1이면행 별 위치를 반환합니다. -
Tip. 하나의 값만을 찾는 것이 목적이라면 DataFrame의 idxmax(), idxmin() 함수를 사용하는 것이 더 유용합니다.
-
arr1 (1차원)의 경우 axis 파라미터가 적용되지 않습니다.
-
arr2 (2차원)의 경우 axis=0일 때, 첫 번째 열인 10, 7, 12를 예시로 보면 세 개의 수를 정렬하면 7 < 10 < 12가 됩니다.
-
기존 7의 인덱스 값은 1이 argsort(axis=0)의 결과로 출력됩니다.
-
나머지도 동일한 방식으로 적용되어 우측의 결과값으로 나타납니다.
거리기반 데이터 병합 실습
단계별로 생각해 봅시다.
2019년 서울 아파트 거래가 & 주소 데이터에 지하철 역 별 위도 / 경도 데이터를 활용해서 가장 가까운 역이 어디인지 파악
Pandas 라이브러리의 read_csv 함수를 사용하여 2019년 서울 아파트 매매 실거래가와 서울시 아파트 주소 데이터를 불러옵니다. 한글 데이터의 경우 글자가 깨지는 것을 방지하기 위해 encoding 파라미터에 "cp949"를 지정합니다. 이 과정을 통해 두 개의 데이터프레임 df1과 df2가 생성됩니다.
1
2
3
4
# 아파트 관련 데이터 불러오기
# 한글 자료이므로, 글씨 깨짐 방지위해 cp949로 인코딩한다.
df1 = pd.read_csv("2019년_서울_아파트매매_실거래가.csv", encoding = "cp949")
df2 = pd.read_csv("2019년_서울시_아파트주소.csv", encoding = "cp949")
df1.head() 함수는 데이터프레임 df1에서 상위 5개 행을 반환합니다. 이 함수는 데이터의 구조를 빠르게 파악하고자 할 때 유용하게 사용됩니다.
1
df1.head() # 데이터프레임 df1의 상위 5개 행을 출력합니다.
df2.head() 함수는 데이터프레임에서 처음 5개의 행을 반환합니다. 이 함수는 데이터의 구조를 빠르게 확인하고자 할 때 유용하게 사용됩니다.
1
df2.head() # 데이터프레임의 처음 5개 행을 보여줍니다.
step1. 두 개의 데이터를 이어 붙인다.
단계별로 생각해 봅시다.
이 코드는 두 데이터프레임 df1과 df2를 병합하는 과정을 보여줍니다. pd.merge() 함수를 사용하여, df1의 ‘법정동’, ‘도로명’, ‘아파트’ 컬럼과 df2의 ‘읍면동명’, ‘도로명’, ‘건물명’ 컬럼을 기준으로 데이터를 병합합니다. 이때, 병합될 컬럼의 순서와 이름이 서로 일치해야 합니다. 결과적으로, 이 과정은 두 데이터셋에서 관련된 정보를 결합하여 새로운 데이터프레임 df를 생성합니다.
1
2
3
4
5
6
# 데이터 병합
# 병합될 컬럼의 순서가 일치해야 merge() 함수가 적용된다.
# '법정동'은 '읍면동명'으로, '도로명'은 동일하게, '아파트'는 '건물명'으로 각각 매칭하여 병합한다.
df = pd.merge(df1, df2, left_on = ['법정동', '도로명', '아파트'], right_on = ['읍면동명', '도로명', '건물명'])
df
문제 상황인 가장 가까운 지하철역을 찾기 위해 위치 계산을 할 대상 데이터를 불러온다.
이 함수는 pandas 라이브러리의 read_excel 메서드를 사용하여 ‘지하철역_위경도.xlsx’ 파일을 읽고, 이를 DataFrame 객체로 변환합니다. 이 과정을 통해, 지하철역의 위도와 경도 정보가 포함된 엑셀 파일의 데이터를 분석 및 처리할 수 있는 형태로 불러옵니다.
1
df3 = pd.read_excel("지하철역_위경도.xlsx") # '지하철역_위경도.xlsx' 파일을 읽어서 DataFrame으로 변환합니다.
df3.head() 함수는 데이터프레임 df3에서 상위 5개 행을 반환합니다. 이 함수는 데이터의 초기 부분을 빠르게 검토할 때 유용하며, 기본적으로 처음 5개의 행을 출력하지만, 괄호 안에 다른 숫자를 지정하여 출력할 행의 수를 조정할 수 있습니다.
1
df3.head() # 데이터프레임 df3의 상위 5개 행을 출력합니다.
df.info() 함수는 데이터프레임의 기본 정보를 출력합니다. 이 함수는 데이터프레임에 포함된 열의 수, 각 열의 데이터 타입, 비어 있지 않은 값의 수, 그리고 메모리 사용량을 포함한 정보를 제공합니다. 이는 데이터 분석을 시작하기 전 데이터의 구조를 이해하는 데 유용합니다.
1
df.info() # 데이터프레임의 기본 정보를 출력합니다.
df3.info() 함수는 DataFrame df3의 요약 정보를 출력합니다. 이 함수는 데이터의 각 열에 대한 정보를 포함하여, 열의 이름, 비어 있지 않은 값의 개수, 각 열의 데이터 타입 등을 보여줍니다. 또한, 메모리 사용량에 대한 정보도 제공합니다.
1
df3.info() # DataFrame 'df3'의 정보를 출력합니다.
step2. 거리 행렬 계산 (scipy.spatial.distance import cdist)
단계별로 생각해 봅시다.
이 문서는 위경도 좌표를 사용하여 두 지점 간의 거리를 계산하기 위한 haversine 모듈의 설치 방법을 설명합니다. 사용자는 필요에 따라 이 모듈을 설치할 수 있으며, 설치 후에는 지리적 좌표를 기반으로 한 거리 계산을 수행할 수 있습니다.
1
# 위경도 거리 계산을 위한 모듈 설치(필요시 설치)
본 코드는 데이터프레임에서 경도와 위도 컬럼을 추출하여 거리 행렬을 생성하기 위한 준비 작업을 수행합니다. 두 개의 데이터프레임 df와 df3에서 각각 ‘경도’와 ‘위도’ 컬럼을 선택하여 새로운 데이터프레임 df_location과 df3_location을 생성합니다. 이후, 지구상의 두 지점 간 거리를 계산할 때는 유클리드 거리나 맨해튼 거리 대신 haversine 거리를 사용하는 것이 일반적임을 언급합니다. 이는 haversine 공식이 지구의 곡률을 고려하여 두 지점 간의 거리를 보다 정확하게 계산하기 때문입니다.
1
2
3
4
5
6
7
# 거리 행렬 생성을 위한 컬럼 추출
df_location = df[['경도', '위도']]
df3_location = df3[['경도', '위도']]
# 지구상의 위경도 거리를 구할 때는 유클리드 거리나 맨해튼 거리 사용보다는 haversine 거리를 사용하는 것이 일반적입니다.
이 문서는 scipy.spatial.distance.cdist 함수와 haversine 라이브러리를 사용하여 두 위치 집합 간의 거리 행렬을 계산하는 방법을 설명합니다. cdist 함수는 두 배열 간의 거리를 계산하며, metric 파라미터를 통해 다양한 거리 측정 방법을 지정할 수 있습니다. 여기서는 haversine 메트릭을 사용하여 지구상의 두 지점 간의 거리를 계산합니다. 이는 특히 위도와 경도를 기반으로 한 위치 데이터에 유용합니다.
1
2
3
4
5
6
7
8
9
# 거리 행렬 생성
from scipy.spatial.distance import cdist
from haversine import haversine
# cdist(행, 열) 함수를 사용해 거리를 계산합니다.
# metric= 에 들어갈 수 있는 것들: ['euclidean', 'cityblock', 'jaccard'] (기본적으로 내장된 것들)
# 또는 haversine처럼 외부 패키지를 설치하고 사용할 수도 있습니다.
dist_mat = cdist(df_location, df3_location, metric = haversine)
1
step3. argsort()를 적용해 이웃 지역 탐색 후 병합
이 코드는 데이터프레임 df에 가장 가까운 지하철 역과 그 거리를 새로운 컬럼으로 추가합니다. 먼저 dist_mat.argsort()[:, 0]를 사용하여 각 위치에서 가장 가까운 지하철 역의 인덱스를 찾습니다. 이 인덱스를 사용하여 df3에서 해당 역의 이름을 가져와 df의 ‘가까운역’ 컬럼에 할당합니다. 마지막으로, 각 위치에서 가장 가까운 지하철 역까지의 거리를 df의 ‘가까운역까지_거리’ 컬럼에 할당합니다. 이 과정에서 .values를 사용하여 df3.iloc[...]의 결과로부터 값 배열을 직접 추출함으로써 인덱스 충돌을 방지합니다.
1
2
3
4
5
close_subway_index = dist_mat.argsort()[:, 0] # axis = 0에 따라 정렬
df['가까운역'] = df3.iloc[close_subway_index]['역명'].values # '가까운역' 컬럼에 가장 가까운 역명 할당
df['가까운역까지_거리'] = dist_mat[close_subway_index][:, 0] # '가까운역까지_거리' 컬럼에 거리 할당
이 함수는 DataFrame에서 특정 행을 선택하는 데 사용됩니다. 여기서 df3.iloc[close_subway_index]는 df3 DataFrame에서 close_subway_index에 해당하는 행을 선택합니다. iloc 메서드는 위치 기반 인덱싱을 사용하여 데이터를 선택할 때 사용됩니다.
1
2
# df3.iloc[close_subway_index]에서 df3은 DataFrame을 나타내며, .iloc[]는 행 위치를 기반으로 데이터를 선택하는 데 사용됩니다.
# close_subway_index는 가까운 지하철역의 인덱스를 나타냅니다.
df.head() 함수는 데이터프레임에서 처음 다섯 행을 반환합니다. 이 함수는 데이터의 구조를 빠르게 파악하고자 할 때 유용하게 사용됩니다.
1
df.head() # 데이터프레임의 처음 다섯 행을 출력합니다.
댓글