설문조사를 분석하고 시각화하는데 좋은 자료가 있어서 포스팅을 한다.

자료는 아래서 참조하였다.

ref.
corazzon / KaggleStruggle / kaggle-survey-2017 / Kaggle-ML-DS-survey-2017-EDA-FAQ.ipynb
https://github.com/corazzon/KaggleStruggle/blob/master/kaggle-survey-2017/Kaggle-ML-DS-survey-2017-EDA-FAQ.ipynb



분석에 필요한 자료는 아래링크에서 Data탭에 들어가면 구할 수 있다.



https://www.kaggle.com/kaggle/kaggle-survey-2017





============================ Python ============================

import pprint


import pandas as pd

import numpy as np

from scipy import stats

import matplotlib.pyplot as plt

# 이미지를 그려주는 모듈.

import seaborn as sns




# 데이터 프레임의 컬럼을 최대 12개로 늘린다.

pd.set_option('display.max_columns', 12)


# schema.csv를 question 객체에 담기

question = pd.read_csv('schema.csv')


# multipleChoiceResponses.csv를 mcq에 담기. encoding='ISO-8859-1'은 범용적으로 사용되는 인코딩이다.

mcq = pd.read_csv('multipleChoiceResponses.csv', encoding='ISO-8859-1', low_memory=False)


# 한국 자료를 따로 설정해준다.

korea = mcq.loc[mcq.Country == 'South Korea']








### 어디서 데이터 사이언스를 배워야 하는지를 확인

    # print(mcq['LearningPlatformSelect'].head())  # 데이터 확인

'''

'어디서 배워야 하는가?'라는 질문에 대해서 중복 응답이 가능하므로 

중복응답들을 다 나눠서 갯수를 세어야 한다.

이를 위해서

1. 한 줄로 되어있는 응답을 각 원소별로 나눠서 리스트에 저장.

2. 리스트의 원소값을 분리해서 한 행에 하나의 데이터만 들어가도록 데이터 처리.

    2-1. 리스트로 표현된 자료를 2 level 인덱스를 생성하여 한 행에 하나의 데이터만 들어가도록 바꾼다.

    2-2. 2 level 인덱스 중, 하나를 없애서 보기 편하게 바꾼다.

3. 각 원소의 갯수를 세서 하나의 응답이 몇 번 나왔었는지 확인.

이 순서로 데이터 처리가 진행되어야 한다.

'''

# LearningPlatformSelect컬럼을 확인한다.

mcq['LearningPlatformSelect'] = mcq['LearningPlatformSelect'].astype('str').apply(lambda x: x.split(','))

    # print(mcq['LearningPlatformSelect'])  # 데이터 확인. 각 응답자들의 응답이 리스트로 저정되어있다.

'''

'.apply() 메서드'

DataFrame.apply(func, axis=0, broadcast=None, raw=False, reduce=None, result_type=None, args=(), **kwds)


Apply a function along an axis of the DataFrame.

Objects passed to the function are Series objects 

whose index is either the DataFrame’s index (axis=0) or the DataFrame’s columns (axis=1). 

DataFrame의 축을 따라 함수를 적용하십시오.

함수에 전달 된 객체는 DataFrame의 인덱스 (축 = 0) 또는 DataFrame의 열 (축 = 1) 인 

인덱스가있는 Series 객체입니다. - 구글 번역


.apply()메서드는 데이터 프레임의 행이나 열에 대해서 func을 적용시켜 데이터를 바꿔주는 메서드이다.




'mcq['LearningPlatformSelect'] 해석'

1. 한 줄로 되어있는 응답을 각 원소별로 나눠서 리스트에 저장. 을 한다.

mcq의 컬럼 LearningPlatformSelect에 존재하는 값을 string값으로 바꿔준다. string으로 바꿔주는 이유는

뒤의 apply()에 나오는 lambda가 split(',')을 사용하는데 이는 string에서만 사용 가능하기 때문이다.

그런데 이 항목에 대해 대답을 안 한 사람의 데이터가 NaN이 되고 이는 float로 인식된다.

그래서 astype('str')로 컬럼 내의 데이터를 전부 string으로 바꿔줘야 

.apply(lambda x: x.split(','))가 제대로 동작 할 수 있다.

(ex) print(type(mcq['LearningPlatformSelect'][16]))

'''

s = mcq.apply(

    lambda x: pd.Series(x['LearningPlatformSelect']), axis=1)\

    .stack().reset_index(level=1, drop=True)

    # 한 사람의 응답에는 같은 인덱스 번호를 부여하여 어떤 응답을 했는지 리스트 형태가 아닌 개별원소로 보여준다.

    # print(s.head(10))

