Kaggle-Survey03-B: replace가 작동 안함 [pandas]

Japan & China: IDE’s

Program_Language 과정과 동일

Treemap을 뽑으려니 “Jupyter (JupyterLab, Jupyter Notebooks, etc)”와 “Visual Studio / Visual Studio Code”가 너무 길어 플롯에서 식별하기 난감하다.

각각 “Jupyter”와 “VS / VSCode”로 간략화 하려한다.

1차 시도

1
2
df_IDEs_JnC_21n19.replace(to_replace = 'Jupyter (JupyterLab, Jupyter Notebooks, etc)', value =  'Jupyter', inplace = True)
df_IDEs_JnC_21n19.replace(to_replace = 'Visual Studio / Visual Studio Code', value = 'VS / VSCode', inplace = True)

둘 다 변경되지 않았다.

2차 시도

실제 string을 확인해보자.

1
2
print(df_IDEs_JnC_21n19.loc[0].tolist())
print(df_IDEs_JnC_21n19.iloc[29].tolist())
['2021', 'Japan', 'Jupyter (JupyterLab, Jupyter Notebooks, etc) ', 200]
['2019', 'China', ' Visual Studio / Visual Studio Code ', 200]

뒤(혹은 앞뒤)로 공백이 들어간 상황임을 알 수 있다.

1
2
df_IDEs_JnC_21n19.replace(to_replace = 'Jupyter (JupyterLab, Jupyter Notebooks, etc) ', value =  'Jupyter', inplace = True)
df_IDEs_JnC_21n19.replace(to_replace = ' Visual Studio / Visual Studio Code ', value = 'VS / VSCode', inplace = True)

성공적으로 변경됐다.

더 간편하게

근대 이럴거면 그냥 요소를 뽑아내서 직접 삽입하는게 편할 듯하다.

1
2
df_IDEs_JnC_21n19.replace(to_replace = df_IDEs_JnC_21n19.loc[0,"IDE\'s"], value =  'Jupyter', inplace = True)
df_IDEs_JnC_21n19.replace(to_replace = df_IDEs_JnC_21n19.loc[29,"IDE\'s"], value = 'VS / VSCode', inplace = True)

인덱스와 칼럼명을 직접 지정해 뽑아낸 string과 동일한 요소를 모두 변경한다.

정규식?

‘ Visual Studio / Visual Studio Code ‘ 요소는 실제로는 아니지만 정규 표현식으로 해석할 여지가 있다.
정 방법을 못찾겠다면 regex 요소를 True로 지정해보는것도 방법이 될 수 있다.

1
2
df_IDEs_JnC_21n19.replace(to_replace = 'Jupyter (JupyterLab, Jupyter Notebooks, etc) ', value = 'Jupyter', inplace = True)
df_IDEs_JnC_21n19.replace(to_replace = 'Visual Studio / Visual Studio Code', value = 'VS / VSCode', inplace = True, regex = True)

IDE’s Treemap

IDE's

외부링크

Kaggle_Survey03: Treemap 시각화 [plotly]

기본 설정

module

treemap으로 많은 요소를 건드리진 않을 예정이니 express 라이브러리를 사용

1
2
import pandas as pd
import plotly.express as px

Import data

2021년 자료 외에도 19년 자료를 추가

1
2
3
4
df21 = pd.read_csv("https://raw.githubusercontent.com/hangack/project-green/main/Kaggle_Survey-2021/data/kaggle-survey-2021/kaggle_survey_2021_responses.csv", dtype='unicode')
df19 = pd.read_csv("https://raw.githubusercontent.com/hangack/project-green/main/Kaggle_Survey-2021/data/kaggle-survey-2019/multiple_choice_responses.csv", dtype='unicode')
#df21 = pd.read_csv("../input/kaggle-survey-2021/kaggle_survey_2021_responses.csv", dtype='unicode')
#df19 = pd.read_csv("../input/kaggle-survey-2019/multiple_choice_responses.csv", dtype='unicode')

Japan & China: Programming_Languages

2021 Japan & China total

2021년 Q3(Country) 일본 중국 추출 dataframe

1
df21_ChJp = df21[df21.Q3.isin(["Japan","China"])]

Split Country

나라별 value_counts를 위해 각 나라로 dataframe 분리

2021

