county_facts.csv primary_results.csv

필요한 패키지 import

%matplotlib nbagg
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib


데이터 2개 읽기

primary = pd.read_csv("python_da/data/2016_presidential_election/primary_results.csv", sep=",")
counties = pd.read_csv("python_da/data/2016_presidential_election/county_facts.csv", sep=",")

primary에는, 미국내 주 - 카운티 별,   각 정당, 후보자의 데이터 및 득표율 데이터
counties라는 primary의 칼럼 중 fips라는 코드를 식별자를 하여, 각 유권자별 데이터가 나와있다.

image

head()와 shape와 columns까지 확인해보자.
image



데이터 분석-1 : 각 후보별 전체지역 득표수

각 후보들별로 전체지역 득표수를 계산해보자.
이전 방식이라면 후보를 의미하는 candidate의 유니크한 값들을 추출한 다음, 반복문을 돌리면서 마스크로 votes열만 뽑아 낸 뒤, 통계량을 계산했다.
데이터 그룹화기능을 사용하면, 이를 한 줄에 끝낼 수 있다.
( 각 ~별 -> groupby의 기준열로 들어간다.)
( ~를 계산 -> 데이터그룹화의 결과물에 [ "칼럼명" ] 으로 추출한다)

  1. 각 후보별 득표수를 계산할 것이므로, 각 후보의 unique한 이름들만 확인해준다.(분석과정에서 필요한 것은 아니다)
    primary["candidate"].unique()
    image
  2. primary 전체 DataFrame에 대해서 groupby()를 할 것인데, 기준열이 candidate열 이다.
    각 후보별로 데이터를 계산하므로,groupby()의 기준열로 쓰면, 각 성분인 후보들을 기준으로 데이터가 그룹화되서 계산할 수 있다.
    그룹화된 결과물에서 DataFrame 전체가 아니고, votes열만 필요하므로, 그룹화된 결과물에 열인덱싱 처리를 해준다.
    마지막으로, 득표수를 계산하려면, 그룹별로 votes열의 합을 구해야하기 때문에 sum()함수를 적용한다.
    primary.groupby("candidate")["votes"].sum()
    image
  3. 투표수(성분)별 오름차순으로 보기 좋게 정렬하기 위해서, 맨 뒤에 .sort_values()적용해서 새로운 변수에 담아준다.
    (변수에 담아야지, plot을 그릴 수 있다!)
    이 때, by= 정렬기준열 을 명시하지않은 것은, 열이 하나(votes열) 밖이기 때문이다.
    candidate_to_votes_s = primary.groupby("candidate")["votes"].sum().sort_values()
    image
  4. 후보별 전체지역 득표수을 정렬한 것을, 수평 바 plot으로 나타내자.
    candidate_to_votes_s.plot(kind="barh", fontsize=8)
    image



(my :  각 ~~ 별 –> ~~열을 groupby()함수의 기준열로 삼아라! ,  a와 b의 ~ –> a + b (배반)으로 포함하는 열을 기준열로 삼아라!)

데이터 분석 – 2 : 각 주별, 공화당과 민주당의, 득표비율 계산

다시 데이터의 head()를 보자.
primary.head()
image

각 주별 ----------> state열이 기준열1
공화당과 민주당 –> party열이 기준열2
2가지 열을 groupby()함수의 [기준열]로 사용할 것이다.
득표비율 --------> votes열을 데이터그룹화의 [추출열]로 사용할 것이다.

  1. 데이터그룹화의 기준열을 state, party순으로 주어서, 각 주별 – 공화당/민주당 – 득표수(합)을 계산해보자.
    계층적인덱스가 주 – 당 형태의 Series가 얻어질 것이다.
    아직까지 우리가 원하는 모양(공화당과 민주당의 각 주별 득표비율)이 아니므로, 변수에 저장해주자.
    state_party_votes_s = primary.groupby( ["state","party"] ) ["votes"].sum()
    image
  2. 비율을 구하기 위해서, 각 주의 전체 득표수를 나누어줘야한다.
    기준열에 state열만 넣어서, votes열을 추출하여 sum()함수를 쓰면, 각 주별 전체 득표수가 나오므로
    계산해서 변수에 담아주자.
    state_to_votes_s = primary.groupby("state")["votes"].sum()
    image
  3. 이제 1에서 구한 Series를 2에서 구한 Series로 나눠준다.
    이렇게 나누기(연산)을 할 때, 계층적 인덱스 中 가장 첫번째 층의 인덱스를 기준으로 계산되기 때문에,
    1에서 기준열을 정할 때, state –> party 순으로, state열을 먼저 지정해야하는 것을 알 수 있다.
    계산한 값을 새로운 변수에 담고 head()를 확인해보자.
    state_party_to_vote_pcts_s = state_party_votes_s / state_to_votes_s
    state_party_to_vote_pcts_s.head()
    image
  4. 이제 비율을 바탕으로 bar plot을 그려보자.
    이 때, 민주당/공화당(2번째 층 인덱스)를 unstack()으로 컬럼으로 올리고 barplot을 그리자.
    컬럼으로 보내면, 인덱스인 각 주(state)가 수평y축에 , 칼럼인 [민주/공화당]이 범례에 나타나면서 각 주별 2개의 막대가 생길 것이다.
    이 때, stacked=True까지 주면, 이 나타나면서 막대에 합쳐진, 비율을 가지게 될 것이다.
    image
    간단히 분석해보자면,  대부분의 주가 공화당이 득표가 우세하고, 몇몇 주는, 민주당이 장악하였다.