'''

's에 대한 해석'

2. 리스트의 원소값을 분리해서 한 행에 하나의 데이터만 들어가도록 데이터 처리. 를 한다.

.apply(lambda x: pd.Series(x['LearningPlatformSelect']), axis=1)

mcq의 LearningPlatformSelect컬럼 중, axis가 1인 즉, 열의 값을 선택해서 내부의 데이터를

Series 데이터 구조로 바꾼다.


    2-1. 리스트로 표현된 자료를 2 level 인덱스를 생성하여 한 행에 하나의 데이터만 들어가도록 바꾼다.

.stack()

그렇게 나온 값을 .stack()을 이용해서 2 level의 데이터 프레임으로 바꿔준다. 여기서 2레벨이라는 것은

인덱스를 2개 사용해서 2차원 배열 구조를 시각화 한 것을 말한다.

s = mcq.apply(

    lambda x: pd.Series(x['LearningPlatformSelect']), axis=1)\

    .stack()

print(s.head(10)) 

0  0    College/University

   1           Conferences

   2              Podcasts

   3            Trade book

1  0                Kaggle

2  0                 Arxiv

   1    College/University

   2                Kaggle

   3        Online courses

   4        YouTube Videos

.stack() 메서드를 사용하면 

0번 인덱스에 저장되었던 값이 세부항목을 리스트가 아닌 리스트에 달려있던 인덱스 넘버로 출력되는 것을 알 수 있다.


    2-2. 2 level 인덱스 중, 하나를 없애서 보기 편하게 바꾼다.

.reset_index(level=1, drop=True)

.stack()까지 2 레벨의 데이터 프레임의 인덱스 중, level=1의 인덱스를 drop시킨다.

즉, 위에서 봤을 때 0 1 2 3 0 0 1 2 3 4 .... 로 진행되는 인덱스를 drop시킨다는 뜻이다.

참고로 맨 앞의 0     1 2      처럼 표현되는 인덱스는 level=0 이다.



최종적으로 s는 아래와 같이 나온다.

0    College/University

0           Conferences

0              Podcasts

0            Trade book

1                Kaggle

2                 Arxiv

2    College/University

2                Kaggle

2        Online courses

2        YouTube Videos

dtype: object

'''

s.name = 'platform'  # <class 'pandas.core.series.Series'> 인 s에 컬럼 이름을 platform이라고 명명해준다.

# 출력 될 figure의 크기를 설정한다. figsize=(가로, 세로)이다.

# https://matplotlib.org/api/figure_api.html?highlight=figure#module-matplotlib.figure

plt.figure(figsize=(6, 8))

# s에서 s가 nan인 값을 제외하고 각 원소가 몇 개 있는지 갯수를 센다. 그런 다음, 상위 15개를 선택한다.

data = s[s != 'nan'].value_counts().head(15)

# print(data)  # 데이터 확인

'''

'data'

Kaggle                           6645

Online courses                   6042

Stack Overflow Q&A               5703

YouTube Videos                   5291

Personal Projects                4873

Blogs                            4828

Textbook                         4246

College/University               3397

Arxiv                            2418

Official documentation           2354

Conferences                      2217

Friends network                  1617

Tutoring/mentoring               1458

Podcasts                         1238

Non-Kaggle online communities    1169

Name: platform, dtype: int64

'''

# data에서는 s에서 데이터로 사용된 것이 index로 들어가게 되므로 y축에는 data.index, x축에는 data값을 위치시켜

# 가로로 누운 바 그래프를 만든다.

sns.barplot(y=data.index, x=data)

# plt.show()







# 설문내용과 누구에게 물어봤는지를 확인

qc = question.loc[question[

    'Column'].str.contains('LearningCategory')]

'''

question은 schema.csv를 담고 있는 데이터 프레임이다.

question의 Column이라는 명칭의 컬럼에서 LearningCategory라는 글자가 들어간 컬럼만 선택해서

컬럼의 명칭과 데이터를 qc에 담는다.

'''

# print(qc.shape)  # (7, 3)

# print(qc)

'''

'결과'

                           Column  \

91    LearningCategorySelftTaught   

92  LearningCategoryOnlineCourses   

93           LearningCategoryWork   

94     LearningCategoryUniversity   

95         LearningCategoryKaggle   

96          LearningCategoryOther   

97  LearningCategoryOtherFreeForm   


                                             Question Asked  

91  What percentage of your current machine learni...   All  

92  What percentage of your current machine learni...   All  

93  What percentage of your current machine learni...   All  

94  What percentage of your current machine learni...   All  

95  What percentage of your current machine learni...   All  

96  What percentage of your current machine learni...   All  

97  What percentage of your current machine learni...   All  

'''






# mcq의 컬럼 중, LearningPlatformUsefulness가 들어간 것들을 찾아서 use_features 리스트에 넣는다.

use_features = [x for x in mcq.columns if x.find(

    'LearningPlatformUsefulness') != -1]


# 학습플랫폼과 유용함에 대한 연관성을 살펴본다.

fdf = {}  # 데이터를 담을 사전 타입의 객체를 생성한다.

for feature in use_features:

    a = mcq[feature].value_counts()  # use_features에서 담긴 각 항목들의 갯수를 센다.

    a = a/a.sum()  # 퍼센트로 표현한다.

    # fdf에 LearningPlatformUsefulnessArxiv의 LearningPlatformUsefulness을 뺀 것을 key로, a를 value로 한다.

    fdf[feature[len('LearningPlatformUsefulness'):]] = a


    # print(fdf)  # 데이터 확인

'''

'fdf 데이터'

행에 '유용하지 않다.', '조금 유용하다.', '많이 유용하다.'가 있고

열에 fdf{} 키의 값이 배치되었다. 

'''


fdf = pd.DataFrame(fdf).transpose().sort_values(

    'Very useful', ascending=False)

'''

위에서 나온 행과 열의 위치를 바꿔주기 위해서 .transpose()를 하고 Very useful컬럼을 내림차순으로 정렬한다.

Very useful에 대한 내림차순 정렬을 하기 위해서 위와 같은 변형을 한 것이다.

'''

    # print(fdf)  # 데이터 확인


# 학습플랫폼들이 얼마나 유용한지에 대한 상관관계를 그려본다.

plt.figure(figsize=(10, 10))

sns.heatmap(

    fdf.sort_values(

        "Very useful", ascending=False), annot=True)

'''

annot=True이면 각 셀에 데이터 값을 씁니다. 

annot는 annotation(주석)의 약자이다.

'''

# plt.show()


# 유용함의 정도를 각 플랫폼별로 그룹화 해서 본다.

fdf.plot(kind='bar', figsize=(20,8),

         title="Usefullness of Learning Platforms")

# plt.show()




============================ Python ============================

+ Recent posts