value_counts 오류 식별 결측값 제거

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
df21_Ch = df21_ChJp[df21_ChJp.Q3.isin(["China"])]
df21_Jp = df21_ChJp[df21_ChJp.Q3.isin(["Japan"])]


## Q7(Program_Language): 칼럼번호 8~20 - others
df21_Jp_PL = pd.DataFrame()
df21_Jp_PL['Program_Language'] = [df21_Jp[col][1:].value_counts().index[0] for col in df21_Jp.columns[7:19]]
df21_Jp_PL['counts'] = [df21_Jp[col][1:].value_counts().values[0] for col in df21_Jp.columns[7:19]]


## 2021 China: Q7_Part12(None) value == 0이므로 결측값 제거
df21_Ch_rmQ07P12 = df21_Ch.drop(['Q7_Part_12'], axis='columns')

## Q7(Program_Language): 칼럼번호 8~20 - others - Q7_Part12(None)
df21_Ch_PL = pd.DataFrame()
df21_Ch_PL['Program_Language'] = [df21_Ch_rmQ07P12[col][1:].value_counts() .index[0] for col in df21_Ch_rmQ07P12.columns[7:18]]
df21_Ch_PL['counts'] = [df21_Ch_rmQ07P12[col][1:].value_counts() .values[0] for col in df21_Ch_rmQ07P12.columns[7:18]]


## 제거된 나라 칼럼과 value를 각각 삽입 및 통합
df21_Jp_PL.insert(0, 'Country', 'Japan')
df21_Ch_PL.insert(0, 'Country', 'China')

df21_PL_JnC = pd.concat([df21_Jp_PL,df21_Ch_PL], ignore_index=True)

2019 Japan & China total

2019년 Q3(Country) 일본 중국 추출 dataframe

1
df19_ChJp = df19[df19.Q3.isin(["Japan","China"])]

2019

2021년과 동일 과정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
df19_Ch = df19_ChJp[df19_ChJp.Q3.isin(["China"])]
df19_Jp = df19_ChJp[df19_ChJp.Q3.isin(["Japan"])]


## Q18(Program_Language): 칼럼번호 83~95 - others & other(text)
df19_Jp_PL = pd.DataFrame()
df19_Jp_PL['Program_Language'] = [df19_Jp[col][1:].value_counts().index[0] for col in df19_Jp.columns[82:93]]
df19_Jp_PL['counts'] = [df19_Jp[col][1:].value_counts().values[0] for col in df19_Jp.columns[82:93]]


## 2019 China Q18_Part11(None) 결측값 제거
df19_Ch_rmQ18P11 = df19_Ch.drop(['Q18_Part_11'], axis='columns')

## Q18(Program_Language): 칼럼번호 83~95 - others & other(text) - Q18_Part11(None)
df19_Ch_PL = pd.DataFrame()
df19_Ch_PL['Program_Language'] = [df19_Ch_rmQ18P11[col][1:].value_counts() .index[0] for col in df19_Ch_rmQ18P11.columns[82:92]]
df19_Ch_PL['counts'] = [df19_Ch_rmQ18P11[col][1:].value_counts() .values[0] for col in df19_Ch_rmQ18P11.columns[82:92]]



df19_Jp_PL.insert(0, 'Country', 'Japan')
df19_Ch_PL.insert(0, 'Country', 'China')

df19_PL_JnC = pd.concat([df19_Jp_PL,df19_Ch_PL], ignore_index=True)

Split year{Country}

다른 csv인 2019자료와 2021자료 통합

1
2
3
4
df21_PL_JnC.insert(0, 'year',  '2021')
df19_PL_JnC.insert(0, 'year', '2019')

df_PL_JnC_21n19 = pd.concat([df21_PL_JnC,df19_PL_JnC], ignore_index=True)

Program_Language의 19년도 21년도 통합 value_counts의 정렬(연도 - 언어 - 나라)

values는 Program_Language의 value_counts

Programming_Languages [treemap]

이전 언급처럼 treemap으로 많은 요소를 건드리진 않을 예정이니 express 라이브러리를 사용했다.

path 요소의 순서는 부모자식 순서로 dataframe 칼럼 순서에 제한되지 않는다. -> path 요소 조정으로 순서를 맘대로 바꿀 수 있다.

color 기준: country

