-
인구 통계 분석 - 위키피디아 크롤링 및 데이터 분석 02빅데이터/Data-Analysis 2022. 3. 5. 13:19
유투버 'todaycode오늘코드'님 강의 참조
- 통계청 데이터 '출생아수'로 진행 예정
01 데이터 준비
*데이터 다운로드 주소 https://kosis.kr/statHtml/statHtml.do?orgId=101&tblId=INH_1B81A01&vw_cd=MT_GTITLE01&list_id=101&seqNo=&lang_mode=ko&language=kor&obj_var_id=&itm_id=&conn_path=MT_GTITLE01
import pandas as pd df_kosis = pd.read_csv('출생아수_시도_시_군_구__20220305113211.csv',encoding='cp949') df_kosis.head() df_kosis.shape (19, 865)
02 데이터 전처리
분석전에는 판다스를 쉽게 쓰기 위해 피벗테이블 형태가 아닌 컬럼형태로 만들어 줘야 한다. 시군구별, 년도월 등을 따로 만들어야 쓰기 편하다
- 또한 데이터를 잘 들여다 보면 전체는 .월, 남자는 .01.1, 여자는 .01.2 로 되어있다. 즉 계(명), 남자(명), 여자(명)이 한번 더 열로 표현되는데 없애줘도 된다.
- 판다스에서는 자동적으로 열을 없애고 데이터를 알아서 맞춰주는 .melt()라이브러리가 있다.
df_kosis.melt(id_vars='시군구별')
.melt()를 하게되면 시군구별/년월 컬럼이 없어지고 이 두개의 컬럼이 행으로 녹아든게 보인다 ▶ 조금 더 깊게 데이터 들여다 보기
df = df_kosis.melt(id_vars='시군구별') df.head()
- .melt() 이후에도 0번째 컬럼에 시군구별이라고 해서 뭔가 겹치는 데이터 혹은 필요없는 컬럼들을 들고 있는 열이 보인다.
df['시군구별'].unique() array(['시군구별', '전국', '서울특별시', '부산광역시', '대구광역시', '인천광역시', '광주광역시', '대전광역시', '울산광역시', '세종특별자치시', '경기도', '강원도', '충청북도', '충청남도', '전라북도', '전라남도', '경상북도', '경상남도', '제주특별자치도'], dtype=object)
- 시군구별만 찍어보면 전국 이름이 나오나 하나가 '시군구별' 컬럼이 있다.
# 불리언 인덱싱을 데이터 프레임으로 보는 방법 df[df['시군구별'] == '시군구별']
- 즉 시군구별 컬럼에 시군구별로 되어있는것만 뽑아보면 의미가 없는 데이터라는것을 알 수 있다. 이 값 없이 데이터 프레임을 만들자
# 필요 없는 컬럼 제거 print(df.shape) df = df[df['시군구별'] != '시군구별'].copy() df.shape (16416, 3) (15552, 3) df['시군구별'].unique() array(['전국', '서울특별시', '부산광역시', '대구광역시', '인천광역시', '광주광역시', '대전광역시', '울산광역시', '세종특별자치시', '경기도', '강원도', '충청북도', '충청남도', '전라북도', '전라남도', '경상북도', '경상남도', '제주특별자치도'], dtype=object)
▶ 년도, 월, 성별, 텍스트 데이터 전처리
- 아직 전처리가 조금 남아 있다
1. 'variable' 컬럼 수정
# 년도, 월, 성별, 텍스트 데이터 전처리 df['variable'] 1 1997.01 2 1997.01 3 1997.01 4 1997.01 5 1997.01 ... -> 먼저 전체/남녀 구분을 해줘야 한다
# 남/녀/전체 구분 # expand='True' 를 하면 스플릿 한 부분대로 나눠서 데이터 프레임을 만듬 df['variable'].str.split('.', expand=True)
# 남/녀/전체 구분 # expand='True' 를 하면 스플릿 한 부분대로 나눠서 데이터 프레임을 만듬 df['연도'] = df['variable'].str.split('.', expand=True)[0] df.head()
# 남/녀/전체 구분 # expand='True' 를 하면 스플릿 한 부분대로 나눠서 데이터 프레임을 만듬 df['연도'] = df['variable'].str.split('.', expand=True)[0] df['월'] = df['variable'].str.split('.', expand=True)[1] # 0(None)=전체, 1=남자, 2=여자 df['성별'] = df['variable'].str.split('.', expand=True)[2] df.head() df['성별'].unique() array([None, '1', '2'], dtype=object) -> 타입이 오브젝트인것을 주의
# None값 처리 df['성별'] = df['성별'].fillna('전체') # 번호 처리 df['성별'] = df['성별'].replace('1', '남자').replace('2','여자') df['성별'].unique() array(['전체', '남자', '여자'], dtype=object) df['성별'].value_counts() 전체 5184 남자 5184 여자 5184
2. 컬럼명 수정
# 컬럼명 rename 처리 df = df.rename(columns={'variable':'기간','value':'출생아수'}) df.head()
03 분석 및 시각화
df.info() # Column Non-Null Count Dtype --- ------ -------------- ----- 0 시군구별 15552 non-null object 1 기간 15552 non-null object 2 출생아수 15552 non-null object 3 연도 15552 non-null object 4 월 15552 non-null object 5 성별 15552 non-null object
- 출생아수를 분석 및 시각화해야하는데 'object'형이다. 수치형으로 바꿔 주자
# 출생아수 수치형 변환 df['출생아수'].astype(int) ValueError: invalid literal for int() with base 10: '-' --> 이 오류를 처리 df['출생아수'] = df['출생아수'].replace('-', np.nan) df['출생아수'].astype(int) ValueError: cannot convert float NaN to integer --> 다시 오류 처리 df['출생아수'] = df['출생아수'].astype(float) df['출생아수'].describe() count 15012.000000 mean 3012.725286 std 6587.701782 min 30.000000 25% 621.000000 50% 1025.000000 75% 1908.250000 max 63268.000000 # 0일때 계산하면 아래와 같다 df['출생아수'] = df['출생아수'].replace('-', 0) df['출생아수'].describe() count 15552.000000 mean 2908.116770 std 6495.774215 min 0.000000 25% 589.000000 50% 989.000000 75% 1833.000000 max 63268.000000
- 최종적으로 Nan값을 처리하는데에 있어서 int값으로 바꿀 수 없는데 '0'으로 바꿔서 처리 할 수 도 있다. 하지만 0으로 바꿔버리게 되면 출생아수가 아예 그달 혹은 그 년도에 0이되버리기 때문에 계산에 엄청난 오류가 발생하게된다. 한명도 안낳을수는 날은 없기때문에 그대로 소수점 처리로 바꿔줘야 문제가 없다
▶ 전체 지역 분석
# 전체 지역 분석 df_all = df[(df['시군구별'] == '전국') & (df['성별']=='전체')] df_all.head()
# 시각화 import matplotlib.pyplot as plt plt.rc('font', family = 'Malgun Gothic' ) df_all.set_index(['연도','월']).plot(figsize=(15,4));
전국적으로도 출생아수는 계속해서 감소하고 있고 특정 주기성으로 출생아수가 늘었다 줄었다 하는것을 볼 수 있다 - 이렇계 계절/주기성은 plot형태로 많이 그린다.
df_all[-24:].set_index(['연도','월']).plot.bar(figsize=(15,4));
▶ 'Seaborn' 시각화
import seaborn as sns plt.figure(figsize=(15,4)) sns.barplot(data=df_all, x='연도', y='출생아수') plt.figure(figsize=(15,4)) sns.lineplot(data=df_all, x='연도', y='출생아수')
- 판다스와 시본의 시각화 가장 큰 차이점은 판다스는 정말 데이터 값 그대로 들어가는 반면 시본은 평균값, 신뢰구간등 다 계산을 해서 보여 준다. 즉 판다스로 정확한 수치를 표현하고싶으면 계산을 따로하여 일일히 표시해야한다.
plt.figure(figsize=(15,4)) sns.lineplot(data=df_all, x='연도', y='출생아수', hue='월')
▶ 지역별 분석
# 지역별 분석 df_local = df[df['시군구별'] != '전국'].copy() plt.figure(figsize=(15,4)) sns.pointplot(data=df_local, x='연도', y='출생아수', hue='성별')
전체적으로 계속 줄고 있고 남아가 여아보다 많이 낳아졌다는것을 볼 수 있다 df_local_all = df_local[df_local['성별'] == '전체'] plt.figure(figsize=(15,4)) sns.pointplot(data=df_local_all, x='연도', y='출생아수', hue='시군구별', ci=None) plt.legend(loc='center right', bbox_to_anchor=(1.15, 0.5), ncol=1)
전국적으로 다 줄어들지만 세종특별자치시만 약간씩 증가하는게 보인다 df_local_2 = df_local_all[df_local_all['시군구별'].isin(['서울특별시', '경기도', '세종특별자치시'])] plt.figure(figsize=(15,4)) sns.pointplot(data=df_local_2, x='연도', y='출생아수', ci=None, hue='시군구별')
▶ 세종 특별시만 보자
df_sj = df[df['시군구별'] == '세종특별자치시'].dropna(how='any') plt.figure(figsize=(15,4)) sns.pointplot(data=df_sj, x='연도', y='출생아수', ci=None, hue='시군구별', estimator=np.sum)
많이 증가했다가 다시 19년부터 줄어들고 있다 '빅데이터 > Data-Analysis' 카테고리의 다른 글
인구 통계 분석 - 위키피디아 크롤링 및 데이터 분석 01 (1) 2022.03.04 실전 예제 - 시계열 분석 13 (0) 2022.03.03 실전 예제 - 시계열 분석 13 (0) 2022.03.03 실전 예제 - 시계열 분석 12 (0) 2022.03.03 실전 예제 - 온-오프라인 비지니스 분석 11 (0) 2022.03.02