>⛹️♀️ 제로베이스 데이터취업스쿨 15기 스터디노트 26(6.9.-10.)
🗂️ 오늘까지(6.10.) 수강한 분량
인구분석 1~3
🗂️ 인구분석 1~3 핵심 내용 정리
데이터 읽고 인구 소멸 지역 계산하기
fillna()
: 결측값 관리 함수fillna_df.fillna(method="pad") #보통은 value = 0이면 0으로 채움 #pad는 앞의 데이터 값을 가져오게 함=ffill , axis = 0 가로축 변경 #backfill은 뒤의 값, 뒤의값이 없으면 NaN값 유지함
- 컬럼 이름 변경
population.rename(columns={"행정구역(동읍면)별(1)":"광역시도", "행정구역(동읍면)별(2)":"시도", "계":"인구수"},inplace=True) population.tail()
population = population[population["시도"] != "소계"] #소계제거 population.head()
- 소멸 지역을 조사하기 위해 데이터 정제하기
population["20-39세"] = ( population["20 - 24세"] + population["25 - 29세"] + population["30 - 34세"]+ population["35 - 39세"]) population["65세 이상"] = ( population["65 - 69세"]+ population["70 - 74세"]+population["75 - 79세"]+ population["80 - 84세"]+population["85 - 89세"]+population["90 - 94세"]+ population["95 - 99세"]+population["100+"])
- 피벗테이블 만들기
pop=pd.pivot(data = population, index=["광역시도","시도"], columns=["구분"], values=["인구수","20-39세","65세 이상"])
- 소멸 비율 계산 :
pop["소멸비율"] = pop["20-39세","여자"]/(pop["65세 이상","합계"] /2)
- 소멸 위기 지역 칼럼 생성
pop["소멸위기지역"] = pop["소멸비율"] < 1.0 #T/F로 값 지정 pop[pop["소멸위기지역"] == True].index.get_level_values(1) #소멸위기지역 조회 pop.reset_index(inplace=True) #데이터 바꾸고 바로 저장 pop.head() #데이터 프레임 안으로 데이터 넣기
- 멀티 칼럼 정리[광역시도 + 빈칼럼 -> 광역시도로 표기]
tmp_columns = [ pop.columns.get_level_values(0)[n] + pop.columns.get_level_values(1)[n] #옆의 컬럼이 없으면 옆의 칼럼을 더함 for n in range(0,len(pop.columns.get_level_values(0))) #컬럼의 길이만큼 ]
- 지도 시각화를 위한 지역별 ID 만들기
si_name = [None] * len(pop) #빈리스트 만들기 tmp_gu_dict = { "수원":["장안구", "권선구","팔달구","영통구"], "성남":["수정구", "중원구","분당구"], "안양":["만안구","동안구"], "안산":["상록구","단원구"], "고양":["덕양구","일산동구","일산서구"], "용인":["처인구","기흥구","수지구"], "청주":["상당구","서원구","흥덕구","청원구"], "천안":["동남구","서북구"], "전주":["완산구","덕진구"], "포항":["남구","북구"], "창원":["의창구","성산구","진해구","마산합포구","마산회원구"], "부천":["오정구","원미구","소사구"]} #행정 구가 있는 곳 정리
- 일반광역시도, 세종특별자치시, 일반구 정리
for idx, row in pop.iterrows(): if row["광역시도"][-3:] not in ["광역시","특별시","자치시"]: #마지막글자에서 3개 역순으로 보여주기(광역시, 특별시, 자치시) si_name[idx] = row["시도"][:-1] #마지막 글자를 떼고 저장(~시, ~군 제외) elif row["광역시도"] == "세종특별자치시": si_name[idx]="세종" else: if len(row["시도"]) == 2: si_name[idx] = row["광역시도"][:2] + " " + row["시도"] #서울 중구 형태로 만듬 else: si_name[idx] = row["광역시도"][:2] + " " + row["시도"][:-1] #마지막자를 빼기
- 행정구역 정리
for idx, row in pop.iterrows(): if row["광역시도"][-3:] not in ["광역시","자치시","특별시"]: for keys, values in tmp_gu_dict.items(): if row["시도"] in values: if len(row["시도"])==2: si_name[idx] = keys + " " + row["시도"] elif row["시도"] in ["마산합포구","마산회원구"]: si_name[idx] = keys + " " + row["시도"][2:-1] else: si_name[idx] = keys + " " + row["시도"][:-1]
- 고성군 정리(강원도, 경남도)
for idx, row in pop.iterrows(): if row["광역시도"][-3:] not in ["광역시","자치시","특별시"]: if row["시도"][:-1] == "고성" and row["광역시도"] == "강원도": si_name[idx] = "고성(강원)" elif row["시도"][:-1] == "고성" and ["광역시도"] == "경상남도": si_name[idx] = "고성(경남)" -필요없는 데이터 제거
- 지도 그리기(카르토그램)
- 지도 좌표 표기 엑셀 가져오기
draw_korea_raw_stacked = pd.DataFrame(draw_korea_raw.stack()) #0~6까지는 0, 7부터 데이터가 있음 draw_korea_raw_stacked.reset_index(inplace=True) draw_korea_raw_stacked #데이터 재설정 및 저장 draw_korea_raw_stacked.rename( columns={"level_0":"y",level_1":"x", 0:"ID"},inplace =True) draw_korea_raw_stacked #컬럼변경 -보더라인 설정 (값 입력)
- 검증 작업 후 데이터 합치기
tmp_list = list(set(pop['ID'].unique()) - set(draw_korea['ID'].unique())) #차집합구하기 for tmp in tmp_list: pop = pop.drop(pop[pop["ID"] == tmp].index) print(set(pop['ID'].unique()) - set(draw_korea['ID'].unique()))
- 데이터합치기 :
pop = pd.merge(pop, draw_korea, how="left", on="ID")
- 그림을 그리기 위해 데이터 계산함수 사용
def get_data_info(targetData,blockedMap): whitelabelmin = ( max(blockedMap[targetData])-min(blockedMap[targetData]) )*0.25 + min(blockedMap[targetData]) vmax = max(blockedMap[targetData])# 최대값 vmin = min(blockedMap[targetData]) #최소값 mapdata = blockedMap.pivot_table(index="y",columns="x",values=targetData) return mapdata,vmax,vmin,whitelabelmin ```python def get_data_info_for_zero_center(targetData,blockedMap): whitelabelmin = 5 #최소값이 아닌 5를 흰색으로 지정 tmp_max = max( [np.abs(min(blockedMap[targetData])), np.abs(max(blockedMap[targetData]))] ) #절대값이 가장 큰 값을 max값으로 지정 -> #해당 절대값의 양수와 음수를 각각 최대 최소로 지정 vmin,vmax = - tmp_max,tmp_max mapdata = blockedMap.pivot_table(index="y",columns="x",values=targetData) return mapdata,vmax,vmin,whitelabelmin ```python def drawKorea(targetData,blockedMap,cmapname,zeroCenter=False): if zeroCenter: masked_mapdata, vmax, vmin, whitelabelmin = get_data_info_for_zero_center(targetData,blockedMap) if not zeroCenter: masked_mapdata, vmax, vmin, whitelabelmin = get_data_info(targetData,blockedMap) #zeroCenter가 true이면, get_data_info로 변수들을 선언 plt.figure(figsize=(8,11)) plt.pcolor(masked_mapdata, vmin = vmin, vmax = vmax, cmap = cmapname, edgecolor="#aaaaaa", linewidth=0.5) plot_text(targetData,blockedMap,whitelabelmin) for path in BORDER_LINES: ys,xs = zip(*path) plt.plot(xs,ys,c="black",lw=1.5) plt.gca().invert_yaxis() plt.axis("off") plt.tight_layout() cb = plt.colorbar(shrink=0.1, aspect = 10) cb.set_label(targetData) plt.show()
- 인구수 합계 시각화 :
drawKorea("인구수합계",pop,"Blues")
- 소멸 위기 지역 시각화 :
pop["소멸위기지역"] = [1 if con else 0 for con in pop["소멸위기지역"]] drawKorea("소멸위기지역",pop,"Reds")
- 여성비 시각화 :
pop["여성비"] = (pop["인구수여자"] / pop["인구수합계"] -0.5) *100 drawKorea("여성비",pop,"RdBu",zeroCenter=True)
- 2030 여성비 시각화:
pop["2030여성비"] = (pop["20-39세여자"] / pop["20-39세합계"] -0.5) *100 drawKorea("2030여성비",pop,"RdBu",zeroCenter=True)
- 지도 위에 관련 내용 그리기(folium, json)
import folium import json pop_folium = pop.set_index("ID") #id로 인덱스를 잡아주기 위해서 pop_folium
- 인구수 합계 지도
#인구수합계 geo_path="../data/07_skorea_municipalities_geo_simple.json" geo_str=json.load(open(geo_path, encoding="utf-8")) mymap = folium.Map(location=[36.2002, 127.054],zoom_start=7) mymap.choropleth(geo_data=geo_str, data=pop_folium["인구수합계"], key_on="feature.id", columns=[pop_folium.index,pop_folium["인구수합계"]], fill_color="YlGnBu") mymap
#소멸위기지역
mymap = folium.Map(location=[36.2002, 127.054],zoom_start=7)
mymap.choropleth(geo_data=geo_str, data=pop_folium["소멸위기지역"],
key_on="feature.id",
columns=[pop_folium.index,pop_folium["소멸위기지역"]],
fill_color="PuRd")
mymap
👩🚀 스터디 감정 노트
> EDA 이대로 끝인건 좋은데 안좋아...소멸위기지도는 안올라가지만,, 했음...해냈다
[헤더 이미지 출처 : 미리캔버스]