1
2
3
4
5
6
7
8
9
fig = px.treemap(df_PL_JnC_21n19, path=[px.Constant("2019n2021"),'year','Program_Language','Country'],
values='counts', color='Country',
color_discrete_map={'(?)':'lightgrey', 'China':'gold', 'Japan':'darkblue'})

fig.data[0].textinfo = 'label+percent parent+value'

fig.update_layout(margin = dict(t=0, l=0, r=0, b=0))

fig.show()

color 참조 값을 counts로 넣었을 때는 plotly.express 설정대로 colorbar가 나온다.

color 기준: counts

1
colors = ['#D2691E','#E19B50','#E6C17B','#F0CB85','#F5D08A','#FFEFD5']
1
2
3
4
5
6
7
8
fig = px.treemap(df_PL_JnC_21n19, path=[px.Constant("2019n2021"),'year','Program_Language','Country'],
values='counts', color='counts', color_continuous_scale=colors)

fig.data[0].textinfo = 'label+percent parent+value'

fig.update_layout(margin = dict(t=0, l=0, r=0, b=0))

fig.show()

Kaggle_Survey02: Bar 시각화 [plotly]

이전 포스팅들과 동일 과정

1
2
3
4
import pandas as pd
import plotly.graph_objects as go

colors = ['#FF0000','#FFBB00','#ffff00','#00FF00','#0000FF','#9C009C']
1
2
df = pd.read_csv("https://raw.githubusercontent.com/hangack/project-green/main/Kaggle_Survey-2021/data/kaggle-survey-2021/kaggle_survey_2021_responses.csv", dtype='unicode')
#df = pd.read_csv("../input/kaggle-survey-2021/kaggle_survey_2021_responses.csv")
1
2
3
4
df_ChJp = df[df.Q3.isin(["Japan","China"])]

df_Ch = df_ChJp[df_ChJp.Q3.isin(["China"])]
df_Jp = df_ChJp[df_ChJp.Q3.isin(["Japan"])]
1
2
3
def indiQ_value_counts(dataframe, indi_Qnum):
df = dataframe[indi_Qnum][1:].value_counts()
return df
1
2
df_Jp_age = indiQ_value_counts(df_Jp, 'Q1')
df_Ch_age = indiQ_value_counts(df_Ch, 'Q1')

Age [plotly: Bar]

01에 이어 이번에도 두 나라의 값을 비교할 예정이니 아예 처음부터 데이터를 합쳐서 표현한 그래프를 뽑아내겠다.

1
2
3
4
5
6
7
8
Bar_C = go.Bar(name='China',
x=df_Ch_age.index,
y=df_Ch_age.values
)
Bar_J = go.Bar(name='Japan',
x=df_Jp_age.index,
y=df_Jp_age.values
)
1
2
3
4
5
6
7
8
fig = go.Figure(data=[Bar_C,
Bar_J])

fig.update_layout(title='Age: Japan & China',
xaxis_title="Age", yaxis_title='Counts'
)

fig.show()

Bar1

bar chart에서 stack 형식을 사용하거나 group과 stack을 동시에 사용하지 않는 이상 하나의 plot에 여러 bar data를 넣으면 default는 group 형식으로 뽑힌다.

index 정렬

나이 순으로 출력하고 싶었지만, value_counts 할 때 원본 dataframe의 요소 순서로 index가 들어가버렸다.

그래서 value_counts된 dataframe을 sort_index를 사용해 오름차순 정렬한다.

1
2
df_Ch_sortAge = df_Ch_age.sort_index()
df_Jp_sortAge = df_Jp_age.sort_index()

Bar2

60-69 구간에 더미값 추가

정렬은 문제없어 보였지만 70+와 60-69 순서가 이상하다.

1
df_Ch_sortAge
18-21    206
22-24    274
25-29    159
30-34    109
35-39     39
40-44     14
45-49      8
50-54      1
55-59      2
70+        1
Name: Q1, dtype: int64

아무래도 China에 60-69 구간에 해당하는 value가 없어서 index 추가가 안된거같다.

index가 전부 있는 Japan을 앞 순서로 바꿔도 되겠지만, 그냥 China 60-69 index를 추가하고 임의로 값 0를 넣겠다.

1
2
df_Ch_sortAge.loc['60-69'] = 0
df_Ch_sortAge = df_Ch_sortAge.sort_index()

Bar3