my) 각 주별, a와 b의  -> 기준열로 사용할 것. 2개 주제 이상이면, 기준열 순차적으로
      ~를 계산         -> 데이터그룹화(groupby)의 결과물에 [""]열인덱싱으로 필요한열 추출
      최종 결과물에 index-> barplot의 index / columns -> 한index에 세워지는  bar막대기 갯수 및 범례의 갯수


데이터 분석3 – 사용자 정의함수를 이용하여,
각 county별, 당선된 후보의,  백인유권자의 비율을 계산하기 -> 정당별, 당선된 후보들의 백인유권자 비율 보기

정치권에서 속설 중, 백인유권자들이 많은 지역일수록 ---> 공화당 후보가 당선될 확률이 높다라는 것이 있다. 이것을 증명하기 위해서
primary데이터에서 각 county별, 당선된 후보의 백인유권자의 비율을 계산해서 증명해보자.

즉, 각 county별로 그룹화 -> 
각 그룹에 대해 투표수가 가장많은 행(당선자를 가진 행) 뽑는 함수 적용(사용자 정의함수) -> 여기까지는 각 county별 당선후보 데이터(행)을 뽑은 것
다른데이터에 있는 county별 백인유권자 정보를, 기준열(county = fips열)을 가지고 merging -> 붙혀진 칼럼명 이름바꾸기->
각 county별 당선후보에 대한 백인유권자비율을 구해진 상태다. 이제 이 데이터에서 ,
각 정당별, 당선후보자들의 (그룹화 기준 : party, candidate) 백인유권자비율(추출열)의 평균(통계함수)을 구하자.->
barplot 그리고 범위 및 index다 보이도록 수정하기


