ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Pandas 병합과 조인 연산 (파이썬 데이터 사이언스 핸드북 예시)
    데이터 분석/Pandas 2020. 8. 20. 09:53

     

    <파이썬 데이터 사이언스 핸드북> p.179 ~ 184 예제: 미국 주 데이터

    이 글은 가지고 있는 데이터셋을 기준으로 유의미한 결과를 추출하기 위해서 어떤 과정을 거치는지를 정리하였습니다. 이 작업이 데이터를 다루는 좋은 습관을 형성하는 데 도움을 줄 것이라고 생각했습니다. 

     


     

     

    Step 1. 목표 결과물 확인하기

     

    목표 결과물: 2010년 인구 밀도 기준으로 미국 주와 지역 순위 계산

    2010년 한정 인구밀도 (인구수 / 면적) 계산이 필요하다. 

     

    state-population.csv  미국 주별 연도별 인구수

    state-areas.csv  미국 주별 면적

    state-abbreves.csv  미국 주와 주 약어코드

     

     

     

     

    Step 2. 가지고 있는 데이터셋 확인하기 

     

    1. 데이터를 스캔하여 컬럼명을 확인한다.

    3. 기대결과를 추출하기 위해 필요한 컬럼을 확인한다. 필터링, 연산대상

    3. 여러 데이터셋에 분리되어있을 경우 JOIN 대상을 확인한다.   

    4. 각 컬럼에 어떤 값들이 분포하고 있는지, Null 은 없는지 확인한다.

     

    state-population.csv  미국 주별 연도별 인구수

    state/region: 주 약어코드

    ages: 나이 (under18, total)

    연도: 1990 ~ 2012 (13년) 중 2010년만

    인구수: 인구수 --> null 데이터 있음(!)

     

    state-areas.csv  미국 주단위 면적

    state: 주명

    area (sq. mi): 마일당 면적

     

    state-abbreves.csv  미국 주와 주 약어코드

    state: 주명

    abbreviation: 주 약어코드

    import pandas as pd
    
    # 데이터셋 읽어오기
    pop = pd.read_csv('./Project/DS/data/USstates/state-population.csv')
    areas = pd.read_csv('./Project/DS/data/USstates/state-areas.csv')
    abbrevs = pd.read_csv('./Project/DS/data/USstates/state-abbrevs.csv')
    
    # 잘 읽어왔나 확인
    print(pop.head())
    print(areas.head())
    print(abbrevs.head())
    
    # 데이터 구성 확인
    pd.unique(pop['year'])
    pd.unique(pop['ages'])

     

     

    Step 3. 데이터 전처리 - 

     

    사실 2010년 인구밀도 데이터만 구하면 되니 2010년만 짤라서 보고싶지만~ 공부하는 차원에서 정도대로 정리해보았다. ㅇ__ㅇ!

     

    NULL 처리

    state-population.csv  미국 주별 연도별 인구수

    인구수: 인구수 --> null 데이터 있음(!)

    pop['population'] 이 null 데이터를 가지고 있는 state/region unique 값을 검사해보니 "PR" 푸에트리코가 나온다. 

    # 데이터 null 확인, null 데이터 이모저모 살피기 
    pop.isnull().any(axis=0)
    
    
    # 출력결과
    # state/region    False
    # ages            False
    # year            False
    # population       True
    # dtype: bool
    
    
    
    pop[pop['population'].isnull()]
    pop[pop['state/region']=="PR"]
    
    # 출력결과: PR 주는 일부 해의 인구수가 null이다.
    # 1990~1999 년 데이터는 인구수가 null 이다. 
    # 2000년부터는 인구수가 있다!
    
    
    pd.unique(pop[pop['population'].isnull()]['state/region'])
    
    # 출력결과: PR 주만 null 값이 있다. 
    # array(['PR'], dtype=object)
    

     

    참고. 푸에트리코는 주권국가도 아니고, 미국 주도 아니라고 한다. (흠)

    Q. Is Puerto Rico part of the US?

    A. The political status of Puerto Rico is that of an unincorporated territory of the United States. As such, the island of Puerto Rico is neither a sovereign nation nor a U.S. state.

     

    나머지 주는 null 값이 없다. 

    areas.isnull().any(axis=0)
    abbrevs.isnull().any(axis=0)

     

     

    Step 4. JOIN 

     

    a. 인구수 데이터셋에 state 공통 식별자를 넣는다. 

    state 가 join 되지 않은 컬럼값은 state/region 기준 PR, USA 이다.

    적당한 값으로 채워주었다!

    # 데이터 머지
    merged = pd.merge(pop, abbrevs, how='left', left_on='state/region', right_on='abbreviation')
    merged = merged.drop('abbreviation', axis=1)
    
    # 머지된 데이터 기준 null 확인
    merged.isnull().any()
    
    # state/region    False
    # ages            False
    # year            False
    # population       True
    # state            True
    # dtype: bool
    
    
    
    # 컬럼마다 확인
    merged[merged['population'].isnull()]     # PR, 1990 ~ 1999 데이터 없음
    merged[merged['state'].isnull()]          # 96 rows × 5 columns
    merged.loc[merged['state'].isnull(), 'state/region'].unique()
    # array(['PR', 'USA'], dtype=object)
    
    
    
    # 값 채워넣기 
    merged.loc[merged['state/region']=='PR', 'state'] = 'Puerto Rico'
    merged.loc[merged['state/region']=='USA', 'state'] = 'United States'
    
    
    # null 값 채우기 잘 되었는지 확인 
    merged['state'].isnull().any()            # False
    merged.loc[merged['state'].isnull(), 'state/region'].unique()
    # array([], dtype=object)

     

     

    b. 여기서 면적 데이터셋을 붙인다. 

    state 가 join 되지 않은 컬럼값은 state/region 기준 USA 이다.

    USA 는 주 가 아니므로, 필요없는 데이터! null값을 날려버리자!

    # 데이터 머지하기
    final = pd.merge(merged, areas, how='left')
    final.head()
    
    
    # 머지된 데이터 기준 null 확인하기
    final.isnull().any()
    # state/region     False
    # ages             False
    # year             False
    # population        True
    # state            False
    # area (sq. mi)     True
    # dtype: bool
    
    
    # 컬럼마다 확인
    final[final['area (sq. mi)'].isnull()]
    final[final['area (sq. mi)'].isnull()]['state'].unique()
    # array(['United States'], dtype=object)
    
    
    # null 값 row 삭제
    final.dropna(inplace=True)
    
    
    # null 값 잘 삭제되었는지 확인
    final[final['area (sq. mi)'].isnull()]['state']
    # Series([], Name: state, dtype: object)
    

     

     

    Step 5. 필터링

    우리가 원하는 결과는 2010년의 총 연령대 인구수, 면적에 대한 데이터이다.

    # 필터링 query 를 위해 numexpr 설치 및 임포트
    import sys
    !{sys.executable} -m pip install numexpr
    import numexpr
    
    # 2010년 총 인구수 필터링
    data2010 = final.query("year==2010 & ages=='total'")
    data2010.head()
    

     

     

    Step 6. 추출결과 선택 및 정리

    우리가 원하는 주 단위 인구밀도를 추출한다.

    단정하게 인구밀도 순으로 내림차순 정렬하면 끝!

    # 추출대상 기준을 index 로 지정한다.
    data2010.set_index('state', inplace=True)
    
    # 인구밀도를 계산
    density = data2010['population'] / data2010['area (sq. mi)']
    density.head()
    
    # 밀도 기준으로 내림차순 정렬
    density.sort_values(ascending=False, inplace=True)
    
    
    

     

     


    null 처리 (채우기, 삭제) 예시가 있고,

    동일한 식별자를 기준으로 JOIN 하는 부분도 잘 설명되엉있고

    인덱스를 기준으로 값을 집계, 추출하는 것까지

     

    알찬 예시였다 :D 

    댓글

Designed by Tistory.