plotly 로 막대그래프 만들기
kaggle survey 시각화
본 글은 kaggle의 2021 Kaggle Machine Learning & Data Science Survey의 데이터를 기반으로 작성되었습니다.
Q25 문항의 연봉에 대한 답변을 한국, 중국, 미국, 일본 간 비교하여 어떤 유의미한 차이가 있는지 분석할 예정이다.
import 와 데이터 불러오기
df에 pd.read_csv 함수를 통해 데이터를 불러와서 저장해준다.
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from google.colab import drive
drive.mount('/content/drive')
df = pd.read_csv('/content/drive/MyDrive/kaggle_survey_2021_responses.csv')
데이터 확인
분석에 직접적으로 사용 될 문항인 ‘Q3’ 과 ‘Q25’ 를 보면 결측치와 필요 없는 값이 너무 많다.
전처리가 필요하다.
df[0:10][['Q3','Q25']]
Q3 | Q25 | |
---|---|---|
0 | In which country do you currently reside? | What is your current yearly compensation (appr... |
1 | India | 25,000-29,999 |
2 | Indonesia | 60,000-69,999 |
3 | Pakistan | $0-999 |
4 | Mexico | 30,000-39,999 |
5 | India | 30,000-39,999 |
6 | India | NaN |
7 | India | NaN |
8 | India | 15,000-19,999 |
9 | Russia | NaN |
연봉 구간 단순화
기존 Q25의 연봉 구간 선택지가 너무 다양하다.
예를 들어 연봉으로 보이지 않는 1000만원 미만의 금액에서도 약 10개에 가까운 분류로 나뉘어져 있다.
딱히 유의미한 정보들이 아니기 때문에 분류를 단순화 시키는 작업이 필요하다.
df.loc[df[‘칼럼명’] == ‘찾는 값’, ‘값을 바꿀 칼럼’] = ‘바꿀 값’ 의 형태로 loc를 사용하여 값을 변경하였다.
df.loc[df['Q25'] == '$0-999' , 'Q25'] = '0-4,999'
df.loc[df['Q25'] == '1,000-1,999' , 'Q25'] = '0-4,999'
df.loc[df['Q25'] == '2,000-2,999' , 'Q25'] = '0-4,999'
df.loc[df['Q25'] == '3,000-3,999' , 'Q25'] = '0-4,999'
df.loc[df['Q25'] == '4,000-4,999' , 'Q25'] = '0-4,999'
df.loc[df['Q25'] == '5,000-7,499' , 'Q25'] = '5,000-9,999'
df.loc[df['Q25'] == '7,500-9,999' , 'Q25'] = '5,000-9,999'
df.loc[df['Q25'] == '10,000-14,999' , 'Q25'] = '10,000-19,999'
df.loc[df['Q25'] == '15,000-19,999' , 'Q25'] = '10,000-19,999'
df.loc[df['Q25'] == '20,000-24,999' , 'Q25'] = '20,000-29,999'
df.loc[df['Q25'] == '25,000-29,999' , 'Q25'] = '20,000-29,999'
df.loc[df['Q25'] == '150,000-199,999' , 'Q25'] = '150,000-249,999'
df.loc[df['Q25'] == '200,000-249,999' , 'Q25'] = '150,000-249,999'
df.loc[df['Q25'] == '250,000-299,999' , 'Q25'] = '250,000-499,999'
df.loc[df['Q25'] == '300,000-499,999' , 'Q25'] = '250,000-499,999'
df.loc[df['Q25'] == '$500,000-999,999' , 'Q25'] = '> 500000'
df.loc[df['Q25'] == '>$1,000,000' , 'Q25'] = '> 500000'
결측치 제거
dropna를 사용하여 ‘Q25’ 문항에 답을 안 한 사람들의 행을 제거하였다.
df.dropna(subset=[‘결측치를 제거할 칼럼명’])
df2=df.dropna(subset=['Q25'])
국가별 데이터프레임 생성
국가별로 데이터 프레임을 만들어 저장하였다.
df_korea= df2[df2['Q3']=='South Korea']
df_China= df2[df2['Q3']=='China']
df_Japan= df2[df2['Q3']=='Japan']
df_USA= df2[df2['Q3']=='United States of America']
퍼센트 칼럼 추가 함수 정의
데이터의 개수가 국가별로 너무 차이가 크다보니 백분위를 사용한 비율로서 표현 하는 것이 맞다고 판단하였다.
우선 value.count() 함수를 통해 시리즈 형태의 데이터를 파라메타 값으로 받아서 백분위를 구할 때 분모가 될 전체 값의 수를 구한다.
그 후 기존 시리즈 형태의 데이터를 데이터프레임 형태로 바꿔준 후 percent 칼럼을 새로 만들어서 계산된 백분위 값을 넣어준다.
def to_df_addpercent(value_count):
sum_vc = value_count.sum()
to_DF = pd.DataFrame(value_count)
to_DF['percent'] = round(to_DF['Q25']*100/sum_vc,1)
return to_DF
정의한 함수를 사용하여 최종 데이터 프레임 저장
함수를 통해 분석에 필요한 최종 형태의 데이터 프레임을 만든다.
df_percent_China= to_df_addpercent(df_China['Q25'].value_counts())
df_percent_USA= to_df_addpercent(df_USA['Q25'].value_counts())
df_percent_Japan= to_df_addpercent(df_Japan['Q25'].value_counts())
df_percent_Korea= to_df_addpercent(df_korea['Q25'].value_counts())
df_percent_USA
Q25 | percent | |
---|---|---|
150,000-249,999 | 350 | 19.0 |
100,000-124,999 | 289 | 15.7 |
125,000-149,999 | 186 | 10.1 |
0-4,999 | 165 | 8.9 |
80,000-89,999 | 113 | 6.1 |
250,000-499,999 | 111 | 6.0 |
70,000-79,999 | 110 | 6.0 |
90,000-99,999 | 108 | 5.9 |
60,000-69,999 | 92 | 5.0 |
50,000-59,999 | 73 | 4.0 |
40,000-49,999 | 58 | 3.1 |
20,000-29,999 | 55 | 3.0 |
30,000-39,999 | 48 | 2.6 |
10,000-19,999 | 35 | 1.9 |
> 500000 | 32 | 1.7 |
5,000-9,999 | 20 | 1.1 |
막대 그래프로 시각화
make_subplots 를 통해 2행 2열 구조의 figure 객체를 생성해준다.
그 후 fig.add_trace에 go.bar()로 막대그래프 객체를 생성하여 입력한다.
이 때 add_trace의 파라메타 값으로 row=,col= 을 줌으로서 해당 trace의 위치를 설정할 수 있다.
처음 그래프를 만들었을 때 index(연봉구간)가 문자열로 구성되어 있다보니 x축의 순서가 연봉과 무관하게 뒤죽박죽 나오는 문제가 발생했다.
해당 문제를 해결하기 위해 dataframe에 새로운 인덱스를 만드는 함수도 만들어 봤으나 좋은 결과를 얻지 못 했고, 구글링 끝에 방법을 찾았다.
fig.update_xaxes(categoryorder=’array’, categoryarray= []) 을 통해 x축의 순서를 지정해줌으로서 해결했다.
fig = make_subplots(rows = 2, cols = 2,
shared_xaxes=True,
shared_yaxes=True,
vertical_spacing = 0.05,
subplot_titles=("USA", "China", "Japan", "Korea"),
column_widths = [0.5, 0.5])
fig.add_trace(go.Bar(
y=df_percent_China['percent'].values,
x=df_percent_China.index,
text = df_percent_China['percent'].astype(str) + "%",
textposition='outside',name='China'),
row=1,col=2)
fig.add_trace(go.Bar(
y=df_percent_USA['percent'].values,
x=df_percent_USA.index,
text = df_percent_USA['percent'].astype(str) + "%",
textposition='outside',name='USA'),
row=1,col=1 )
fig.add_trace(go.Bar(
y=df_percent_Japan['percent'].values,
x=df_percent_Japan.index,
text = df_percent_Japan['percent'].astype(str) + "%",
textposition='outside',name='Japan'),
row=2,col=1)
fig.add_trace(go.Bar(
y=df_percent_Korea['percent'].values,
x=df_percent_Korea.index,
text = df_percent_Korea['percent'].astype(str) + "%",
textposition='outside',name='Korea'),
row=2,col=2 )
fig.update_xaxes(categoryorder='array', categoryarray= [ '0-4999','5,000-9,999', '10,000-19,999','20,000-29,999','30,000-39,999','40,000-49,999','50,000-59,999'
,'60,000-69,999','70,000-79,999','80,000-89,999','90,000-99,999','100,000-124,999','125,000-149,999','150,000-249,999','250,000-499,999','> 500000'])
fig.update_layout(height = 1000,
showlegend=False)
fig.show()
분석
사실 잘못된 응답인지 아니면 학생의 응답인지 모르겠지만 연봉 천만원 밑의 응답이 너무 많아서 분석하는 데 에러사항이 있었다.
한중일의 직업에 대한 응답을 보니 미국에 비해 학생의 비중이 높았으니 어느정도 납득은 간다.
확실한건 미국은 한중일에 비해 억대 연봉의 비중이 상당하다는 것이다.
이렇게 연봉의 차이가 큰 이유는 이 그래프만으론 판단 내릴 수 없고 다른 데이터들의 분석이 필요할 것으로 보인다.
추후 다른 분석들과 함께 원인을 파악해보겠다.. 시간이 된다면..
댓글남기기