단순 방문자 수/신규 유저만큼 중요하며, 서비스 만족도와 장기 성장성을 가늠하는 핵심 지표
2. 클래식 리텐션
특정 기준일 이후 n일차에 얼마나 많은 사용자(%)가 재방문했는지를 계산하는 방식
단순하면서 가장 많이 쓰이는 리텐션 측정법
장점 1) 계산이 단순하고 명확 2) 매일 접속이 중요한 서비스(SNS, 메신저)에 적합
단점 1) 사용 주기가 긴 서비스(여행 앱, 부동산)에서는 부적합
3. 롤링 리텐션
사용자가 이탈하지 않고 여전히 서비스에 남아 있는가에 초점을 둔 리텐션 지표
기준일을 포함하여 그 이후에 한 번이라도 재방문한 유저의 비율 → 마지막 방문일 이전은 방문한 것으로 간주
장점 1) 사용 주기가 긴 서비스(여행, 부동산, 쇼핑)에서 유용 2) 짧은 재방문일을 요구하지 않으므로 사용자 행동을 넓게 반영 3) 단기 방문 여부보다 사용 지속 여부를 파악하는 데 적절
단점 1) 계산이 과대 추정될 수 있음
4. 범위 리텐션
클래식 리텐션을 구간 단위로 확장한 리텐션 지표
클래식 리텐션은 특정 일/주/월 단위로 한정짓는 느낌이라면 범위 리텐션은 구간을 유연하게 나눈다는 점만 다름
장점 1) 노이즈에 강함: 하루만 안 써도 리텐션이 떨어지는 클래식 방식과 달리 구간 내 한 번만 방문해도 유지로 봄 2) 서비스 사용 주기(여행, 부동산, 쇼핑)가 긴 경우 유리: 하루 방문 없다고 리텐션이 급락하는 걸 완화
단점 1) 구간 설정에 유의해야 함
5. Stickiness(사용자 고착도)
사용자가 서비스에 얼마나 자주 방문하고 '딱 붙어있는지' 나타내는 지표
사용자 고착도는 활성 사용자 비율로 계산 [구성 요소] 1) DAU(Daily Active Users): 일간 활성 사용자 수 → 하루 동안 활동한 고유 활성 사용자 수 ex) 1월 1일 동안 로그인/행동한 사용자 A, B, C가 있다면 → DAU(1월 1일) = 3명 2) WAU(Weekly Active Users): 주간 활성 사용자 수 → 최근 7일 동안 활동한 고유 활성 사용자 수 ex) 1월 7일 기준으로 1월 1~7일 중에 활동한 사용자들의 고유 수 3) MAU(Monthly Active Users): 월간 활성 사용자 → 최근 30일 동안 활동한 고유 활성 사용자 수 ex) 1월 31일 기준으로 1월 1~31일 동한 활동한 사용자들의 고유 수
높은 값일수록 사용자가 자주 다시 방문하고 있다는 의미
Stickiness(DAU/WAU) = 1/7 ≈ 14%
# 주간 사용자 중 14%만이 날짜에 활동했다는 뜻
Stickiness(DAU/WAU) = 7/7 = 100%
# 주간 사용자 모두 매일 서비스 활동했다는 뜻
이 세 가지 지표로 고객을 점수화하고, 그 점수를 기반으로 고객을 여러 군집(segment)으로 나누어 각 세그먼트에 적절한 마케팅 전략을 수립
2. 실제 서비스 적용
분석 대상 기간 설정이 분석 목적에 따라 중요
각 지표별 점수 분포를 보고 적절한 컷오프를 정함
RFM 결과만으로 끝내지 않고, 그룹별 행동 패턴(예: 이탈확률, 재구매율 등)을 함께 보기
각 비즈니스 모델/상품군마다 고객 구매패턴이 다르므로 R, F, M의 의미가 달라질 수 있다는 점 염두
→ 고객수, 구매패턴이 산업이나 서비스마다 다르므로 도메인에 따른 맞춤형 기준 설정 필요
3. 회고
학부 때 R, SPSS로 RFM 분석을 '분석 기법이 하나'로 바라보았다면, 실무를 접하고, 강의를 수강하는 지금은 세그먼트 → 마케팅 액션 → 성과 측정까지 이어지는 전체 흐름이 중요하다는 것을 느낀다. 학부 때는 단순히 RFM 스코어를 도출하는 데 집중했다면, 이제는 이 결과를 '비즈니스적으로 어떻게 활용할 것인가?'라는 고민을 하게 되는 것 같다.
Seaborn의 많은 시각화 함수들은 판다스 DataFrame과 잘 통합되어 있다. 이들 시각화 함수들은 X축과 Y축 각각에 DataFrame을 컬럼명을 입력받아서 처리할 수 있도록 설계되어 있다. 이를 위해 대부분의 시각화 함수들은 data, x, y를 각각 인자로 가지는데, data 인자는 시각화 대상 DataFrame 객체, x 인자는 X축에 사용될 컬럼명, y 인자는 Y축에 사용될 컬럼명을 입력받는다.
Seaborn은 Axes level, Figure level 함수로 나뉘어져 있다. - Axes level은 matplotlib의 axes에 plotting을 하는거라 matplotlib 메서드로 커스터마이징 가능하다. → matplotlib에서 사용했던 그래프 크기를 조정하는 plt.figure(figsize=(10,6))이 가능하다.
- Figure level은 seaborn 독자적인 figure를 만들어서 거기에 plotting을 한다. 그러므로 Figure level은 facetgrid(seaborn의 figure)를 통해서 커스터마이징이 가능하다. 즉, matplotlib API 사용을 최소화하고, 기본 matplotlib에서 사용하는 기능들을 Figure level 함수의 인자 등으로 대체하게 설계되었다. → matplotlib에서 사용했던 그래프 크기를 조정하는 plt.figure(figsize=(10,6))이 불가능하고, 그래프를 그리는 함수 내 인자로 조정해야 한다.
※ Figure level 함수를 사용할 경우 새로운 API에 적응을 해야하기 때문에 우리는 matplotlib을 기본적으로 알고있으므로 Axes level 함수를 사용하는게 효율적이다.(하단 히스토그램 part에서 둘의 차이를 확인하고, 그 이후에 나오는 차트들은 Axes level 함수만 다룬다.)
정보의 종류에 따른 시각화 차트 유형
1) 히스토그램
연속형 값에 대한 도수 분포를 나타낸다. X축 값은 도수 분포를 원하는 연속형 값의 구간, Y축 값은 해당 구간의 도수 분포를 나타낸다.
2) 바 플롯(막대 그래프)
특정 컬럼의 범주형 값에 따른 다른 컬럼의 연속형 값(평균, 총합 등)을 막대 그래프 형태로 시각화한다.
3) 박스 플롯(상자 수염 그래프)
연속형 값의 사분위 IQR과 최대, 최소, 이상치 값을 시각화한다. 보통 단일 컬럼의 연속형 값에 적용하지만, 이 연속형 값의 사분위를 다른 컬럼의 범주형 값별로 시각화할 때 사용할 수 있다.
4) 바이올린 플롯
히스토그램의 연속 확률 분포 곡선과 박스 플롯을 바이올린 형태로 함께 시각화한다. 보통 단일 컬럼의 연속형 값에 적용하지만, 이 연속형 값의 분포를 다른 컬럼의 범주형 값별로 시각화할 때 유용하다.
5) 스캐터 플롯(산점도)
산점도로 불리며 2개의 연속형 값들을 X, Y 좌표상의 점으로 시각화하여 해당 값들이 어떻게 관계되어 있는지 나타낸다.
6) 상관 히트맵
다수의 연속형 컬럼들에 대해서 상호 간의 상관 관계를 시각화한다.
히스토그램
히스토그램은 막대 차트처럼 보이지만 연속형 값을 범위 또는 구간으로 그룹화해 개별 구간에 해당되는 데이터의 건수를 시각화해준다.
Seaborn 히스토그램은 초기에는 distplot() 함수를 사용했지만 기능 개선 등의 이유로 현재는 deprecated된 상태이며, 이제 histplot() 또는 displot() 함수 사용을 권장하고 있다.
히스토그램은 기본적으로 한 개의 변수만 시각화하므로 y 인자는 생략한다. bins 인자는 구간 개수를 설정할 수 있으며, kde 인자는 연속 확률분포 곡선을 나타낼지 여부를 설정할 수 있다.
histplot
import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(8,4))
sns.histplot(x='Age', data=titanic_df, bins=30, kde=True)
plt.show()
displot
# Figure level 함수는 plt.figure()로 Figure의 크기를 조절 할 수 없음
# 아래에 변하지 않는 그래프
plt.figure(figsize=(8,4))
sns.displot(x='Age', data=titanic_df, bins=30, kde=True)
plt.show()
# Figure 크기를 조절하기 위한 인자로 height, aspect 사용
# height는 세로의 크기 / aspect는 가로와 세로의 배율
# width와 같은 별도의 가로 크기를 설정하는 인자는 제공되지 않고, height * aspect를 적용하여 자동으로 가로의 크기가 결정
# ex) height가 4이고 aspect가 2인 경우, 가로 크기는 4*2=8로 주어짐
sns.displot(x='Age', data=titanic_df, bins=30, kde=True, height=4, aspect=2)
plt.show()
히스토그램이나 박스 플롯이 별도로 존재하기 때문에 굳이 바이올린 플롯까지 활용할 필요가 없다고 생각할 수 있지만 boxplot() 함수와 유사하게 violinplot() 함수는 여러 범주형값별로 여러 개의 바이올린 플롯들을 그릴 수 있다. 이는 여러 범주형값별로 여러 개의 히스토그램 연속 확률 분포 곡선들을 그려 줄 수 있는 장점을 가지고 있다.
hue 인자를 사용하여 시각화 정보를 추가적으로 세분화 할 수 있다. 추가적으로 histplot() 함수도 hue 기능을 제공하지만 그보다는 vilolinplot() 함수가 특정 범주형값에 해당하는 연속형 값의 데이터 분포도를 훨씬 더 효과적으로 시각화해주기 때문에 데이터 분석 시 활용도가 높다.
heatmap() 함수는 인자로 컬럼들 간의 상관계수를 가지는 DataFrame을 입력받아야 시각화가 가능하다. 판다스 DataFrame의 corr() 메서드를 호출하면 간단하게 상관계수를 가지는 DataFrame을 생성할 수 있다. corr() 메서드는 연속형 컬럼들의 상관계수만 계산하여 상관계수 DataFrame으로 생성한다.
corr_df = titanic_df.corr()
corr_df
sns.heatmap(corr_df)
plt.show()
참고로 가운데 대각선 방향으로 위치한 상관계수는 모두 1인데 이는 자기 자신과의 상관계수이기 때문이다.
일반적으로 상관계수는 연속형값에서 해석되어야 한다. Survived와 Pclass는 숫자값이지만 범주형 컬럼이지만 Survived가 0일 때(즉 사망)는 Pclass가 1보다는 3인 값이 더 많고(즉 3등실 승객이 더 사망할 확률이 높음), Survived가 1일 때(즉 생존)는 Pclass가 3보다는 1인 값이 더 많기 때문에 이러한 상관계수를 가지게 되었음에 유의하자
→ Survived와 Pclass는 음의 상관관계를 가짐
cmap 인자는 color map으로서 히트맵의 색상을 변경할 수 있게 해준다.color map의 종류는 너무 다양해서 아래 URL을 참조하자.
seaborn의 시각화 함수를 subplots로 할당된 개별 Axes 객체에 적용하는 방식은 맷플롯립과 약간 다르다.
seaborn의 모든 Axes level 시각화 함수는 ax라는 인자를 가지고 있으며, 시각화 함수 호출 시 이 ax 인자에 개별 Axes 객체를 할당하면 된다. 예를 들어 fig, axs = plt.subplots(nrows=1, ncols=3)라고 한다면 sns.countplot(x=컬럼명, data=DataFrame, ax=axs[0])과 같이 ax 인자값으로 첫번째 로우 위치의 첫번째 컬럼 위치에 해당하는 Axes 객체 변수를 입력하게 되면 해당 위치의 subplot에 카운트 플롯을 시각화해준다.
파이썬 시각화에 큰 공헌을 한 시각화 라이브러리로 파이썬 세계에서 시각화를 위해서 가장 많이 사용
하지만 직관적이지 못한 개발 API로 인해서 시각화 코딩에 익숙해지는 데 많은 시간이 필요하며, 차트의 축 이름이나, 차트 타이틀, 범례(legend) 등의 부가적인 속성까지 코딩을 해주어야 하는 불편함이 있음
Seaborn(시본)
Matplotlib보다 쉬운 구현, 수려한 시각화, 그리고 판다스와의 연동이 편리한 특징을 가짐
Matplotlib을 기반으로 하고 있지만, Matplotlib보다 상대적으로 적은 양의 코딩으로도 보다 수려한 시각화 플롯을 제공
판다스의 컬럼명을 기반으로 자동으로 축 이름을 설정하는 등 편리한 연동 기능을 가짐
하지만 Seaborn 역시 Matplotlib을 기반으로 하고 있으며, 특정 요소들의 경우 Matplotlib 함수들을 그대로 사용하고 있기에 Seaborn을 잘 활용하려면 반드시 Matplotlib을 어느 정도는 알고 있어야 함
Matplotlib은 다양한 그래프/차트를 포함한 많은 시각화 객체(선 그래프, 막대 그래프, 파이 차트 등)와 함수를 제공하지만 여기서는 이들을 설명하지 않을 것이며, 선과 막대 그래프를 이용한 기본 시각화 구현을 실습하면서 Matplotlib을 이용시 개괄적인 시각화 코드 작성 방법에 대해서 설명한다. 본격적인 그래프/차트는 뒤에서 소개하는 Seaborn에서 좀 더 자세히 알아볼 것이다.
Matplotlib
Matplotlib의 pyplot 모듈의 이해
Matplotlib은 파이썬 시각화를 위한 기반 모듈인 pyplot을 제공하며 이를 통해 시각화를 구현할 수 있음
title() 함수는 입력값으로 타이틀 문자열을 받아서 차트 타이틀을 설정할 수 있음
show() 함수를 호출하여 그래프를 화면에 출력할 수 있음
# pyplot 모듈을 관용적으로 plt라는 이름으로 import
import matplotlib.pyplot as plt
# x축 입력값 [1, 2, 3], y축 입력값 [2, 4, 6]으로 선 그래프 생성
plt.plot([1, 2, 3], [2, 4, 6])
# 선그래프 타이틀을 Hello plot으로 설정
plt.title('Hello plot')
# 선 그래프를 출력
plt.show()
pyplot의 두 가지 중요 요소 - Figure와 Axes
Figure
그림을 그리기 위한 캔버스의 역할(그림판의 크기를 조절한다든가, 플롯을 최종적으로 화면에 나타내는 역할 수행)
하지만 실제적으로 그림을 그리는 역할은 수행하지 않음
Axes
실제 그림을 그리는 메서드들을 가짐 → 시각화를 수행하는 메서드들은 Axes에서 호출됨
X축, Y축, 타이틀, 축 범위 조정, 범례 등의 속성을 설정하는 데도 이용
실제 그림을 그리는 데 핵심적인 역할을 수행
→ Axes(축 Axis의 복수형)라는 이름이 주는 인상 때문에 단순히 X축이나 Y축에 관련된 설정 정도의 역할을 수행할 것이라는 선입견과는 다르게 시각화와 관련된 많은 작업들이 이 Axes 객체 기반에서 수행된다. 반면에 Figure는 그림을 그리는 실제 작업에는 크게 연관되어 있지 않다.
앞의 선 그래프를 그리는 예제를 Figure와 Axes 관점에서 설명하면 다음과 같다.
import matplotlib.pyplot as plt 기본으로 설정된 Figure, Axes가 로딩됨
plt.plot([1, 2, 3], [2, 4, 6]) 기본으로 설정된 Axes에서 Axes.plot() 함수를 호출하여 그림을 그림
plt.title('Hello plot') plt.title()은 내부적으로 Axes.set_title() 함수를 호출하여 타이틀을 설정
plt.show() plt.show()는 내부적으로 Figure.show()를 호출하여 그림을 나타냄
pyplot의 두 가지 중요 요소 - Figure와 Axes
plt.figure(figsize=(10,4))와 같이 plt 모듈의 figure() 함수를 호출하면 Figure 객체가 반환된다. 이때 인자로 figsize=(가로크기, 세로크기) 입력하면 해당 크기를 가지는 Figure 객체를 반환하게 된다.
# figure 크기가 가로 10, 세로 4인 Figure 객체를 반환
plt.figure(figsize=(10, 4))
plt.plot([1, 2, 3], [2, 4, 6])
plt.title('Hello plot')
plt.show()
앞서 말했듯이, plt.figure() 함수에 의해 반환된 Figure가 실제로 그림을 그리는 역할은 하지 못하지만 그림판의 배경 색상을 바꾸는 등의 설정을 할 수 있음
plt.figure(facecolor='yellow')를 적용해도 전체 그림판이 노란색으로 변하지 않는다. Axes가 차지하는 영역이 Figure가 차지하는 그림판 위에 적용되기 때문이다.
plt의 axes() 함수는 현재 사용하는 Axes 객체를 반환한다. (참고로 하단의 결과에서 plt.axes()만 호출했는데도 축을 포함한 그림이 표출된 이유는 pyplot 모듈이 import되어 있는 상태에서 주피터노트북은 별도의 plt.show()가 없더라도 Axes가 할당되어 있으면 자동으로 plt.show()와 같은 역할을 하는 함수를 호출하면서 그림이 표출되게 된다.)
ax = plt.axes()
pyplot에서 Figure와 Axes 객체를 함께 가져올 수 있는데 이는 plt.subplots()을 이용한다. plt.subplots() 함수는 인자로 여러 개의 Axes를 설정할 수 있으며, 여기서는 디폴트 인자만 적용해 단 한개의 Axes만 가져온다.
fig, ax = plt.subplots()
여러 개의 plot을 가지는 subplot들을 생성하기
plt.subplots() 함수는 하나의 Figure상에서 여러 개의 그래프를 그릴 수 있게 만들어 주는데, 이때 개별 subplot은 하나의 Axes를 가진다. 즉 plt.subplots()은 여러 개의 그래프를 그릴 수 있게 하는 1개의 Figure와 여러 개의 Axes를 생성하고 반환한다.
plt.subplots()의 주요 인자로 nrows와 ncols, figsize가 사용된다. nrows는 전체 subplot들의 배치를 2차원 행렬 형태로 표현할 때 행의 개수가 되며, ncols는 열의 개수가 된다. 그리고 figsize는 모든 subplot들을 포함한 전체 Figure의 크기를 설정한다.
plt.subplots(nrows=1, ncols=2, figsize=(6,3)) 수행 시 Figure와 두 개의 Axes 객체를 반환하는데, 이때 반환되는 Axes 객체는 (ax1, ax2)와 같이 튜플 형태로 반환받을 수 있다. ax1이 첫번째 Axes 객체를, ax2가 두번째 Axes 객체를 가리킨다.
하지만 여러 개의 Axes 객체를 튜플 형태가 아니라 넘파이의 ndarray 형태로도 받을 수 있고 이 방법이 더 선호된다. 이는 '여러 개의 subplots들을 이용해 개별 그래프들을 subplot별로 시각화하기' 파트에서 더 알아보자.
pyplot의 plot() 함수를 이용해 선 그래프 그리기
pyplot의 plot() 함수는 선 그래프를 그릴 때 활용된다. X 좌표 값, Y 좌표 값으로 파이썬 리스트, 넘파이 ndarray, 판다스의 DataFrame/Series 모두 적용 가능하다. 다만 입력되는 X 좌표 값과 Y 좌표 값의 개수는 모두 같은 크기를 가져야 한다.
X좌표값을 0~99까지 100개로 설정했지만, 0, 20, 40, 60, 80, 100 눈금 값들만 표시가 된다. Matplotlib은 축 값이 문자열인 경우는 모든 값을 나타내 주지만, 축 값이 숫자값이면 자동으로 최솟값과 최댓값에 기반해 축의 크기에 따라 눈금 간격을 만들어 준다.
X축의 눈금 값을 좀 더 세밀하게 나타내고 싶으면 xticks() 함수의 인자로 ticks 값을 나타내고 싶은 값을 설정하면 된다.
plt.subplots()의 인자인 nrows가 1이거나 또는 ncols가 1인 경우에는 1차원 배열 인덱싱 방식으로 Axes를 접근할 수 있다.(ex: fig, ax = plt.subplots(nrows=1, ncols=3)이라면 ax[0], ax[1], ax[2]와 같은 방식으로 3개의 Axes 객체를 접근할 수 있음) 하지만 nrows도 2 이상이고, ncols도 2 이상이 되면 1차원 배열 인덱싱 방식이 아니라 2차원 배열 인덱싱 방식으로 Axes를 접근해야 한다.
ax[0][0]은 첫번째 로우의 첫번째 컬럼에 해당하는 Axes 객체, ax[0][1]은 첫번째 로우의 두번째 컬럼에 해당하는 Axes 객체, ax[1][0]은 두번째 로우의 첫번째 컬럼에 해당하는 Axes 객체, ax[1][1]은 두번째 로우의 두번째 컬럼에 해당하는 Axes 객체를 가리킨다.
경도(UTM 세로 격자): 양 끝 180° 기준, 6° 간격으로 60등분(1 ~ 60 zone) → 180°W부터 시작하여 동쪽으로 가면 경도 6° 간격으로 총 60개의 세로 zone 생성 → 각 세로 zone의 중앙 자오선(ex: 180°W ~ 174°W zone의 중앙 자오선은 177°W임)과 적도와의 교점을 기준 원점으로 함 → 60개의 세로 zone의 각 중앙 자오선을 기준으로 각각 횡축 메르카토르 투영으로 지도에 옮김
위도(UTM 가로 격자): 80°S 부터 84°N 까지 8° 간격으로 20등분(c ~ x zone, i와 o 제외) → 각 세로 zone을 다시 20개의 가로 zone으로 나눔 → 각 가로 zone은 위도 8° 간격이며 단, 가장 북쪽의 격자(72°N ~ 84°N)는 12°로 되어있음 → 최남단인 80°S ~ 72°S 부터 최북단인 72°N ~84°N 까지 'c'부터 'x'까지의 알파벳 기호를 매겨 구분하는데, i는 숫자 1과 o는 숫자 0과 혼동될 수 있기 때문에 i, o는 제외함
좌표는 기준 원점의 위치에 따라 음의 부호를 갖는 좌표가 나타날 수 있는데, Y축(동서방향)에는 500,000m / X축(남북방향)에는 남반구만 10,000,000m를 더함
특정 지구상의 지점(Y, X)은 Y축(동서방향)은 대상점이 속한 zone의 중앙 자오선으로부터 대상점까지의 투영 거리, X축(남북방향)은 대상점의 적도로부터의 투영 거리
메르카토르 투영은 적도를 따라 원기둥을 감싸는 방식으로 극지방의 왜곡이 크게 나타날 수 밖에 없다. → 의문점: 왜 적도를 따라서만 원기둥을 감싸야 하지? → 대안: 남극과 북극을 지나는 자오선을 따라 원기둥을 감싼 것이 "횡축 메르카토르 투영"
메르카토르 투영은 적도 지방에 왜곡이 없다면, 횡축 메르카토르 투영은 자오선을 따라서 왜곡이 없다. 따라서 특정 경도 부근에서 정확한 지도를 그리고 싶다면, 해당 경도의 자오선을 따라 횡축 메르카토르 투영을 하면된다.
메르카토르 투영은 러시아 처럼 동서로 긴 지역에 적합하고, 횡축 메르카토르 투영은 한반도처럼 남북이 긴 지역에 적합하다.
즉, 횡축 메르카토르 투영은 메르카토르 투영에서 원기둥을 90도 회전시켜 중앙 자오선이 원기둥 면에 접하도록 하는 투영으로 우리나라의 국가 기본도 등의 대·중축척 지형도에 사용되고 있다.
→ 지구에 적도는 하나밖에 없는 반면 자오선은 무한대로 존재하므로 이론상 횡축 메르카토르 투영을 통해 그릴 수 있는 지도는 무한함
우리나라의 평면 직각 좌표(TM 투영)
우리나라와 같이 남북이 길다 하더라도 동서의 폭이 어느정도 존재하기 때문에 4개의 자오선을 선택하여 각각 투영하여 투영 오차를 줄임
서부좌표계, 중부좌표계, 동부좌표계, 동해좌표계로 구분하여 사용
서부원점(N38°, E125°), 중부원점(N38°, E127°), 동부원점(N38°, E129°), 동해원점(N38°, E131°)으로 각각의 서부좌표계, 중부좌표계, 동부좌표계, 동해좌표계에 대한 원점을 잡음
각 평면 직각 좌표계에서 모든 지역의 좌표가 +가 되게 하기 위해서 모든 좌표값에 아래와 같은 값을 더함
Y축(동서방향/경도방향)에는 200,000m / X축(남북방향/위도방향)에는 600,000m를 더함 → 이렇게 하면 우리나라 전 지역에 대해 양수 좌표값으로 표현 가능
서부원점을 (0, 0)이라고 하고 백령도에 대한 좌표를 예측해보면 (-, -) 형태의 마이너스 좌표가 나온다. 이 마이너스 좌표에 대한 해결 방안이 Y축(동서방향)으로 200,000m, X축(남북방향)으로 600,000m를 더한다.
즉, 서부원점을 (0, 0)으로 하는 것이 아니라 (600,000, 200,000)으로 잡는다. 이렇게 되면 백령도가 +값으로 좌표가 정의된다.
서부원점, 중부원점, 동부원점, 동해원점이 각각의 서부좌표계, 중부좌표계, 동부좌표계, 동해좌표계의 원점이 되지만, 실질적으로 (0, 0)이 되는 지점은 서부원점을 기준으로 좌측 하단의 TM지도좌표 서부원점에 해당하고 이 위치를 시작으로 특정 지점을 양의 값으로 구현화 할 수 있다.
→ 중부, 동부, 동해도 동일한 맥락
예를 들어, 서울이나 인천처럼 중부좌표계에 가까운 지점은 중부좌표계를 사용해서 해당 위치를 표현하는 것이 왜곡을 최소화할 수 있는 방안이 될 것이고, 반면에 대구처럼 동부좌표계에 가까운 지점은 동부좌표계를 사용해서 해당 위치를 표현하는 것이 왜곡을 최소화할 수 있는 방안이 된다.
정리를 하자면, 우리나라는 TM투영을 4개로 나눠서 서부좌표계, 중부좌표계, 동부좌표계, 동해좌표계로 표현한다.