이번에는 집계함수를 직접 정의하여, 집계를 수행해보자.

  1. 통계(집계)함수를 정의하는데, func이라는 함수는, 데이터그룹화의 결과물(agg_df)에 대해, sort_values()함수를 이용해 votes열을 내림차순으로 정렬하고, 그 중 첫번째 성분을 뽑는 .iloc[0]으로 인덱싱하여,
    대입되는 그룹화결과물의, votes열에 내림차순 정렬 후 1번째 행만 뽑기 = 가장 득표수가 많은 행을 뽑아낼 것이다.
    func = lambda agg_df: agg_df.sort_values("votes", ascending=False ).iloc[0]
    (당선된 후보 = 투표수가 많은 후보 =  투표열을 내림차순 정열후 1번째 행인 후보)
    image
  2. primary의 head()를 다시 한번 살핀 뒤, county를 대변하는 코드인 fips열을 그룹화 기준열로 사용해서 그룹화하고,
    그룹화된 결과물에 사용자 정의함수를 사용할 수 있게 해주는 .agg()함수에다가,
    그룹화결과물을 인자로 받아 votes열을 추출하여 votes열의 가장 큰 수(득표수가 가장 많아 당선)를 뽑아내는 func 함수를 인자로 주자.
    그럼 primary를 fips(county)별로 그룹화한 결과물에, func함수를 적용하여, 각 county별 <votes순으로 내림차순하여, 득표수가 가장 큰 행이 후보이름 + 당명과 함께>을 뽑아내진다.
    이것을 winners라는 변수에 담아서 살펴보자.
    winners = primary.groupby("fips").agg(func)
    winners
    image
    살펴보면) 각 county별 votes수가 가장 많은 행을 뽑아서 –> 그 county에 가장 많은 득표를 얻은 사람 + 당 까지 알 수 있다.

  3. primary데이터에서 얻은 winners라는 각 county별 최다득표 후보와 당 데이터에다가
    각 county별 백인유권자 정보를 붙혀넣어야한다!
    앞서 read한 counties라는 df에서 얻어와야한다. columns 중에 RHI825214라는 칼럼이, 해당 county별 백인 윤권자 비율이다.
    counties["RHI825214"].head()
    image
    이winnders와 counrties의 county에 대한 행의 갯수가 서로 다르나, 병합의 key열(들or인덱스)을 지정해서,
    각각 동일한 기준성분에 대해 m x n형태로 합쳐주는 것
    pd.merge()함수라고 배웠다.
    merging을 이용해서, fips를 기준으로 winner에다가county의 백인유권자 정보를 병합시켜보자.
    (한쪽 데이터를 고정시켜서 병합시킬 때는, how=left or right인자)

  4. 이제 counties에서는 fips열과 rhi825214열만 병합시킬 것이므로, merge()의 인자에서, 열인덱싱을 리스트형식으로 넣어준다.
    그리고, 데이터를 확인해보면,  winners에서는 fips가 그룹화의 기준이 된 결과 index로 있고 / counties에서는 fips가 이므로,
    image
    pd.merge()의 인자에 left_index=True, right_on="fips" 로,  [df의 인덱스 <----> 특정열2개 중 1열]이 서로의 병합기준이 된다고 지정해줘야한다.
    how="left"인자를 통해서, left인 winners 에다가 병합시킬 것이다.
    winners_county_races = pd.merge(winners, counties[ ["fips", "RHI825214"]],
             left_index=True, right_on="fips", how="left")
    image
    새로운 데이터를 보게되면, 인덱스에 있던 fips가, 새로운데이터와 겹치는 부분으로 mxn형태로, 열로 왔고 우측에는 백인유권자 비율이 붙은 것을 확인할 수 있다.
  5. 이제 백인유권자 비율의 컬럼(RHI825214)의 이름을 바꿔주자. rename()함수의 인자로, 컬럼 = {딕셔너리}형태로 바꿔준다.
    이것을 다시 기존 데이터에 대입하면 바뀐 데이터가 된다.
    winners_county_races = winners_county_races.rename(columns={"RHI825214" : "white_pcts"})
    winners_county_races.head()
    image
  6. 이렇게 얻어진, 각 county별 최다득표자(winner)의 백인유권자 비율까지 표시된 데이터에다가,
    party와, candidate를 그룹화 한뒤, 각 정당별 후보자들의 백인유권자 비율의 평균을 계산해보자.
    ( 각 county별 최다득표자들만 모았으니, 각 county별 당선자들이다. 이제 county를 잊고, 정당 별 후보자=당선자의 백인비율을 보는 것이다)
    winners_county_white_pcts = winners_county_races.groupby(["party", "candidate"])["white_pcts"].mean()
    winners_county_white_pcts
    image
  7. 수평 바 플롯을 그려보자.
    winners_county_white_pcts.plot(kind="barh", fontsize=8)
    image
  8. .plot()을 그린 좌표평면 변수를 생성해서, 몇가지 수정해 이쁘게 보이도록 하자.
    ax = winners_county_white_pcts.plot(kind="barh", fontsize=8)
    (1)먼저, x축의 범위를 50부터 100까지 보자.(0~50까지는 모두 차 있으니까)
    (2) index가 다 안보일 때는, 이 함수를 호출하자 : plt.tight_layout()

    ax.set_xlim([50,100])
    plt.tight_layout()

    image
    간단히 살펴보면 ) 공화당 후보(Rep.)가 당선된 county에 백인유권자의 비율이 75%으로 높긴 높다.
    그런데 특이한 점은, 민주당 후보에서도 하나의 county에 백인유권자의 비율이 80%이상으로 높다.




피벗 테이블(pivot_table)로 데이터 분석하기

예제를 보면서 해석해보자.

1.
total_votes = primary.pivot_table( values = "votes" , index="state" , columns ="candidate", aggfunc="sum", fill_value=0 )

primary라는 df에, 피컷테이블함수를 적용시키는데,
values = 통계함수를 적용할 df의 특정열
index = 그룹화의 1번째 기준이면서, 피벗테이블(df)의 index로 가져올 primary의 특정열
columns = 그룹화의 2번째 기준이면서, 피벗테이블(df)의 columns로 가져올 primary의 특정열
aggfunc = 2개의 그룹화기준을 가지고 values에 들어간 특정열에 적용시킬 통계함수를 문자열로 표현
fill_value=0  NaN을 0으로 처리

각 주별, 당선자들의, 득표수, 총합

total_votes
image


2.
primary.pivot_table(values="fraction_votes", index="state_abbreviation", columns="party", aggfunc="mean")
values = fraction_votes(해당후보의 득표율)을 가지고, 통계함수를 계산할 것인데,
index에는 state의 축약어 /  columns에서는 정당 으로 가져오면서,   2개를 기준으로 그룹화 한뒤,
aggfunc를 통해 <해당 후보의 득표율의> mean(평균값)을 구한다.

각 주별(축약어), 정당들의, 득표율, 평균
image

+ Recent posts