외부링크

Kaggle_Survey01: Pie 시각화 [plotly]

dataset 구조 확인하기

1
2
3
4
import pandas as pd
import plotly.graph_objects as go

colors = ['#FF0000','#FFBB00','#ffff00','#00FF00','#0000FF','#9C009C']
1
2
df = pd.read_csv("https://raw.githubusercontent.com/hangack/project-green/main/Kaggle_Survey-2021/data/kaggle-survey-2021/kaggle_survey_2021_responses.csv", dtype='unicode')
#df = pd.read_csv("../input/kaggle-survey-2021/kaggle_survey_2021_responses.csv")

Columns 구조는 문자열에서 특정 값을 뽑아내고 input을 받는 함수 포스트에서 확인했으므로 넘어간다.

비교 대상 선정하기

2021 kaggle_survey 분석을 계속 진행한다.

베이스는 2021년 기준 survey 응답 count 수가 비슷한 일본과 중국을 선정했다.
한국 넣으려다 응답수가 낮아 방향을 바꿨다

kaggle_survey_2021_responses의 모든 row를 사용할 필요 없으므로 Q3(country) 응답에 Jp(Japan), Ch(China)인 요소만 추출한다.

1
2
3
4
df_ChJp = df[df.Q3.isin(["Japan","China"])]

df_Ch = df_ChJp[df_ChJp.Q3.isin(["China"])]
df_Jp = df_ChJp[df_ChJp.Q3.isin(["Japan"])]

Gender [plotly: Pie]

일단 간단히 비교할 수 있는 Gender(Q2)와 Age(Q1) 중 Q2를 Pie 그래프로 시각화할 예정이다.

간단한 Pie 그래프를 사용할 예정이고, 간단한 그래프인 만큼 pie 요소 option을 만질 여지가 많다.
따라서 express가 아닌 graph_objects 모듈로 작업했다.

plotly.graph_objects.Pie를 사용해서 만든 그래프를 Figure 형식으로 지정하고 fig_j 객체에 저장한다.

아래 코드는 필수 요소인 lablesvalues만 넣은 결과다.

1
2
3
4
5
6
7
fig_j = go.Figure(data=[go.Pie(labels=df_Jp['Q2'][1:].value_counts().index, 
values=df_Jp['Q2'][1:].value_counts().values
)
]
)

fig_j.show()

Pie1

대응하는 value_counts 함수 만들기

앞으로 많은 그래프를 그려낼거고 df_Jp['Q2'][1:].value_counts() 형식이 반복된다.

df_Jp['Q2'][1:].value_counts()을 객체로 만들어서 넣어도 되겠지만, 이번 작업에서 사용할 df은 df_Jp&df_Ch 2개로 dataframe 객체의 변동이 있고, 칼럼명도 Q1,Q2로 변동이 있다.
위 조건에 부합하는 간단한 함수 하나 만들겠다.

1
2
3
def indiQ_value_counts(dataframe, indi_Qnum):
df = dataframe[indi_Qnum][1:].value_counts()
return df
1
2
df_Jp_gen = indiQ_value_counts(df_Jp, 'Q2')
df_Ch_gen = indiQ_value_counts(df_Ch, 'Q2')

subplots: 그래프 figure 합치기

japan과 china 함수를 각각의 figure로 보기엔 불편하다.
subplost를 이용해 하나의 fig로 합칠 예정이다.

1
from plotly.subplots import make_subplots
1
2
3
4
5
6
7
Pie_J = go.Pie(labels=df_Jp_gen.index, 
values=df_Jp_gen.values
)

Pie_C = go.Pie(labels=df_Ch_gen.index,
values=df_Ch_gen.values
)
1
2
3
4
5
6
fig = make_subplots(rows=1, cols=2,specs=[[{"type": "domain"},{"type": "domain"}]])

fig.add_trace(Pie_J,row=1,col=1)
fig.add_trace(Pie_C,row=1,col=2)

fig.show()

Pie1

text, color 커스텀

커스텀 색상이나 타이틀 등 텍스트를 넣어 간단한 시각적 커스텀을 입혀보자

1
2
3
4
5
6
7
8
9
10
11
Pie_J = go.Pie(labels=df_Jp_gen.index, 
values=df_Jp_gen.values,
title='Japan',
textinfo ='label,percent'
)

