상권분석
in Study on datavisualization
데이터 출처 : 공공데이터포털
소상공인 상권정보 상가업소 데이터
라이브러리 로드
#라이브러리 로드
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
한글폰트 설정
# 한글 폰트 설정
plt.rc("font", family="Malgun Gothic")
plt.rc("axes", unicode_minus=False) # -깨지는거 제거
# 레티나 디스플레이로 폰트가 선명하게 표시되도록 합니다.
from IPython.display import set_matplotlib_formats
set_matplotlib_formats("retina")
#한글 폰트 설정
pd.Series([-4, 1, 0, 3, -2, 4, 5]).plot(title="한글폰트 설정")
<matplotlib.axes._subplots.AxesSubplot at 0x24d4e5e9df0>

파일로드
%ls data
C 드라이브의 볼륨: Windows
볼륨 일련 번호: F667-FF4C
C:\Users\actyu\jupyter_ex\data 디렉터리
2021-01-24 오전 12:01 <DIR> .
2021-01-24 오전 12:01 <DIR> ..
2021-01-24 오전 12:01 57,732 seoul_municipalities_geo_simple.json
2021-01-24 오전 12:01 264,920,940 상가업소정보_201912_01.csv
2021-01-19 오후 02:35 2,163 전국 평균 분양가격(2013년 9월부터 2015년 8월까지).csv
2021-01-19 오후 02:21 175,016 주택도시보증공사_전국 신규 민간 아파트 분양가격 동향_20200331.csv
2021-01-19 오후 02:36 162,510 주택도시보증공사_전국 평균 분양가격(2019년 12월).csv
5개 파일 265,318,361 바이트
2개 디렉터리 102,667,726,848 바이트 남음
# 파일을 로드합니다.
df = pd.read_csv("data/상가업소정보_201912_01.csv", sep='|')
df.shape
(573680, 39)
pd.options.display.max_columns = 39 # 모든컬럼을 표시
df.head()
| 상가업소번호 | 상호명 | 지점명 | 상권업종대분류코드 | 상권업종대분류명 | 상권업종중분류코드 | 상권업종중분류명 | 상권업종소분류코드 | 상권업종소분류명 | 표준산업분류코드 | 표준산업분류명 | 시도코드 | 시도명 | 시군구코드 | 시군구명 | 행정동코드 | 행정동명 | 법정동코드 | 법정동명 | 지번코드 | 대지구분코드 | 대지구분명 | 지번본번지 | 지번부번지 | 지번주소 | 도로명코드 | 도로명 | 건물본번지 | 건물부번지 | 건물관리번호 | 건물명 | 도로명주소 | 구우편번호 | 신우편번호 | 동정보 | 층정보 | 호정보 | 경도 | 위도 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 19905471 | 와라와라호프 | NaN | Q | 음식 | Q09 | 유흥주점 | Q09A01 | 호프/맥주 | I56219 | 기타 주점업 | 11 | 서울특별시 | 11680 | 강남구 | 1168060000 | 대치1동 | 1168010600 | 대치동 | 1168010600206040000 | 1 | 대지 | 604 | NaN | 서울특별시 강남구 대치동 604 | 116802000003 | 서울특별시 강남구 남부순환로 | 2933 | NaN | 1168010600106040000014378 | 대치상가 | 서울특별시 강남구 남부순환로 2933 | 135280 | 6280.0 | NaN | 1 | NaN | 127.061026 | 37.493922 |
| 1 | 19911397 | 커피빈코리아선릉로93길점 | 코리아선릉로93길점 | Q | 음식 | Q12 | 커피점/카페 | Q12A01 | 커피전문점/카페/다방 | I56220 | 비알콜 음료점업 | 11 | 서울특별시 | 11680 | 강남구 | 1168064000 | 역삼1동 | 1168010100 | 역삼동 | 1168010100206960042 | 1 | 대지 | 696 | 42.0 | 서울특별시 강남구 역삼동 696-42 | 116804166502 | 서울특별시 강남구 선릉로93길 | 6 | NaN | 1168010100106960042022041 | NaN | 서울특별시 강남구 선릉로93길 6 | 135080 | 6149.0 | NaN | 1 | NaN | 127.047883 | 37.505675 |
| 2 | 19911801 | 프로포즈 | NaN | Q | 음식 | Q09 | 유흥주점 | Q09A01 | 호프/맥주 | I56219 | 기타 주점업 | 11 | 서울특별시 | 11545 | 금천구 | 1154563000 | 독산3동 | 1154510200 | 독산동 | 1154510200201620001 | 1 | 대지 | 162 | 1.0 | 서울특별시 금천구 독산동 162-1 | 115453117003 | 서울특별시 금천구 가산로 | 34 | 6.0 | 1154510200101620001017748 | NaN | 서울특별시 금천구 가산로 34-6 | 153010 | 8545.0 | NaN | 1 | NaN | 126.899220 | 37.471711 |
| 3 | 19912201 | 싱싱커피&토스트 | NaN | Q | 음식 | Q07 | 패스트푸드 | Q07A10 | 토스트전문 | I56192 | 피자, 햄버거, 샌드위치 및 유사 음식점업 | 26 | 부산광역시 | 26530 | 사상구 | 2653062000 | 괘법동 | 2653010400 | 괘법동 | 2653010400205780000 | 1 | 대지 | 578 | NaN | 부산광역시 사상구 괘법동 578 | 265303139004 | 부산광역시 사상구 괘감로 | 37 | NaN | 2653010400105780000002037 | 산업용품유통상가 | 부산광역시 사상구 괘감로 37 | 617726 | 46977.0 | NaN | 1 | 26 | 128.980455 | 35.159774 |
| 4 | 19932756 | 가락사우나내스낵 | NaN | F | 생활서비스 | F09 | 대중목욕탕/휴게 | F09A02 | 사우나/증기탕/온천 | S96121 | 욕탕업 | 11 | 서울특별시 | 11710 | 송파구 | 1171060000 | 석촌동 | 1171010500 | 석촌동 | 1171010500202560000 | 1 | 대지 | 256 | NaN | 서울특별시 송파구 석촌동 256 | 117103123001 | 서울특별시 송파구 가락로 | 71 | NaN | 1171010500102560005010490 | NaN | 서울특별시 송파구 가락로 71 | 138846 | 5690.0 | NaN | 1 | NaN | 127.104071 | 37.500249 |
df.tail()
| 상가업소번호 | 상호명 | 지점명 | 상권업종대분류코드 | 상권업종대분류명 | 상권업종중분류코드 | 상권업종중분류명 | 상권업종소분류코드 | 상권업종소분류명 | 표준산업분류코드 | 표준산업분류명 | 시도코드 | 시도명 | 시군구코드 | 시군구명 | 행정동코드 | 행정동명 | 법정동코드 | 법정동명 | 지번코드 | 대지구분코드 | 대지구분명 | 지번본번지 | 지번부번지 | 지번주소 | 도로명코드 | 도로명 | 건물본번지 | 건물부번지 | 건물관리번호 | 건물명 | 도로명주소 | 구우편번호 | 신우편번호 | 동정보 | 층정보 | 호정보 | 경도 | 위도 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 573675 | 16394290 | 비파티세리공덕 | NaN | Q | 음식 | Q01 | 한식 | Q01A01 | 한식/백반/한정식 | I56111 | 한식 음식점업 | 11 | 서울특별시 | 11440 | 마포구 | 1144056500 | 공덕동 | 1144010200 | 공덕동 | 1144010200201050067 | 1 | 대지 | 105 | 67.0 | 서울특별시 마포구 공덕동 105-67 | 114404139142 | 서울특별시 마포구 마포대로14길 | 4 | NaN | 1144010200101050067001710 | NaN | 서울특별시 마포구 마포대로14길 4 | 121801 | 4211.0 | NaN | NaN | NaN | 126.955059 | 37.548618 |
| 573676 | 16336474 | 앤탑PC방 | NaN | N | 관광/여가/오락 | N01 | PC/오락/당구/볼링등 | N01A01 | 인터넷PC방 | R91222 | 컴퓨터 게임방 운영업 | 11 | 서울특별시 | 11200 | 성동구 | 1120069000 | 성수2가3동 | 1120011500 | 성수동2가 | 1120011500202890015 | 1 | 대지 | 289 | 15.0 | 서울특별시 성동구 성수동2가 289-15 | 112004109367 | 서울특별시 성동구 성수일로8길 | 37 | NaN | 1120011500102890015004255 | 으뜸프린팅(주) | 서울특별시 성동구 성수일로8길 37 | 133834 | 4794.0 | NaN | 2 | NaN | 127.054615 | 37.545853 |
| 573677 | 16336218 | 오즈아레나PC방 | NaN | N | 관광/여가/오락 | N01 | PC/오락/당구/볼링등 | N01A01 | 인터넷PC방 | R91222 | 컴퓨터 게임방 운영업 | 11 | 서울특별시 | 11680 | 강남구 | 1168052100 | 논현1동 | 1168010800 | 논현동 | 1168010800201650008 | 1 | 대지 | 165 | 8.0 | 서울특별시 강남구 논현동 165-8 | 116802102001 | 서울특별시 강남구 강남대로 | 492 | NaN | 1168010800101650008000001 | 한맥빌딩 | 서울특별시 강남구 강남대로 492 | 135825 | 6119.0 | NaN | 2 | NaN | 127.024102 | 37.506202 |
| 573678 | 16335152 | 파인트리네일 | NaN | F | 생활서비스 | F01 | 이/미용/건강 | F01A02 | 발/네일케어 | S96119 | 기타미용업 | 11 | 서울특별시 | 11560 | 영등포구 | 1156054000 | 여의동 | 1156011000 | 여의도동 | 1156011000200230000 | 1 | 대지 | 23 | NaN | 서울특별시 영등포구 여의도동 23 | 115603118002 | 서울특별시 영등포구 국제금융로 | 10 | NaN | 1156011000100230000000001 | 서울국제금융센터 | 서울특별시 영등포구 국제금융로 10 | 150945 | 7326.0 | NaN | 1 | NaN | 126.924863 | 37.525172 |
| 573679 | 16335150 | 마이리틀네일 | NaN | F | 생활서비스 | F01 | 이/미용/건강 | F01A02 | 발/네일케어 | S96119 | 기타미용업 | 11 | 서울특별시 | 11320 | 도봉구 | 1132051100 | 창1동 | 1132010700 | 창동 | 1132010700208120000 | 1 | 대지 | 812 | NaN | 서울특별시 도봉구 창동 812 | 113204127109 | 서울특별시 도봉구 도봉로114길 | 22 | 8.0 | 1132010700108120000018489 | 현대타운아파트 | 서울특별시 도봉구 도봉로114길 22-8 | 132691 | 1455.0 | 101 | NaN | NaN | 127.035145 | 37.647099 |
#인덱스 정보
df.index
RangeIndex(start=0, stop=573680, step=1)
df.columns
Index(['상가업소번호', '상호명', '지점명', '상권업종대분류코드', '상권업종대분류명', '상권업종중분류코드',
'상권업종중분류명', '상권업종소분류코드', '상권업종소분류명', '표준산업분류코드', '표준산업분류명', '시도코드',
'시도명', '시군구코드', '시군구명', '행정동코드', '행정동명', '법정동코드', '법정동명', '지번코드',
'대지구분코드', '대지구분명', '지번본번지', '지번부번지', '지번주소', '도로명코드', '도로명', '건물본번지',
'건물부번지', '건물관리번호', '건물명', '도로명주소', '구우편번호', '신우편번호', '동정보', '층정보',
'호정보', '경도', '위도'],
dtype='object')
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 573680 entries, 0 to 573679
Data columns (total 39 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 상가업소번호 573680 non-null int64
1 상호명 573679 non-null object
2 지점명 76674 non-null object
3 상권업종대분류코드 573680 non-null object
4 상권업종대분류명 573680 non-null object
5 상권업종중분류코드 573680 non-null object
6 상권업종중분류명 573680 non-null object
7 상권업종소분류코드 573680 non-null object
8 상권업종소분류명 573680 non-null object
9 표준산업분류코드 539290 non-null object
10 표준산업분류명 539290 non-null object
11 시도코드 573680 non-null int64
12 시도명 573680 non-null object
13 시군구코드 573680 non-null int64
14 시군구명 573680 non-null object
15 행정동코드 573680 non-null int64
16 행정동명 573680 non-null object
17 법정동코드 573680 non-null int64
18 법정동명 573680 non-null object
19 지번코드 573680 non-null int64
20 대지구분코드 573680 non-null int64
21 대지구분명 573680 non-null object
22 지번본번지 573680 non-null int64
23 지번부번지 474924 non-null float64
24 지번주소 573680 non-null object
25 도로명코드 573680 non-null int64
26 도로명 573680 non-null object
27 건물본번지 573680 non-null int64
28 건물부번지 71988 non-null float64
29 건물관리번호 573680 non-null object
30 건물명 265608 non-null object
31 도로명주소 573680 non-null object
32 구우편번호 573680 non-null int64
33 신우편번호 573671 non-null float64
34 동정보 50856 non-null object
35 층정보 347127 non-null object
36 호정보 85266 non-null object
37 경도 573680 non-null float64
38 위도 573680 non-null float64
dtypes: float64(5), int64(11), object(23)
memory usage: 170.7+ MB
df.dtypes
상가업소번호 int64
상호명 object
지점명 object
상권업종대분류코드 object
상권업종대분류명 object
상권업종중분류코드 object
상권업종중분류명 object
상권업종소분류코드 object
상권업종소분류명 object
표준산업분류코드 object
표준산업분류명 object
시도코드 int64
시도명 object
시군구코드 int64
시군구명 object
행정동코드 int64
행정동명 object
법정동코드 int64
법정동명 object
지번코드 int64
대지구분코드 int64
대지구분명 object
지번본번지 int64
지번부번지 float64
지번주소 object
도로명코드 int64
도로명 object
건물본번지 int64
건물부번지 float64
건물관리번호 object
건물명 object
도로명주소 object
구우편번호 int64
신우편번호 float64
동정보 object
층정보 object
호정보 object
경도 float64
위도 float64
dtype: object
결측치 확인
df.isnull()
# true 는 결측치
| 상가업소번호 | 상호명 | 지점명 | 상권업종대분류코드 | 상권업종대분류명 | 상권업종중분류코드 | 상권업종중분류명 | 상권업종소분류코드 | 상권업종소분류명 | 표준산업분류코드 | 표준산업분류명 | 시도코드 | 시도명 | 시군구코드 | 시군구명 | 행정동코드 | 행정동명 | 법정동코드 | 법정동명 | 지번코드 | 대지구분코드 | 대지구분명 | 지번본번지 | 지번부번지 | 지번주소 | 도로명코드 | 도로명 | 건물본번지 | 건물부번지 | 건물관리번호 | 건물명 | 도로명주소 | 구우편번호 | 신우편번호 | 동정보 | 층정보 | 호정보 | 경도 | 위도 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | False | False | False | True | False | False | False | False | False | True | False | True | False | False |
| 1 | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | True | False | False | False | True | False | True | False | False |
| 2 | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | False | False | True | False | True | False | False |
| 3 | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | False | False | False | True | False | False | False | False | False | True | False | False | False | False |
| 4 | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | False | False | False | True | False | True | False | False | False | True | False | True | False | False |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 573675 | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | True | False | False | False | True | True | True | False | False |
| 573676 | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | False | False | False | False | True | False | True | False | False |
| 573677 | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | False | False | False | False | True | False | True | False | False |
| 573678 | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | False | False | False | True | False | False | False | False | False | True | False | True | False | False |
| 573679 | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | False | False | False | False | False | False | False | False | False | False | True | True | False | False |
573680 rows × 39 columns
n = df.isnull().sum()
#막대그래프 시각화
n.plot.bar() # 결측치 보기
<matplotlib.axes._subplots.AxesSubplot at 0x24d4ed9f760>

# 옆으로 그래프 보기(결측치 순서대로) sort_values
n.sort_values().plot.barh(figsize=(7,8))
<matplotlib.axes._subplots.AxesSubplot at 0x24d4fec1a00>

missingno로 결측치 시각화
import missingno as msno
msno.matrix(df)
<matplotlib.axes._subplots.AxesSubplot at 0x24d264ee160>

#heatmap 으로 시각화
msno.heatmap(df)
<matplotlib.axes._subplots.AxesSubplot at 0x24d297517c0>

# dendrogram으로 표현
msno.dendrogram(df)
<matplotlib.axes._subplots.AxesSubplot at 0x24d0777ac10>

사용하지 않는 칼럼 제거
# sort_values 를 통해 결측치가 많은 데이터를 위에서 9개 가져와서 not_use 변수에 담습니다.
# not_use 변수에 담긴 인덱스값만 추출해서 not_use_col 이라는 변수에 담습니다.
not_use = n.sort_values(ascending=False).head(9)
not_use_col = not_use.index
not_use_col
Index(['동정보', '건물부번지', '지점명', '호정보', '건물명', '층정보', '지번부번지', '표준산업분류명',
'표준산업분류코드'],
dtype='object')
# 사용하지 않는 칼럼 제거, shpae으로 확인
print(df.shape) # 칼럼 39
df = df.drop(not_use_col, axis=1) # 칼럼제거 axis =1
print(df.shape) # 칼럼 30
(573680, 39)
(573680, 30)
cols = df.columns
cols_code = cols[cols.str.contains("코드|번호")] # 코드나 번호가 들어가는 칼럼
cols_code
Index(['상가업소번호', '상권업종대분류코드', '상권업종중분류코드', '상권업종소분류코드', '시도코드', '시군구코드',
'행정동코드', '법정동코드', '지번코드', '대지구분코드', '도로명코드', '건물관리번호', '구우편번호',
'신우편번호'],
dtype='object')
#코드나 번호가 들어가는 칼럼 제거
print(df.shape) # 칼럼 30
df = df.drop(cols_code, axis= 1)
print(df.shape) # 칼럼 16
(573680, 30)
(573680, 16)
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 573680 entries, 0 to 573679
Data columns (total 16 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 상호명 573679 non-null object
1 상권업종대분류명 573680 non-null object
2 상권업종중분류명 573680 non-null object
3 상권업종소분류명 573680 non-null object
4 시도명 573680 non-null object
5 시군구명 573680 non-null object
6 행정동명 573680 non-null object
7 법정동명 573680 non-null object
8 대지구분명 573680 non-null object
9 지번본번지 573680 non-null int64
10 지번주소 573680 non-null object
11 도로명 573680 non-null object
12 건물본번지 573680 non-null int64
13 도로명주소 573680 non-null object
14 경도 573680 non-null float64
15 위도 573680 non-null float64
dtypes: float64(2), int64(2), object(12)
memory usage: 70.0+ MB
행,열 기준으로 값을 가져오기
열기준으로 가져오기
#상호명 가져오기
df[["상호명"]]
| 상호명 | |
|---|---|
| 0 | 와라와라호프 |
| 1 | 커피빈코리아선릉로93길점 |
| 2 | 프로포즈 |
| 3 | 싱싱커피&토스트 |
| 4 | 가락사우나내스낵 |
| ... | ... |
| 573675 | 비파티세리공덕 |
| 573676 | 앤탑PC방 |
| 573677 | 오즈아레나PC방 |
| 573678 | 파인트리네일 |
| 573679 | 마이리틀네일 |
573680 rows × 1 columns
# 상호명,도로명 칼럼가져오기 (두 칼럼 이상 가져올때는 [[]]형태로 가져오기)
df[["상호명","도로명주소"]].head()
| 상호명 | 도로명주소 | |
|---|---|---|
| 0 | 와라와라호프 | 서울특별시 강남구 남부순환로 2933 |
| 1 | 커피빈코리아선릉로93길점 | 서울특별시 강남구 선릉로93길 6 |
| 2 | 프로포즈 | 서울특별시 금천구 가산로 34-6 |
| 3 | 싱싱커피&토스트 | 부산광역시 사상구 괘감로 37 |
| 4 | 가락사우나내스낵 | 서울특별시 송파구 가락로 71 |
행기준으로 가져오기
# 0번째 인덱스 행을 가져오기
df.loc[0]
상호명 와라와라호프
상권업종대분류명 음식
상권업종중분류명 유흥주점
상권업종소분류명 호프/맥주
시도명 서울특별시
시군구명 강남구
행정동명 대치1동
법정동명 대치동
대지구분명 대지
지번본번지 604
지번주소 서울특별시 강남구 대치동 604
도로명 서울특별시 강남구 남부순환로
건물본번지 2933
도로명주소 서울특별시 강남구 남부순환로 2933
경도 127.061
위도 37.4939
Name: 0, dtype: object
# 0, 1, 2 번째 인덱스 행을 가져온다 .
df.loc[[0,1,2]]
| 상호명 | 상권업종대분류명 | 상권업종중분류명 | 상권업종소분류명 | 시도명 | 시군구명 | 행정동명 | 법정동명 | 대지구분명 | 지번본번지 | 지번주소 | 도로명 | 건물본번지 | 도로명주소 | 경도 | 위도 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 와라와라호프 | 음식 | 유흥주점 | 호프/맥주 | 서울특별시 | 강남구 | 대치1동 | 대치동 | 대지 | 604 | 서울특별시 강남구 대치동 604 | 서울특별시 강남구 남부순환로 | 2933 | 서울특별시 강남구 남부순환로 2933 | 127.061026 | 37.493922 |
| 1 | 커피빈코리아선릉로93길점 | 음식 | 커피점/카페 | 커피전문점/카페/다방 | 서울특별시 | 강남구 | 역삼1동 | 역삼동 | 대지 | 696 | 서울특별시 강남구 역삼동 696-42 | 서울특별시 강남구 선릉로93길 | 6 | 서울특별시 강남구 선릉로93길 6 | 127.047883 | 37.505675 |
| 2 | 프로포즈 | 음식 | 유흥주점 | 호프/맥주 | 서울특별시 | 금천구 | 독산3동 | 독산동 | 대지 | 162 | 서울특별시 금천구 독산동 162-1 | 서울특별시 금천구 가산로 | 34 | 서울특별시 금천구 가산로 34-6 | 126.899220 | 37.471711 |
#0번째 행의 상호명을 가져오기
df.loc[0, "상호명"]
'와라와라호프'
#0, 1, 2 번째 행의 "상호명" , "도로명주소"가져오기
df.loc[[0, 1, 2], ["상호명", "도로명주소"]]
| 상호명 | 도로명주소 | |
|---|---|---|
| 0 | 와라와라호프 | 서울특별시 강남구 남부순환로 2933 |
| 1 | 커피빈코리아선릉로93길점 | 서울특별시 강남구 선릉로93길 6 |
| 2 | 프로포즈 | 서울특별시 금천구 가산로 34-6 |
# 위에서 5개의 행과 왼쪽에서 5개의 열을 가져온다. iloc 슬라이싱
df.iloc[:5]
| 상호명 | 상권업종대분류명 | 상권업종중분류명 | 상권업종소분류명 | 시도명 | 시군구명 | 행정동명 | 법정동명 | 대지구분명 | 지번본번지 | 지번주소 | 도로명 | 건물본번지 | 도로명주소 | 경도 | 위도 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 와라와라호프 | 음식 | 유흥주점 | 호프/맥주 | 서울특별시 | 강남구 | 대치1동 | 대치동 | 대지 | 604 | 서울특별시 강남구 대치동 604 | 서울특별시 강남구 남부순환로 | 2933 | 서울특별시 강남구 남부순환로 2933 | 127.061026 | 37.493922 |
| 1 | 커피빈코리아선릉로93길점 | 음식 | 커피점/카페 | 커피전문점/카페/다방 | 서울특별시 | 강남구 | 역삼1동 | 역삼동 | 대지 | 696 | 서울특별시 강남구 역삼동 696-42 | 서울특별시 강남구 선릉로93길 | 6 | 서울특별시 강남구 선릉로93길 6 | 127.047883 | 37.505675 |
| 2 | 프로포즈 | 음식 | 유흥주점 | 호프/맥주 | 서울특별시 | 금천구 | 독산3동 | 독산동 | 대지 | 162 | 서울특별시 금천구 독산동 162-1 | 서울특별시 금천구 가산로 | 34 | 서울특별시 금천구 가산로 34-6 | 126.899220 | 37.471711 |
| 3 | 싱싱커피&토스트 | 음식 | 패스트푸드 | 토스트전문 | 부산광역시 | 사상구 | 괘법동 | 괘법동 | 대지 | 578 | 부산광역시 사상구 괘법동 578 | 부산광역시 사상구 괘감로 | 37 | 부산광역시 사상구 괘감로 37 | 128.980455 | 35.159774 |
| 4 | 가락사우나내스낵 | 생활서비스 | 대중목욕탕/휴게 | 사우나/증기탕/온천 | 서울특별시 | 송파구 | 석촌동 | 석촌동 | 대지 | 256 | 서울특별시 송파구 석촌동 256 | 서울특별시 송파구 가락로 | 71 | 서울특별시 송파구 가락로 71 | 127.104071 | 37.500249 |
#끝에서 5개의 행과 , 오른쪽에서 5개의 열을 가져오기
df.iloc[-5:,-5:]
| 도로명 | 건물본번지 | 도로명주소 | 경도 | 위도 | |
|---|---|---|---|---|---|
| 573675 | 서울특별시 마포구 마포대로14길 | 4 | 서울특별시 마포구 마포대로14길 4 | 126.955059 | 37.548618 |
| 573676 | 서울특별시 성동구 성수일로8길 | 37 | 서울특별시 성동구 성수일로8길 37 | 127.054615 | 37.545853 |
| 573677 | 서울특별시 강남구 강남대로 | 492 | 서울특별시 강남구 강남대로 492 | 127.024102 | 37.506202 |
| 573678 | 서울특별시 영등포구 국제금융로 | 10 | 서울특별시 영등포구 국제금융로 10 | 126.924863 | 37.525172 |
| 573679 | 서울특별시 도봉구 도봉로114길 | 22 | 서울특별시 도봉구 도봉로114길 22-8 | 127.035145 | 37.647099 |
기술통계값 보기
# describe() 기술통계값을 볼 수 있다.
df.describe()
| 지번본번지 | 건물본번지 | 경도 | 위도 | |
|---|---|---|---|---|
| count | 573680.000000 | 573680.000000 | 573680.000000 | 573680.000000 |
| mean | 469.281810 | 153.912094 | 127.596287 | 36.854698 |
| std | 484.778049 | 276.980935 | 0.941262 | 1.081285 |
| min | 1.000000 | 0.000000 | 126.768169 | 35.006760 |
| 25% | 109.000000 | 20.000000 | 126.968316 | 35.215422 |
| 50% | 335.000000 | 50.000000 | 127.047672 | 37.511207 |
| 75% | 678.000000 | 172.000000 | 128.986938 | 37.560362 |
| max | 9999.000000 | 3318.000000 | 129.292243 | 37.692398 |
df[["위도","경도"]].describe()
| 위도 | 경도 | |
|---|---|---|
| count | 573680.000000 | 573680.000000 |
| mean | 36.854698 | 127.596287 |
| std | 1.081285 | 0.941262 |
| min | 35.006760 | 126.768169 |
| 25% | 35.215422 | 126.968316 |
| 50% | 37.511207 | 127.047672 |
| 75% | 37.560362 | 128.986938 |
| max | 37.692398 | 129.292243 |
# 결측치를 제외한 값의 갯수를 계산
df["위도"].count()
573680
#평균
df["위도"].max()
37.69239838166121
#최솟값
df["위도"].min()
35.0067597383124
#1 사분위 수(25%)
df["위도"].quantile(q=0.25)
35.21542173433561
# 중앙값
df["위도"].median()
37.5112070048312
#평균
df["위도"].mean()
36.85469787421801
# 분산
df["위도"].var()
1.1691762199811755
# 표준편차1
import numpy as np
np.sqrt(df["위도"].var())
1.0812845231395738
# 표준편차2
df["위도"].std()
1.0812845231395738
단변량 수치형 변수 시각화
# 위도의 distplot을 그린다.
sns.distplot(df["위도"])
# bins로 막대그리프 갯수를 정할 수 있다.
<matplotlib.axes._subplots.AxesSubplot at 0x24d06547250>

# 경도의 distplot을 그린다.
sns.distplot(df["경도"])
<matplotlib.axes._subplots.AxesSubplot at 0x24d06e602b0>

# 위도의 평균, 중앙값의 표현, color로 선의 색상을 linestyle로 점선으로 표시
plt.axvline(df["위도"].mean(), linestyle=":", color="r")
plt.axvline(df["위도"].median(), linestyle="--", color="b")
sns.distplot(df["위도"])
<matplotlib.axes._subplots.AxesSubplot at 0x24d06513eb0>

상관계수 구하기
# 각 변수의 상관계수
corr = df.corr()
corr
| 지번본번지 | 건물본번지 | 경도 | 위도 | |
|---|---|---|---|---|
| 지번본번지 | 1.000000 | 0.057987 | 0.182678 | -0.196658 |
| 건물본번지 | 0.057987 | 1.000000 | 0.000255 | 0.004606 |
| 경도 | 0.182678 | 0.000255 | 1.000000 | -0.994711 |
| 위도 | -0.196658 | 0.004606 | -0.994711 | 1.000000 |
#위에서 구한 상관계수를 시각화
sns.heatmap(corr, annot=True, cmap="Blues" ) # annot=True 값도 표시 # Blues색으로 표현
<matplotlib.axes._subplots.AxesSubplot at 0x24d285bd3d0>

mask = np.triu(np.ones_like(corr, dtype=np.bool))
sns.heatmap(corr, annot=True, cmap="Blues", mask=mask)
<matplotlib.axes._subplots.AxesSubplot at 0x24d070f9d00>

산점도로 이변량 수치형 변수 표현
# scatterplot 으로 경도와 위도를 표현하며,
# 데이터의 갯수가 많으면 오래 걸리기 때문에 1000 개의 샘플을 추출해서 그립니다.
sns.scatterplot(data=df.sample(1000), x="경도", y="위도")
<matplotlib.axes._subplots.AxesSubplot at 0x24d076b5e20>

# 위 시각화에서 회귀선을 그리기
sns.regplot(data=df.sample(1000), x="경도", y="위도")
<matplotlib.axes._subplots.AxesSubplot at 0x24d0779f160>

# 회귀선을 그리는 그래프의 서브플롯을 그리기
sns.lmplot(data=df.sample(1000), x="경도", y="위도", hue="시도명",col="시도명",truncate=False, fit_reg=True)
<seaborn.axisgrid.FacetGrid at 0x24d077aebb0>

object타입의 데이터 요약
# object 타입 문자열 데이터 요약
df.describe(include="object")
| 상호명 | 상권업종대분류명 | 상권업종중분류명 | 상권업종소분류명 | 시도명 | 시군구명 | 행정동명 | 법정동명 | 대지구분명 | 지번주소 | 도로명 | 도로명주소 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| count | 573679 | 573680 | 573680 | 573680 | 573680 | 573680 | 573680 | 573680 | 573680 | 573680 | 573680 | 573680 |
| unique | 378758 | 9 | 94 | 709 | 2 | 39 | 629 | 648 | 2 | 190237 | 18001 | 190486 |
| top | 점프셈교실 | 음식 | 한식 | 한식/백반/한정식 | 서울특별시 | 강남구 | 역삼1동 | 역삼동 | 대지 | 부산광역시 부산진구 부전동 503-15 | 서울특별시 서초구 신반포로 | 부산광역시 부산진구 가야대로 772 |
| freq | 2297 | 185516 | 59725 | 38133 | 407376 | 47080 | 10400 | 12102 | 572913 | 1058 | 3543 | 1058 |
# 상권업종대분류명의 요약값
df["상권업종대분류명"].describe()
count 573680
unique 9
top 음식
freq 185516
Name: 상권업종대분류명, dtype: object
#상권업종대분류명 의 unique값
df["상권업종대분류명"].unique()
array(['음식', '생활서비스', '소매', '의료', '학문/교육', '관광/여가/오락', '부동산', '숙박', '스포츠'],
dtype=object)
#상권업종대분류명 의 unique 개수
df["상권업종대분류명"].nunique()
9
df["상권업종대분류명"].mode() # mode 최빈값
0 음식
dtype: object
# 범주형 변수 의 빈도수
df["상권업종대분류명"].value_counts()
음식 185516
소매 179460
생활서비스 97789
학문/교육 42477
의료 25509
부동산 20918
관광/여가/오락 16377
숙박 5327
스포츠 307
Name: 상권업종대분류명, dtype: int64
인덱싱과 필터로 서브셋 만들기
# "상권업종대분류명" 이 "음식인 데이터만 가져오기
# df_food 라는 변수에 담아줍니다. 서브셋을 새로운 변수에 저장할 때 copy()를 사용하는 것을 권장
df_food = df[df["상권업종대분류명"] == "음식"].copy()
df_food.head()
| 상호명 | 상권업종대분류명 | 상권업종중분류명 | 상권업종소분류명 | 시도명 | 시군구명 | 행정동명 | 법정동명 | 대지구분명 | 지번본번지 | 지번주소 | 도로명 | 건물본번지 | 도로명주소 | 경도 | 위도 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 와라와라호프 | 음식 | 유흥주점 | 호프/맥주 | 서울특별시 | 강남구 | 대치1동 | 대치동 | 대지 | 604 | 서울특별시 강남구 대치동 604 | 서울특별시 강남구 남부순환로 | 2933 | 서울특별시 강남구 남부순환로 2933 | 127.061026 | 37.493922 |
| 1 | 커피빈코리아선릉로93길점 | 음식 | 커피점/카페 | 커피전문점/카페/다방 | 서울특별시 | 강남구 | 역삼1동 | 역삼동 | 대지 | 696 | 서울특별시 강남구 역삼동 696-42 | 서울특별시 강남구 선릉로93길 | 6 | 서울특별시 강남구 선릉로93길 6 | 127.047883 | 37.505675 |
| 2 | 프로포즈 | 음식 | 유흥주점 | 호프/맥주 | 서울특별시 | 금천구 | 독산3동 | 독산동 | 대지 | 162 | 서울특별시 금천구 독산동 162-1 | 서울특별시 금천구 가산로 | 34 | 서울특별시 금천구 가산로 34-6 | 126.899220 | 37.471711 |
| 3 | 싱싱커피&토스트 | 음식 | 패스트푸드 | 토스트전문 | 부산광역시 | 사상구 | 괘법동 | 괘법동 | 대지 | 578 | 부산광역시 사상구 괘법동 578 | 부산광역시 사상구 괘감로 | 37 | 부산광역시 사상구 괘감로 37 | 128.980455 | 35.159774 |
| 5 | 초밥왕 | 음식 | 일식/수산물 | 음식점-초밥전문 | 서울특별시 | 송파구 | 잠실6동 | 신천동 | 대지 | 7 | 서울특별시 송파구 신천동 7-28 | 서울특별시 송파구 올림픽로 | 293 | 서울특별시 송파구 올림픽로 293-19 | 127.102490 | 37.515149 |
강남구의 상권업종대분류가 음식만 보기
df[df["시군구명"] == "강남구"].head()
| 상호명 | 상권업종대분류명 | 상권업종중분류명 | 상권업종소분류명 | 시도명 | 시군구명 | 행정동명 | 법정동명 | 대지구분명 | 지번본번지 | 지번주소 | 도로명 | 건물본번지 | 도로명주소 | 경도 | 위도 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 와라와라호프 | 음식 | 유흥주점 | 호프/맥주 | 서울특별시 | 강남구 | 대치1동 | 대치동 | 대지 | 604 | 서울특별시 강남구 대치동 604 | 서울특별시 강남구 남부순환로 | 2933 | 서울특별시 강남구 남부순환로 2933 | 127.061026 | 37.493922 |
| 1 | 커피빈코리아선릉로93길점 | 음식 | 커피점/카페 | 커피전문점/카페/다방 | 서울특별시 | 강남구 | 역삼1동 | 역삼동 | 대지 | 696 | 서울특별시 강남구 역삼동 696-42 | 서울특별시 강남구 선릉로93길 | 6 | 서울특별시 강남구 선릉로93길 6 | 127.047883 | 37.505675 |
| 26 | 쉼터 | 음식 | 분식 | 라면김밥분식 | 서울특별시 | 강남구 | 삼성1동 | 삼성동 | 대지 | 159 | 서울특별시 강남구 삼성동 159 | 서울특별시 강남구 봉은사로 | 524 | 서울특별시 강남구 봉은사로 524 | 127.057100 | 37.512939 |
| 27 | 배제현의웰빙낙지한마리수제비 | 음식 | 일식/수산물 | 낙지/오징어 | 서울특별시 | 강남구 | 신사동 | 신사동 | 대지 | 512 | 서울특별시 강남구 신사동 512-13 | 서울특별시 강남구 강남대로152길 | 19 | 서울특별시 강남구 강남대로152길 19 | 127.020945 | 37.517574 |
| 38 | 타워광명내과의원 | 의료 | 병원 | 내과/외과 | 서울특별시 | 강남구 | 도곡2동 | 도곡동 | 대지 | 467 | 서울특별시 강남구 도곡동 467-14 | 서울특별시 강남구 언주로30길 | 39 | 서울특별시 강남구 언주로30길 39 | 127.053198 | 37.488742 |
# 시군구명이 강남구, 사우건업종대분류명이 음식인것
# 상권업종중분류명 별로 빈도수를 구하기
df[(df["시군구명"] == "강남구") &
(df["상권업종대분류명"] == "음식")]["상권업종중분류명"].value_counts()
한식 4371
커피점/카페 2790
유흥주점 1573
양식 1573
일식/수산물 1255
분식 1197
패스트푸드 786
제과제빵떡케익 650
닭/오리요리 539
중식 358
별식/퓨전요리 341
부페 63
기타음식업 47
음식배달서비스 11
Name: 상권업종중분류명, dtype: int64
# 위와 똑같이 구하고 loc 이용하기
df.loc[(df["시군구명"] == "강남구") &
(df["상권업종대분류명"] == "음식"), "상권업종중분류명"].value_counts()
한식 4371
커피점/카페 2790
유흥주점 1573
양식 1573
일식/수산물 1255
분식 1197
패스트푸드 786
제과제빵떡케익 650
닭/오리요리 539
중식 358
별식/퓨전요리 341
부페 63
기타음식업 47
음식배달서비스 11
Name: 상권업종중분류명, dtype: int64
구별 음식점 업종 비교하기
# df_seoul_food 에 "시도명"이 "서울특별시" 이고 "상권업종대분류명" 이 "음식" 에 대한 서브셋만 가져오기
df_seoul_food = df[(df["시도명"] == "서울특별시") & (df["상권업종대분류명"] == "음식")].copy()
df_seoul_food.shape
(132889, 16)
# "시군구명", "상권업종중분류명" 으로 그룹화
# 결과를 food_gu 에 담아 재사용할 예정
food_gu = df_seoul_food.groupby(["시군구명", "상권업종중분류명"])["상호명"].count()
food_gu.head()
시군구명 상권업종중분류명
강남구 기타음식업 47
닭/오리요리 539
별식/퓨전요리 341
부페 63
분식 1197
Name: 상호명, dtype: int64
# food_gu 에 담긴 데이터로 시각화
# 상권업종 중분류명과 상점수로 barplot 그리기
food_gu.unstack().plot.bar()
#unstack으로 피벗테이블로 바꾼다
<matplotlib.axes._subplots.AxesSubplot at 0x24d0cf03c10>

food_gu.unstack().iloc[:5, :5]
| 상권업종중분류명 | 기타음식업 | 닭/오리요리 | 별식/퓨전요리 | 부페 | 분식 |
|---|---|---|---|---|---|
| 시군구명 | |||||
| 강남구 | 47.0 | 539.0 | 341.0 | 63.0 | 1197.0 |
| 강동구 | 4.0 | 318.0 | 138.0 | 24.0 | 509.0 |
| 강북구 | 2.0 | 208.0 | 97.0 | 6.0 | 329.0 |
| 강서구 | 16.0 | 323.0 | 145.0 | 21.0 | 531.0 |
| 관악구 | 11.0 | 324.0 | 118.0 | 11.0 | 461.0 |
food = food_gu.reset_index()
food = food.rename(columns={"상호명":"상호수"})
food.head()
| 시군구명 | 상권업종중분류명 | 상호수 | |
|---|---|---|---|
| 0 | 강남구 | 기타음식업 | 47 |
| 1 | 강남구 | 닭/오리요리 | 539 |
| 2 | 강남구 | 별식/퓨전요리 | 341 |
| 3 | 강남구 | 부페 | 63 |
| 4 | 강남구 | 분식 | 1197 |
plt.figure(figsize=(15,4))
sns.barplot(data=food, x="시군구명", y="상호수")
# 검은색은 신뢰구간
<matplotlib.axes._subplots.AxesSubplot at 0x24d070571c0>

# catplot으로 사용하여 서브프롯을 그리기
sns.catplot(data=food, x="시군구명", y="상호수",
kind="bar", col="상권업종중분류명", col_wrap=4)
<seaborn.axisgrid.FacetGrid at 0x24d0d999310>

구별 학원수 비교
df["상권업종대분류명"].unique()
# 학문/교육
array(['음식', '생활서비스', '소매', '의료', '학문/교육', '관광/여가/오락', '부동산', '숙박', '스포츠'],
dtype=object)
# 시도명이 서울특별시이고, 상권업종대분류명이 학문/교육인 데이터 셋
df_academy = df[(df["시도명"] == "서울특별시") & (df["상권업종대분류명"] == "학문/교육")].copy()
df_academy
| 상호명 | 상권업종대분류명 | 상권업종중분류명 | 상권업종소분류명 | 시도명 | 시군구명 | 행정동명 | 법정동명 | 대지구분명 | 지번본번지 | 지번주소 | 도로명 | 건물본번지 | 도로명주소 | 경도 | 위도 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 85 | GIA보석교육원 | 학문/교육 | 학원-자격/국가고시 | 학원-보석감정 | 서울특별시 | 강남구 | 압구정동 | 신사동 | 대지 | 639 | 서울특별시 강남구 신사동 639-3 | 서울특별시 강남구 압구정로 | 320 | 서울특별시 강남구 압구정로 320 | 127.036437 | 37.528532 |
| 101 | 안재형영어 | 학문/교육 | 학원-어학 | 학원-외국어/어학 | 서울특별시 | 양천구 | 목5동 | 목동 | 대지 | 905 | 서울특별시 양천구 목동 905-34 | 서울특별시 양천구 목동서로 | 133 | 서울특별시 양천구 목동서로 133-2 | 126.875973 | 37.531592 |
| 121 | 정아트 | 학문/교육 | 학원-음악미술무용 | 서예/서화/미술 | 서울특별시 | 강서구 | 염창동 | 염창동 | 대지 | 184 | 서울특별시 강서구 염창동 184-8 | 서울특별시 강서구 양천로73가길 | 21 | 서울특별시 강서구 양천로73가길 21 | 126.873645 | 37.550924 |
| 126 | 경찰태권도 | 학문/교육 | 학원-예능취미체육 | 태권도장 | 서울특별시 | 성북구 | 길음1동 | 길음동 | 대지 | 1283 | 서울특별시 성북구 길음동 1283-4 | 서울특별시 성북구 길음로 | 20 | 서울특별시 성북구 길음로 20 | 127.023020 | 37.604749 |
| 134 | 아트인스튜디오 | 학문/교육 | 학원-음악미술무용 | 서예/서화/미술 | 서울특별시 | 강남구 | 역삼1동 | 역삼동 | 대지 | 818 | 서울특별시 강남구 역삼동 818-1 | 서울특별시 강남구 강남대로96길 | 12 | 서울특별시 강남구 강남대로96길 12 | 127.028054 | 37.499729 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 573529 | 쌤통수학교습소 | 학문/교육 | 학원-보습교습입시 | 학원-입시 | 서울특별시 | 서대문구 | 홍제2동 | 홍제동 | 대지 | 106 | 서울특별시 서대문구 홍제동 106 | 서울특별시 서대문구 통일로34길 | 24 | 서울특별시 서대문구 통일로34길 24 | 126.949389 | 37.585709 |
| 573654 | 골든벨독서실 | 학문/교육 | 도서관/독서실 | 독서실 | 서울특별시 | 양천구 | 신월2동 | 신월동 | 대지 | 447 | 서울특별시 양천구 신월동 447-5 | 서울특별시 양천구 월정로 | 56 | 서울특별시 양천구 월정로 56 | 126.841706 | 37.524719 |
| 573656 | 에이디링크연구소 | 학문/교육 | 학원기타 | 학원(종합) | 서울특별시 | 송파구 | 가락본동 | 가락동 | 대지 | 76 | 서울특별시 송파구 가락동 76 | 서울특별시 송파구 양재대로62길 | 47 | 서울특별시 송파구 양재대로62길 47 | 127.120757 | 37.495986 |
| 573661 | 도무스링구아 | 학문/교육 | 학원-보습교습입시 | 학원-입시 | 서울특별시 | 서초구 | 양재1동 | 우면동 | 대지 | 721 | 서울특별시 서초구 우면동 721-1 | 서울특별시 서초구 태봉로 | 70 | 서울특별시 서초구 태봉로 70 | 127.025571 | 37.464531 |
| 573662 | 아소비 | 학문/교육 | 학원-보습교습입시 | 학원-입시 | 서울특별시 | 구로구 | 고척1동 | 고척동 | 대지 | 327 | 서울특별시 구로구 고척동 327 | 서울특별시 구로구 중앙로6길 | 17 | 서울특별시 구로구 중앙로6길 17 | 126.865601 | 37.500695 |
31509 rows × 16 columns
#df_academy 에서 상호명으로 빈도수 구하기
df_academy["상호명"].value_counts().head(10)
점프셈교실 1659
해법수학 57
윤선생영어교실 34
뮤엠영어 27
해법영어교실 24
눈높이 22
해동검도 22
삼성영어 21
구몬학습 20
경희대태권도 19
Name: 상호명, dtype: int64
#"시군구명"으로 빈도수 구하기
df_academy["시군구명"].value_counts()
강남구 4005
서초구 2103
양천구 1881
광진구 1848
송파구 1797
강동구 1585
노원구 1582
강서구 1498
은평구 1333
관악구 1313
성북구 1246
구로구 1140
동대문구 1051
동작구 1050
마포구 1007
영등포구 984
도봉구 931
중랑구 884
서대문구 773
성동구 742
금천구 701
종로구 638
강북구 513
용산구 491
중구 413
Name: 시군구명, dtype: int64
# 상권업종소분류명 으로 빈도수를 구하고 위에서 30개만 보기
academy_count = df_academy["상권업종소분류명"].value_counts().head(30)
academy_count
학원-입시 7509
학원(종합) 4561
어린이집 4395
학원-외국어/어학 3544
피아노/바이올린/기타 2868
서예/서화/미술 1595
독서실 1096
고시원 1062
학원-기타 677
태권도장 610
학습지보급 430
학원-어린이영어 319
컴퓨터학원 270
학원-스포츠/재즈댄스 269
학원-무용 220
놀이방 139
학원-주산암산부기속셈 122
유아교육기관기타 107
학원-미용 106
학원-배우/탤런트 102
합기도장 96
검도도장 95
실내놀이터-유아 84
학원-요리 78
학원-간호조무사 76
학원/국가고시 70
학원-사교춤 54
유도장 49
학원-심리변론 46
학원-국악 45
Name: 상권업종소분류명, dtype: int64
# 상권업종소분류명으로 빈도수를 구하고
# 빈도수가 1000개 이상인 데이터 보기
academy_count_1000 = academy_count[academy_count > 1000]
academy_count_1000
학원-입시 7509
학원(종합) 4561
어린이집 4395
학원-외국어/어학 3544
피아노/바이올린/기타 2868
서예/서화/미술 1595
독서실 1096
고시원 1062
Name: 상권업종소분류명, dtype: int64
# "시군구명", "상권업종소분류명" 으로 그룹화를 하고 "상호명"으로 빈도수를 계산
g_academy = df_academy.groupby(["시군구명", "상권업종소분류명"])["상호명"].count()
g_academy = g_academy.reset_index()
g_academy.columns = ["시군구명", "상권업종소분류명", "상호수"]
g_academy.head()
| 시군구명 | 상권업종소분류명 | 상호수 | |
|---|---|---|---|
| 0 | 강남구 | 검도도장 | 9 |
| 1 | 강남구 | 고시원 | 139 |
| 2 | 강남구 | 놀이방 | 8 |
| 3 | 강남구 | 독서실 | 125 |
| 4 | 강남구 | 서예/서화/미술 | 219 |
seaborn으로 시각화 하기
# 위에서 구한 결과를 시군구명, 상호수로 barplot을 그림
plt.figure(figsize=(15, 4))
sns.barplot(data=g_academy, x="시군구명", y="상호수")
# ci=None으로 신뢰구간 없애기 가능
<matplotlib.axes._subplots.AxesSubplot at 0x24d0d9d3040>

isin을 사용해서 서브셋 만들기
academy_count_1000.index
Index(['학원-입시', '학원(종합)', '어린이집', '학원-외국어/어학', '피아노/바이올린/기타', '서예/서화/미술',
'독서실', '고시원'],
dtype='object')
# isin 으로 빈도수로 계산했을 때 1000개 이상인 데이터만 가져와서 봅니다.
# 서브셋을 df_academy_selected 에 저장합니다.
print(df_academy.shape)
df_academy_selected = df_academy[
df_academy["상권업종소분류명"].isin(academy_count_1000.index)].copy()
df_academy_selected.shape
(31509, 16)
(26630, 16)
df_academy_selected["상권업종소분류명"].value_counts()
학원-입시 7509
학원(종합) 4561
어린이집 4395
학원-외국어/어학 3544
피아노/바이올린/기타 2868
서예/서화/미술 1595
독서실 1096
고시원 1062
Name: 상권업종소분류명, dtype: int64
# df_academy_selected 의 "시군구명"으로 빈도수를 셉니다.
df_academy_selected["시군구명"].value_counts()
강남구 3410
서초구 1732
양천구 1706
광진구 1536
송파구 1484
노원구 1425
강서구 1288
강동구 1255
은평구 1162
관악구 1115
성북구 1066
구로구 987
동작구 877
동대문구 863
마포구 857
도봉구 849
영등포구 775
중랑구 745
서대문구 656
성동구 642
금천구 568
종로구 479
강북구 444
용산구 395
중구 314
Name: 시군구명, dtype: int64
df_academy_selected.loc[
df_academy_selected["법정동명"] == "목동",
"상권업종소분류명"].value_counts()
학원-입시 375
학원-외국어/어학 152
학원(종합) 88
어린이집 61
피아노/바이올린/기타 41
서예/서화/미술 39
독서실 22
고시원 7
Name: 상권업종소분류명, dtype: int64
df_academy_selected.loc[
df_academy_selected["법정동명"] == "대치동",
"상권업종소분류명"].value_counts()
학원-입시 831
학원-외국어/어학 281
학원(종합) 211
서예/서화/미술 113
피아노/바이올린/기타 60
독서실 42
고시원 30
어린이집 16
Name: 상권업종소분류명, dtype: int64
# df_academy_selected 로 위에서 했던 그룹화를 복습
# "상권업종소분류명", "시군구명" 으로 그룹화를 하고 "상호명"으로 빈도수를 계산
# g 라는 변수에 담아 재사용 할 예정
g = df_academy_selected.groupby(["상권업종소분류명", "시군구명"])["상호명"].count()
g
상권업종소분류명 시군구명
고시원 강남구 139
강동구 62
강북구 11
강서구 32
관악구 83
...
학원-입시 용산구 70
은평구 337
종로구 75
중구 59
중랑구 172
Name: 상호명, Length: 200, dtype: int64
Pandas 의 plot 으로 시각화
# 상권업종소분류명이 index
# loc를 통해 index 값을 가져올 수 있다.
# 그룹화된 결과 중 "학원-입시" 데이터
g.loc["학원-입시"].sort_values().plot.barh(figsize=(10, 7))
<matplotlib.axes._subplots.AxesSubplot at 0x24d12a1d910>

# 그룹화된 데이터를 시각화 하게 되면 멀티인덱스 값으로 표현이 되어 보기가 어렵습니다.
# 다음 셀부터 이 그래프를 개선해 봐요!
g.plot.bar()
<matplotlib.axes._subplots.AxesSubplot at 0x24d12ae4c70>

#g.unstack()
g.unstack().iloc[:5,:5]
| 시군구명 | 강남구 | 강동구 | 강북구 | 강서구 | 관악구 |
|---|---|---|---|---|---|
| 상권업종소분류명 | |||||
| 고시원 | 139 | 62 | 11 | 32 | 83 |
| 독서실 | 125 | 46 | 14 | 60 | 69 |
| 서예/서화/미술 | 219 | 110 | 19 | 70 | 72 |
| 어린이집 | 189 | 210 | 112 | 262 | 220 |
| 피아노/바이올린/기타 | 266 | 189 | 47 | 150 | 139 |
# 행과 열을 바꾸기
g.unstack().T.iloc[:5,:5]
| 상권업종소분류명 | 고시원 | 독서실 | 서예/서화/미술 | 어린이집 | 피아노/바이올린/기타 |
|---|---|---|---|---|---|
| 시군구명 | |||||
| 강남구 | 139 | 125 | 219 | 189 | 266 |
| 강동구 | 62 | 46 | 110 | 210 | 189 |
| 강북구 | 11 | 14 | 19 | 112 | 47 |
| 강서구 | 32 | 60 | 70 | 262 | 150 |
| 관악구 | 83 | 69 | 72 | 220 | 139 |
# 그룹화된 결과에 unstack 을 사용하면 마지막 인덱스 컬럼이 컬럼으로 바꿈
g.unstack().plot.barh(figsize=(8,9))
<matplotlib.axes._subplots.AxesSubplot at 0x24d13123f70>

# T는 transpose이다.
g.unstack().T.plot.bar(figsize=(15, 5))
<matplotlib.axes._subplots.AxesSubplot at 0x24d17ebaeb0>

# 그룹화한 값의 인덱스
g.index
MultiIndex([( '고시원', '강남구'),
( '고시원', '강동구'),
( '고시원', '강북구'),
( '고시원', '강서구'),
( '고시원', '관악구'),
( '고시원', '광진구'),
( '고시원', '구로구'),
( '고시원', '금천구'),
( '고시원', '노원구'),
( '고시원', '도봉구'),
...
('학원-입시', '성동구'),
('학원-입시', '성북구'),
('학원-입시', '송파구'),
('학원-입시', '양천구'),
('학원-입시', '영등포구'),
('학원-입시', '용산구'),
('학원-입시', '은평구'),
('학원-입시', '종로구'),
('학원-입시', '중구'),
('학원-입시', '중랑구')],
names=['상권업종소분류명', '시군구명'], length=200)
# 멀티인덱스 보기쉽게
t = g.reset_index()
t = t.rename(columns={"상호명":"상호수"})
t
| 상권업종소분류명 | 시군구명 | 상호수 | |
|---|---|---|---|
| 0 | 고시원 | 강남구 | 139 |
| 1 | 고시원 | 강동구 | 62 |
| 2 | 고시원 | 강북구 | 11 |
| 3 | 고시원 | 강서구 | 32 |
| 4 | 고시원 | 관악구 | 83 |
| ... | ... | ... | ... |
| 195 | 학원-입시 | 용산구 | 70 |
| 196 | 학원-입시 | 은평구 | 337 |
| 197 | 학원-입시 | 종로구 | 75 |
| 198 | 학원-입시 | 중구 | 59 |
| 199 | 학원-입시 | 중랑구 | 172 |
200 rows × 3 columns
같은 그래프를 seaborn으로 그리기
# 상권업종소분류명으로 색상을 다르게 표현
plt.figure(figsize=(15,4))
sns.barplot(data=t, x="시군구명", y="상호수",ci=None)
<matplotlib.axes._subplots.AxesSubplot at 0x24d178aeee0>

# 시군구명 색상을 다르게 표현
plt.figure(figsize=(15,4))
sns.barplot(data=t, x="상권업종소분류명", y="상호수",ci=None)
<matplotlib.axes._subplots.AxesSubplot at 0x24d17bbbbb0>

# 상권업종소분류명이 학원-입시인 서브셋만 가져와서 시각화
academy_sub = t[t["상권업종소분류명"] == "학원-입시"].copy()
print(academy_sub.shape)
plt.figure(figsize=(15,4))
sns.barplot(data=academy_sub, x="시군구명", y="상호수")
(25, 3)
<matplotlib.axes._subplots.AxesSubplot at 0x24d17b0a160>

# catplot을 통해 그리기
sns.catplot(data =t, x="상권업종소분류명", y="상호수", kind="bar", col="시군구명",
col_wrap=4, sharex=False)
<seaborn.axisgrid.FacetGrid at 0x24d17d17760>

경도와 위도를 scatterplot으로 표현
#scatterplot으로 경도 위도 표현, 시군구명으로 색상을 다르게
plt.figure(figsize=(10, 7))
sns.scatterplot(data=df_academy_selected, x="경도", y="위도", hue="시군구명")
<matplotlib.axes._subplots.AxesSubplot at 0x24d2081ec40>

# 상권업종소분류명으로 색상을 다르게
plt.figure(figsize=(10, 7))
sns.scatterplot(data=df_academy_selected, x="경도", y="위도", hue="상권업종소분류명")
<matplotlib.axes._subplots.AxesSubplot at 0x24d24596c40>

# 상권업종소분류명이 학원-입시인 데이터만 그리기
plt.figure(figsize=(10, 7))
sns.scatterplot(
data=df_academy_selected[df_academy_selected["상권업종소분류명"] == "학원-입시"],
x="경도", y="위도", hue="상권업종소분류명")
<matplotlib.axes._subplots.AxesSubplot at 0x24d24fd41f0>

# 상권업종소분류명이 어린이집인 데이터만 그리기
plt.figure(figsize=(10, 7))
sns.scatterplot(
data=df_academy_selected[df_academy_selected["상권업종소분류명"] == "어린이집"],
x="경도", y="위도", hue="상권업종소분류명")
<matplotlib.axes._subplots.AxesSubplot at 0x24d17a65760>

# 상권업종소분류명이 어린이집과 학원-입시인것만 보기
plt.figure(figsize=(10, 7))
sns.scatterplot(
data=df_academy_selected[df_academy_selected["상권업종소분류명"].isin(["어린이집","학원-입시"])],
x="경도", y="위도", hue="상권업종소분류명")
<matplotlib.axes._subplots.AxesSubplot at 0x24d24fc4940>

folium 으로 지도에 자세히 표현하기
# 학원-입시에 대한 상호 데이터를 지도에 시각화
import folium
long = df_academy_selected["경도"].mean()
lat = df_academy_selected["위도"].mean()
df_m = df_academy_selected[
df_academy_selected["상권업종소분류명"].isin(["어린이집", "학원-입시"])]
df_m = df_m.sample(1000) # 10000개중에 천개만 뽑기
df_m.shape
(1000, 16)
m = folium.Map(location=[lat, long], zoom_start=12)
folium.Marker([37.5545, 126.867], tooltip="해법수학").add_to(m)
m
m.save('index.html')
df_m.index
Int64Index([215750, 547772, 206446, 2764, 294827, 344741, 254574, 23980,
492177, 542639,
...
29611, 504010, 504878, 195984, 183872, 100263, 341046, 488051,
343393, 340195],
dtype='int64', length=1000)
for i in df_m.index[:10]:
tooltip = df_m.loc[i, "상호명"] +"-"+ df_m.loc[i, "도로명주소"]
lat = df_m.loc[i, "위도"]
long = df_m.loc[i, "경도"]
print(tooltip, lat, long)
이앤씨중국어학원-서울특별시 양천구 중앙로32길 61 37.52007048583621 126.860285482948
김동하국어논술-서울특별시 송파구 위례성대로20길 28 37.508990067945795 127.127085790274
트리니타스학원-서울특별시 강남구 삼성로 38 37.4886790644454 127.066824789888
분석수학-서울특별시 강서구 강서로 289 37.551594718354295 126.83596025326901
일공교육그룹-서울특별시 서초구 서초대로46길 19-18 37.49163218142171 127.011151105667
튼튼어린이집-서울특별시 은평구 갈현로31길 14-9 37.62056046519629 126.914530631335
해법영수학원-서울특별시 노원구 노원로28길 9 37.6530158859823 127.06845526207199
배화여자대학사직어린이집-서울특별시 종로구 필운대로1길 16-8 37.57810285378061 126.96868574886601
예랑어린이집-서울특별시 강동구 고덕로 210 37.553126080293204 127.14836913597601
개인과외-서울특별시 도봉구 해등로 113 37.6535161376325 127.039822243456
m = folium.Map(location=[lat, long], zoom_start=12,
tiles='Stamen Toner')
#Stamen Toner 스타일 바꿈
for i in df_m.index[:100]:
tooltip = df_m.loc[i, "상호명"] +"-"+ df_m.loc[i, "도로명주소"]
lat = df_m.loc[i, "위도"]
long = df_m.loc[i, "경도"]
folium.CircleMarker([lat, long], tooltip=tooltip, radius=3).add_to(m)
#radius=3 마커크기 줄이기
m