Pie_C = go.Pie(labels=df_Ch_gen.index,
values=df_Ch_gen.values,
title='China',
textinfo ='label,percent'
)
1
2
3
4
5
6
7
8
9
fig = make_subplots(rows=1, cols=2,specs=[[{"type": "domain"},{"type": "domain"}]])

fig.add_trace(Pie_J,row=1,col=1)
fig.add_trace(Pie_C,row=1,col=2)

fig.update_layout(title_text='Gender')
fig.update_traces(marker=dict(colors=colors[1:]))

fig.show()

Pie1

시각 요소 커스텀

Trace의 title이 Pie 외부에 위치하는게 맘에들지 않는 부분을 수정하기 위해 시각 효과에서 legend를 제거하는 등 각종 요소 값을 변경한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Pie_J = go.Pie(labels=df_Jp_gen.index, 
values=df_Jp_gen.values,
# pull=[0,0,0.2,0.2,0.2], ## 중앙에서 n% 떨어진 위치 할당
title='Japan',
textinfo ='label,percent',
hole=0.3
)

Pie_C = go.Pie(labels=df_Ch_gen.index,
values=df_Ch_gen.values,
# pull=[0,0,0.2,0.2,0.2],
title='China',
textinfo ='label,percent',
hole=0.3
)
1
2
3
4
5
6
7
8
9
10
11
12
13
fig = make_subplots(rows=1, cols=2,specs=[[{"type": "domain"},{"type": "domain"}]])

fig.add_trace(Pie_J,row=1,col=1)
fig.add_trace(Pie_C,row=1,col=2)

fig.update_layout(title_text='Gender',
# showlegend=False, ## ledend(lable 목록) 시각적으로 제거
margin=dict(t=0, b=0, l=0, r=0)
)
fig.update_traces(marker=dict(colors=colors[1:]))


fig.show()

외부링크

plotly 동적 그래프 웹페이지에 삽입하기

plotly에 그래프 업로드

Kaggle_Survey01: Pie [Plotly]에서 작성한 plotly chart는 동적 그래프라 이미지로 사용하긴 아쉽고 github page의 ipynb에서도 동작하지 않는다.

그래프를 끌어오기 위해 plotly 홈페이지 저장환경을 이용할 예정이다.

chart_studio 설치

우선 사용할 작업환경에 chart_studio 라이브러리를 설치해주자.

1
$ pip i chart_studio

※ jupyter 로컬 작업환경을 사용한다면 anaconda prompt로 설치

chart_studio는 plotly 그래프를 plotly 홈페이지에 업로드하고 원한다면 html iframe 태그로 변환까지 해주는 녀석이다.

plotly Access Key

plotly 개인 공간에 업로드 할 예정이니 plotly 회원가입을 진행하자.

[profile] - [API keys] 에서 Access key를 얻어온다.

API key

위에서 설치한 라이브러리를 import하고 API key를 사용해 계정에 접근하자

1
2
import chart_studio
chart_studio.tools.set_credentials_file(username='유저명', api_key='접근키')

성공적으로 연동했다면 저장할 figure 객체와 저장될 파일명을 넣어준다.

1
chart_studio.plotly.plot(fig, filename = '파일명', auto_open=True)
'https://plotly.com/~hangack/1/'

out된 url에 들어가보면 그래프가 업로드 되었을거다.

웹페이지에 그래프 끌어오기

원래 목적이었던 웹페이지에서 그래프를 사용해보자.

html iframe

iframe(inline frame) html 형식을 수작업으로 작성해도 되겠지만 chart_studio 모듈 내 라이브러리에서도 변환할 수 있다.

1
chart_studio.tools.get_embed('https://plotly.com/~hangack/1/#/')
'<iframe id="igraph" scrolling="no" style="border:none;" seamless="seamless" src="https://plotly.com/~hangack/1.embed" height="525" width="100%"></iframe>'
1
<iframe id="igraph" scrolling="no" style="border:none;" seamless="seamless" src="https://plotly.com/~hangack/1.embed" height="525" width="100%"></iframe>

iframe(inline frame):

hexo tag plugin iframe

hexo 환경에서 작성중이라면 기본 plugin인 tag 문법으로도 iframe을 삽입할 수 있다.

1
{% iframe https://plotly.com/~hangack/1.embed %}

외부링크