파이썬 데이터 시각화 본문

파이썬 응용

파이썬 데이터 시각화

꼬마곰 2021. 5. 18. 11:41
반응형

파이썬 시각화

차트 종류
1. Column/Bar chart : 데이터들 간 비교, 순위, 시계열분석
2. Dural Axis, 파레토 chart : 데이터들 간 비교, 순위, 파레토는 히스토그램의 일종
3. Pie chart : 전체 중 비율, 데이터들 간 비교
4. Line chart : 트렌드 파악/시계열 분석, 누적 비율
5. Scatter chart : 상관관계, 선형회귀
6. Bubble chart : Scatter chart의 변형, BCG Matrix
7. Heat map : 상관관계
8. Histogram : 분산
9. Box plot : 분산
10. Geo chart : 지역별 분산

 

 # 필요한 라이브러리 inport
 
  import pandas as pd
  import numpy as np
  
  import matplotlib.pyplot as plt # 시각화 라이브러리
  import seaborn as sns		  # 시각화 라이브러리
  
  from tqdm import tqdm_notebook  # for문 진행상황을 게이지로 표시
  
  #파이썬 warning 무시
  import warnings
  warnings.filterwarnings(action='ignore')

1. column 차트

part1. 참가자 많은 나이 순서대로 column chart 그리기

 marathon_2015_2017 = pd.read_csv('./data_boston/marathon_2015_2017.csv')
 
 # 미국인 데이터만 가져오기
 USA_runner= marathon_2015_2017[marathon_2015_2017.Country=='USA']

 print(USA_runner.shape)
 USA_runner.head(3)

(64474, 21)

 USA_runner.info()

<class 'pandas.core.frame.DataFrame'>

Int64Index: 64474 entries, 6 to 79637

Data columns (total 21 columns):

# Column Non-Null Count Dtype

--- ------ -------------- -----

0 Name 64474 non-null object

1 Age 64474 non-null int64

2 M/F 64474 non-null object

3 City 64474 non-null object

4 State 64474 non-null object

5 Country 64474 non-null object

6 5K 64474 non-null int64

7 10K 64474 non-null int64

8 15K 64474 non-null int64

9 20K 64474 non-null int64 1

....

20 Year 64474 non-null int64

dtypes: int64(16), object(5)

memory usage: 10.8+ MB

(1) State 별 runner 수

 # column 그래프 그리기(필수)
 plt.figure(figsize=(20, 10))                                # 그래프 크기
 runner_state = sns.countplot('State', data=USA_runner)      # 그래프 함수 : sns.countplot() 사용

 # column 그래프 부가 설명(옵션)
 runner_state.set_title('Number of runner by State - USA', fontsize=18)   # 제목
 runner_state.set_xlabel('State', fontdict={'size':16})                   # x축 이름
 runner_state.set_ylabel('Number of runner', fontdict={'size':16})        # y축 이름
 plt.show()

-> MA주가 가장 참가자 수가 많다. 남/녀 누가 더 많이 참가했을까?

(2) State, Gender 별 runner 수

 # column 그래프 그리기(필수)
 plt.figure(figsize=(20, 10))                                                                   # 그래프 크기
 runner_state = sns.countplot('State', data=USA_runner, hue='M/F', palette={'F':'y', 'M':'b'})  # 그래프 함수 : sns.countplot() 사용
                                                      # hue : 칼럼명 기준으로 데이터 구분해줌
 # column 그래프 부가 설명(옵션)
 runner_state.set_title('Number of runner by State, Gender - USA', fontsize=18)   # 제목
 runner_state.set_xlabel('State', fontdict={'size':16})                   # x축 이름
 runner_state.set_ylabel('Number of runner', fontdict={'size':16})        # y축 이름
 plt.show()

-> MA주는 여성들의 참여가 더 높다

년도별로 참가자 수를 보고 싶으면?

 

(3) 년도별 runner 수

 # column 그래프 그리기(필수)
 plt.figure(figsize=(20, 10))                                                                   # 그래프 크기
 runner_state = sns.countplot('State', data=USA_runner, hue='Year')  # 그래프 함수 : sns.countplot() 사용
                                                      # hue : 칼럼명 기준으로 데이터 구분해줌
 # column 그래프 부가 설명(옵션)
 runner_state.set_title('Number of runner by State, Year - USA', fontsize=18)   # 제목
 runner_state.set_xlabel('State', fontdict={'size':16})                   # x축 이름
 runner_state.set_ylabel('Number of runner', fontdict={'size':16})        # y축 이름
 plt.show()

-> MA 주는 가장 참여자가 많은 주인데 매년 참가자 수가 줄고 있다. CA 주는 올해 참가자 수가 증가한 것으로 봐서 캠페인을 잘 한 것 같다.

2. Dual Axis, 파레토 차트

이타리아 학자 파레토가 부의 불균형을 설명하려고 만든 차트(80/20 rule)

데이터들 간 비교,  순위, 히스토그램에 사용됨

 import pandas as pd
 import matplotlib.pyplot as plt

 marathon_2015_2017 = pd.read_csv('./marathon_2015_2017.csv')

 #### 18세~59세 데이터만 가져오기 : isin()
 runner_18_59 = marathon_2015_2017[marathon_2015_2017.Age.isin(range(18, 60))]
 print(runner_18_59)

Name Age M/F City State Country 5K 10K \

0 Desisa, Lelisa 25 M Ambo NaN ETH 883 1783

1 Tsegay, Yemane Adhane 30 M Addis Ababa NaN ETH 883 1783

2 Chebet, Wilson 29 M Marakwet NaN KEN 883 1783

3 Kipyego, Bernard 28 M Eldoret NaN KEN 883 1784

4 Korir, Wesley 32 M Kitale NaN KEN 883 1784

... ... ... .. ... ... ... ... ...

79631 Leroy, Stefan M. 25 M Jupiter FL USA 2398 5153

79632 Quinn, Adam H. 19 M Belmont MI USA 2114 4233

79634 Avelino, Andrew R. 25 M Fayetteville NC USA 1923 3933

79635 Hantel, Johanna 57 F Malvern PA USA 3191 6216

79637 Rigsby, Scott 48 M Alpharetta GA USA 2376 4632

15K 20K ... 25K 30K 35K 40K Pace Official Time \

0 2697 3629 ... 4567 5520 6479 7359 296 7757

1 2698 3628 ... 4567 5519 6479 7362 298 7788

2 2697 3629 ... 4567 5520 6479 7381 299 7822

3 2701 3629 ... 4567 5520 6483 7427 300 7847

4 2698 3628 ... 4567 5520 6479 7407 300 7849

... ... ... ... ... ... ... ... ... ...

79631 7821 10867 ... 13986 17380 20571 23668 953 24971

79632 6470 9238 ... 14471 16979 19995 24171 972 25473

79634 6737 10181 ... 13819 17401 21228 24861 1000 26219

79635 9156 0 ... 15321 18397 21633 24878 1007 26377

79637 7210 10735 ... 16034 20233 23947 27683 1095 28694

Overall Gender Division Year

0 1 1 1 2015

1 2 2 2 2015

2 3 3 3 2015

3 4 4 4 2015

4 5 5 5 2015

... ... ... ... ...

79631 26405 14434 4772 2017

79632 26406 14435 4773 2017

79634 26408 14436 4774 2017

79635 26409 11973 698 2017

79637 26411 14438 2553 2017

[73608 rows x 21 columns]

 #### 18~59세 나이대별로 카운트 : value_counts()
 runner_18_59_counting = runner_18_59.Age.value_counts()
 runner_18_59_counting

45 3236

46 3039

40 2734

47 2566

50 2498

41 2494

35 2327

42 2318

48 2277

43 2265

36 2188

38 2128

51 2124

37 2108

39 2101

44 2056

49 2018

52 1930

55 1920

29 1906

30 1849

33 1834

31 1779

28 1758

34 1756

27 1755

53 1730

32 1726

26 1709

25 1539

56 1514

54 1433

24 1301

57 1287

58 1044

23 920

59 788

22 701

21 489

20 264

19 137

18 62

Name: Age, dtype: int64

x축 : Age 나열

 x = runner_18_59_counting.index

 print(type(x[0]))
 print(x)

<class 'numpy.int64'>

Int64Index([45, 46, 40, 47, 50, 41, 35, 42, 48, 43, 36, 38, 51, 37, 39, 44, 49, 52, 55, 29, 30, 33, 31, 28, 34, 27, 53, 32, 26, 25, 56, 54, 24, 57, 58, 23, 59, 22, 21, 20, 19, 18], dtype='int64')

 # int값을 str 값으로 바꾸기
 x = [str(i) for i in x]
 print(type(x[0]))
 print(x)

<class 'str'>

['45', '46', '40', '47', '50', '41', '35', '42', '48', '43', '36', '38', '51', '37', '39', '44', '49', '52', '55', '29', '30', '33', '31', '28', '34', '27', '53', '32', '26', '25', '56', '54', '24', '57', '58', '23', '59', '22', '21', '20', '19', '18']

y축 : 값 나열

 y = runner_18_59_counting.values
 print(type(y[0]))
 print(y)

<class 'numpy.int64'>

[3236 3039 2734 2566 2498 2494 2327 2318 2277 2265 2188 2128 2124 2108 2101 2056 2018 1930 1920 1906 1849 1834 1779 1758 1756 1755 1730 1726 1709 1539 1514 1433 1301 1287 1044 920 788 701 489 264 137 62]

 ratio = y/y.sum()
 ratio

array([0.04396261, 0.04128627, 0.0371427 , 0.03486034, 0.03393653, 0.03388219, 0.03161341, 0.03149114, 0.03093414, 0.03077111, 0.02972503, 0.0289099 , 0.02885556, 0.02863819, 0.02854309, 0.02793175, 0.0274155 , 0.02621998, 0.02608412, 0.02589392, 0.02511955, 0.02491577, 0.02416857, 0.02388327, 0.0238561 , 0.02384252, 0.02350288, 0.02344854, 0.02321759, 0.02090805, 0.02056842, 0.01946799, 0.01767471, 0.01748451, 0.01418324, 0.01249864, 0.01070536, 0.00952342, 0.0066433 , 0.00358657, 0.00186121, 0.0008423 ])

 # 누적데이터 보여주는 함수 : cumsum()
 ratio_sum = ratio.cumsum()
 ratio_sum

array([0.04396261, 0.08524889, 0.12239159, 0.15725193, 0.19118846, 0.22507064, 0.25668406, 0.2881752 , 0.31910934, 0.34988045, 0.37960548, 0.40851538, 0.43737094, 0.46600913, 0.49455222, 0.52248397, 0.54989947, 0.57611944, 0.60220356, 0.62809749, 0.65321704, 0.67813281, 0.70230138, 0.72618465, 0.75004076, 0.77388327, 0.79738615, 0.82083469, 0.84405228, 0.86496033, 0.88552875, 0.90499674, 0.92267145, 0.94015596, 0.9543392 , 0.96683784, 0.9775432 , 0.98706662, 0.99370992, 0.99729649, 0.9991577 , 1. ])

그래프 그리기

 # enumerate : index도 함께 보고 싶을 때 사용
 for i, data in enumerate(range(3, 14)):
    print(i, data)

0 3

1 4

2 5

3 6

4 7

5 8

6 9

7 10

8 11

9 12

10 13

 # figsize 지정
 fig, barChart = plt.subplots(figsize=(20,8))

 # bar chart에 x, y값 넣어서 bar chart 생성
 barChart.bar(x, y)

 # line chart 생성
 lineChart = barChart.twinx()  # twinx() : 두 개의 차트가 서로 다른 y 축, 공통 x 축을 사용하게 해줌
 lineChart.plot(x, ratio_sum, '-ro', alpha = 1)  # alpha:투명도
 # ^: 세모, s : sqaured, o : circle
 # g : green, b: blue, r: red

 ######## ------- 잘라서 보여주기 -------- ########

 # 오른쪽 축(라인 차트 축) 레이블
 ranges = lineChart.get_yticks() # y차트의 단위들
 lineChart.set_yticklabels(['{0:0.1%}'.format(x) for x in ranges]) # 오른쪽 단위 0.1% 소수점 한 자리까지 

 # 라인차트 데이터 별 %값 주석(annotation)
 ratio_sum_percentages = ['{0:.0%}'.format(x) for x in ratio_sum]
 for i, txt in enumerate(ratio_sum_percentages):
    lineChart.annotate(txt, (x[i], ratio_sum[i]), fontsize=12)

 # x, y label만들기
 barChart.set_xlabel('Age', fontdict={'size':16})
 barChart.set_ylabel('Number of runner', fontdict={'size':16})

 # plot에 title 만들기
 plt.title('Pareto Chart - Number of runner by Age', fontsize=18)



 plt.show()

-> 파레토 차트로 직관적으로 상위 n%를 확인할 수 있다

part2. 나이 순서대로 정렬해서 그래프 그리기

 import pandas as pd
 import matplotlib.pyplot as plt

 marathon_2015_2017 = pd.read_csv('./marathon_2015_2017.csv')
 #### 18세~59세 데이터만 가져오기 : isin() : 컬럼에서 어떤 특정 값을 포함하고 있는것만 걸러낼 때
 runner_18_59 = marathon_2015_2017[marathon_2015_2017.Age.isin(range(18, 60))]
 # print(runner_18_59)

 #### 18~59세 나이대별로 카운트 : value_counts()
 runner_18_59_counting = runner_18_59.Age.value_counts()
 # print(runner_18_59_counting)

나이와 참가자 수 각각 데이터프레임에 칼럼 추가 -> Age를 이용한 sort 가능

 runner_age = pd.DataFrame({
    'Age': runner_18_59_counting.index,
    'Count': runner_18_59_counting
 })
 
 runner_age_sort = runner_age.sort_values(by='Age')

 # runner_age_sort 값 기준
 x = runner_age_sort.index
 # int값을 str 값으로 바꾸기
 x = [str(i) for i in x]

 # y값도 변경
 y = runner_age_sort['Count']
 
 # 누적데이터 보여주는 함수 : cumsum()
 ratio = y/y.sum()
 ratio_sum = ratio.cumsum()
 print(ratio_sum)

 # y 누적값을 리스트 형식으로 바꿔주기
 y_ratio = [i for i in ratio_sum]
 print(y_ratio)

18 0.000842

19 0.002704

20 0.006290

21 0.012933 

.......

56 0.957627

57 0.975111

58 0.989295

59 1.000000

Name: Count, dtype: float64

[0.0008422997500271709, 0.0027035104879904355, 0.0062900771655254855, 0.012933376806868818, 0.02245679817411151, 0.0349554396261276, 0.05263014889685904, 0.07353820236930769, 0.09675578741441149, 0.12059830453211609, 0.14448157808933815, 0.17037550266275409, 0.19549505488533858, 0.21966362351918273, 0.24311216172155203, 0.2680279317465493, 0.29188403434409305, 0.32349744592979024, 0.3532224758178459, 0.3818606673187697, 0.41077056841647647, 0.43931366155852625, 0.47645636343875664, 0.5103385501575916, 0.5418296924247364, 0.5726008042604065, 0.6005325508096946, 0.6444951635691772, 0.6857814368003478, 0.7206417780676013, 0.7515759156613412, 0.7789914139767417, 0.8129279426149332, 0.8417835017932833, 0.8680034778828388, 0.8915063580045647, 0.9109743506140636, 0.9370584719052276, 0.9576268883816975, 0.9751114009346808, 0.9892946418867513, 0.9999999999999999]

 # 데이터 그리기

 # figsize 지정
 fig, barChart = plt.subplots(figsize=(20,10))

 # bar chart에 x, y값 넣어서 bar chart 생성
 barChart.bar(x, y)

 # line chart 생성
 lineChart = barChart.twinx()
 lineChart.plot(x, ratio_sum, '-g^', alpha = 0.5)  # alpha:투명도

 # 오른쪽 축(라인 차트 축) 레이블
 ranges = lineChart.get_yticks() # y차트의 단위들
 lineChart.set_yticklabels(['{0:.1%}'.format(x) for x in ranges])

 # 오른쪽 축(라인 차트 축) 레이블
 ranges = lineChart.get_yticks() # y차트의 단위들
 lineChart.set_yticklabels(['{0:.1%}'.format(x) for x in ranges])

 # 라인차트 데이터 별 %값 주석(annotation)
 ratio_sum_percentages = ['{0:.0%}'.format(x) for x in ratio_sum]
 for i, txt in enumerate(ratio_sum_percentages):
    lineChart.annotate(txt, (x[i], y_ratio[i]), fontsize=12)  #변경된 부분: ratio_sum -> y_ratio

 # x, y label, title 만들기
 barChart.set_xlabel('Age', fontdict={'size':16})
 barChart.set_ylabel('Number of runner', fontdict={'size':16})
 plt.title('Dual Axis Chart - Number of runner by Age', fontsize=18)  # 제목 변경(dual axis chart)

 # show plot
 plt.show()

3. Pie chart

전체 100% 중 각 segment들이 차지르하는 비율

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

 marathon_2015_2017 = pd.read_csv('./marathon_2015_2017.csv')
 
 # 튜플 형태로 라벨 지정
 labels = 'Male', 'Female'
 labels

('Male', 'Female')

 # 차트를 입체적으로 보이게
 explode = (0, 0.5)

 marathon_2015_2017.columns

Index(['Name', 'Age', 'M/F', 'City', 'State', 'Country', '5K', '10K', '15K', '20K', 'Half', '25K', '30K', '35K', '40K', 'Pace',

         'Official Time', 'Overall', 'Gender', 'Division', 'Year'],

          dtype='object')

 marathon_2015_2017['M/F'].value_counts()

M    43482

   36156

Name: M/F, dtype: int64

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

 # pie chart 만들기(차트 띄우기, labels 달기, 각 조정, 그림자, 값 소숫점 표시)
 plt.pie(marathon_2015_2017['M/F'].value_counts(), explode=(0, 0.05), labels=labels, startangle=90, shadow=True, autopct='%.2f')

 # 라벨, 타이틀 달기
 plt.title('Male vs Female', fontsize=18)

 # 레전드 달기
 plt.legend(['Male', 'Female'], loc='upper right') # 오른쪽 위의 표시사항

 plt.show()

4. Line chart

트렌드 파악, 시계열 분석에 사용됨. 주로 시간 순서에 따른 추이를 확인

 import pandas as pd
 import matplotlib.pyplot as plt

 marathon_2015_2017.head(3)

필요한 칼럼만 가져와서 데이터프레임으로 만들기

 record = pd.DataFrame(marathon_2015_2017, columns=['5K','10K','15K','20K','Half','25K','30K','35K','40K','Official Time']).sort_values(
 by=['Official Time'])
 
 record.head()

칼럼 추가하기 : insert() - 값을 위치를 지정해서 추가하는 함수

 record.insert(0, 'Rank', range(1, len(record)+1))
 record.head(100)

100등까지만 가져오기

 top100 = record[0:100]
 top100

 yData_full = top100['Official Time']
 yData_10K = top100['10K']
 yData_20K = top100['20K']
 yData_30K = top100['30K']

Line chart 그리기

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

 plt.plot(xData, yData_full, 's')
 plt.plot(xData, yData_30K, '-')
 plt.plot(xData, yData_20K)
 plt.plot(xData, yData_10K) # . 점선/ - 선/ ^ 세모/ o 원/ s네모

 # 레전드 달기
 plt.legend(['Full', '30K', '20K', '10K'], loc='upper left')

 plt.show()

5. Scatter chart

변수 간 상관관계(correlation), 머신러닝- 선형회귀

 marathon_2015_2017 = pd.read_csv('./marathon_2015_2017.csv')
 
 MALE_runner = marathon_2015_2017[marathon_2015_2017['M/F']=='M']
 FEMALE_runner = marathon_2015_2017[marathon_2015_2017['M/F']=='F']
 
 FEMALE_runner.head()

 x_male = MALE_runner.Age
 y_male = MALE_runner['Official Time']

 x_female = FEMALE_runner.Age
 y_female = FEMALE_runner['Official Time']

Scatter chart 그리기

 # figure size 지정
 plt.figure(figsize=(20, 20))

 plt.plot(x_male, y_male, '.', color='b', alpha=0.5)
 plt.plot(x_female, y_female, '.', color='r', alpha=0.5)

 # label과 title 정하기
 plt.xlabel('Age', fontsize=30)
 plt.ylabel('Official Time(second)', fontsize=30)
 plt.title('Distribution by Running time and Age', fontsize=30)

 plt.legend(['Male', 'Female'], loc='upper left') # 범례

 plt.show()

6. Bubble chart

버블 사이즈를 통행 데이터의 양을 보여줌, scatter chart에서 변형된 형태

 marathon_results_2017 = pd.read_csv('./marathon_results_2017.csv')
 
 marathon_2017 = marathon_results_2017.drop(['Unnamed: 0', 'Bib', 'Citizen', 'Unnamed: 9', 'Proj Time'], axis='columns')
 
 marathon_2017.head()

초 단위로 바꾸기 : to_timedelta

 # pd.to_timedelt() 적용하기
 # .astype('m8[s]').astype(np.int64) 적용하기
 # -> 초단위로 바꾼 후, int 형태로 변환
 marathon_2017['5K'] = pd.to_timedelta(marathon_2017['5K']).astype('m8[s]').astype(np.int64)
 marathon_2017['10K'] = pd.to_timedelta(marathon_2017['10K']).astype('m8[s]').astype(np.int64)
 marathon_2017['15K'] = pd.to_timedelta(marathon_2017['15K']).astype('m8[s]').astype(np.int64)
 marathon_2017['20K'] = pd.to_timedelta(marathon_2017['20K']).astype('m8[s]').astype(np.int64)
 marathon_2017['Half'] = pd.to_timedelta(marathon_2017['Half']).astype('m8[s]').astype(np.int64)
 marathon_2017['25K'] = pd.to_timedelta(marathon_2017['25K']).astype('m8[s]').astype(np.int64)
 marathon_2017['30K'] = pd.to_timedelta(marathon_2017['30K']).astype('m8[s]').astype(np.int64)
 marathon_2017['35K'] = pd.to_timedelta(marathon_2017['35K']).astype('m8[s]').astype(np.int64)
 marathon_2017['40K'] = pd.to_timedelta(marathon_2017['40K']).astype('m8[s]').astype(np.int64)
 marathon_2017['Pace'] = pd.to_timedelta(marathon_2017['Pace']).astype('m8[s]').astype(np.int64)
 marathon_2017['Official Time'] = pd.to_timedelta(marathon_2017['Official Time']).astype('m8[s]').astype(np.int64)
 
 marathon_2017.head(10)

 check_time = 7200    # 2시간
 Lat = 0  # 초기값
 Long = 0 # 초기값
 Location = ''

 # 5K, 10K, 15K, 20K, 25K, 30K, 35K, 40K
 points = [[42.247835,-71.474357], [42.274032,-71.423979], [42.282364,-71.364801], [42.297870,-71.284260],
           [42.324830,-71.259660], [42.345680,-71.215169], [42.352089,-71.124947], [42.351510,-71.086980]]
 marathon_location = pd.DataFrame(columns=['Lat','Long'])
 marathon_location

 marathon_2017.tail()

 from tqdm import tqdm_notebook

 #time
 # 26000개 행을 돌면서 위치가 어디인지 판단한다.
 # iterrows() : 각각의 행을 돌아라는 뜻
 for index, record in tqdm_notebook(marathon_2017.iterrows()): # 각각 참가자들에 대해서
    if (record['40K'] < check_time):
        Lat = points[7][0]
        Long = points[7][1]
    elif (record['35K'] < check_time):
        Lat = points[6][0]
        Long = points[6][1]
    elif (record['30K'] < check_time):
        Lat = points[5][0]
        Long = points[5][1]
    elif (record['25K'] < check_time):
        Lat = points[4][0]
        Long = points[4][1]
    elif (record['20K'] < check_time):
        Lat = points[3][0]
        Long = points[3][1]
    elif (record['15K'] < check_time):
        Lat = points[2][0]
        Long = points[2][1]
    elif (record['10K'] < check_time):
        Lat = points[1][0]
        Long = points[1][1]
    elif (record['5K'] < check_time):
        Lat = points[0][0]
        Long = points[0][1]
    else:    
        Lat = points[0][0]
        Long = points[0][1]
    marathon_location = marathon_location.append({'Lat' : Lat, 'Long' : Long}, ignore_index=True)
 print(len(marathon_location))
 marathon_location

 marathon_location.groupby(['Lat', 'Long']).size()

Lat              Long

42.274032    -71.423979    49

42.282364    -71.364801    4435

42.297870    -71.284260    13866

42.324830    -71.259660    7261

42.345680    -71.215169    737

42.351510    -71.086980    6

42.352089    -71.124947    56

dtype: int64

 marathon_count = marathon_location.groupby(['Lat', 'Long']).size().reset_index(name='Count')
 marathon_count

-> 2시간 정도 지났을 때, 참가자들은 7개 정도 지역에 분포되어 있다

Bubble chart(지도) 그리기 : scatter chart의 응용버전

 import matplotlib.pyplot as plt

 # figure size 지정
 plt.figure(figsize=(20, 10))

 # scatter chart 적용, s : 분포 동그라미
 plt.scatter(marathon_count.Lat, marathon_count.Long, s=marathon_count.Count, alpha=0.5)

 # 타이틀, 라벨 달기

 plt.title('Runners location at 2nd hours')
 plt.xlabel('Latitude')
 plt.ylabel('Longitude')

 # 위치 별 Count값 넣기
 for i, txt in enumerate(marathon_count.Count):
    plt.annotate(txt, (marathon_count.Lat[i], marathon_count.Long[i]), fontsize=20)

 plt.show()

7. Heat map

여러 변수 간의 상관관계를 색으로 보여주거나, 값의 높고 낮음을 색으로 진하기로 보여줌

 marathon_2015_2017 = pd.read_csv('./marathon_2015_2017.csv')

 import pandas as pd
 import matplotlib.pyplot as plt
 import seaborn as sns
 sns.set()
 
 marathon_2015_2017_under60 = marathon_2015_2017[marathon_2015_2017.Age.isin(range(0, 60))]

 

 marathon_2015_2017_under60.groupby('Age')['M/F'].value_counts()

Age     M/F

18       M    32

           F     30

19        F     70

           M    67

20        F      139

...

57        F      387

58        M     741 

            F      303

59        M      564

            F      224

Name: M/F, Length: 84, dtype: int64

 marathon = marathon_2015_2017_under60.groupby('Age')['M/F'].value_counts().unstack().fillna(0)
 marathon

 f, ax = plt.subplots(figsize=(10,20))
 sns.heatmap(marathon, annot=True, fmt='d', linewidths=1, ax=ax)  # cmap='Accent'
 plt.show()

8. Histogram

 import pandas as pd
 import matplotlib.pyplot as plt
 import seaborn as sns
 
 marathon_2015_2017 = pd.read_csv('./marathon_2015_2017.csv')
 
 print(marathon_2015_2017.shape)
 marathon_2015_2017.head(3)

(1) 나이별 참가자 비율 분포 구하기 : 씨본의 distplot

 # figure size 지정
 plt.figure(figsize = (20, 10))

 # displot 함수로 분포 그리기
 age_count = sns.distplot(marathon_2015_2017.Age)

 # 제목, x라벨 ,y라벨 지정
 age_count.set_title('Distribution Rate by Ages', fontsize=18)
 age_count.set_xlabel('Ages', fontdict={'size':16})
 age_count.set_xlabel('Distibution Rate', fontdict={'size':16})

 plt.show()

(2) 나이별 참가자 실제 수 그리기 : 씨본의 countplot

 # figure size 지정
 plt.figure(figsize = (20, 10))

 # displot 함수로 분포 그리기
 age_count = sns.countplot(marathon_2015_2017.Age)

 # 제목, x라벨 ,y라벨 지정
 age_count.set_title('Distribution by Ages', fontsize=18)
 age_count.set_xlabel('Ages', fontdict={'size':16})
 age_count.set_xlabel('Distibution Rate', fontdict={'size':16})

 plt.show()

(3) 카운트가 높은 연령 기준으로 실제 수 그리기 : 씨본의 countplot 응용

 # figure size 지정
 plt.figure(figsize = (20, 10))

 # displot 함수로 분포 그리기
 # 카운트가 높은 연령 기준으로 : value_counts와 index 메소드를 이용해서
 age_count = sns.countplot('Age', data=marathon_2015_2017, order=marathon_2015_2017['Age'].value_counts().index) # order : 정렬, value_counts().index는 연령별 인원

 # 제목, x라벨 ,y라벨 지정
 age_count.set_title('Distribution by Ages sorted', fontsize=18)
 age_count.set_xlabel('Ages', fontdict={'size':16})
 age_count.set_xlabel('Distibution Rate', fontdict={'size':16})

 plt.show()

9. Box plot

 # 필요한 라이브러리 임포트
 import pandas as pd # 데이터 분석 라이브러리
 import numpy as np  # 숫자, 행렬

 import matplotlib.pyplot as plt  # 시각화
 import seaborn as sns            # 시간화

 from tqdm import tqdm_notebook   # for진행상황
 marathon_2015_2017 = pd.read_csv('./marathon_2015_2017.csv')

 print(marathon_2015_2017.shape)
 marathon_2015_2017.head(3)

미국인 참가자만 가져오기

 USA_runner = marathon_2015_2017[marathon_2015_2017.Country =='USA']
 
 print(USA_runner.shape)
 USA_runner.head(3)

 # 남녀 구분해서 데이터 저장
 USA_MALE_runner = USA_runner[USA_runner['M/F'] == 'M']
 USA_FEMALE_runner = USA_runner[USA_runner['M/F'] == 'F']

 USA_MALE_runner.head(3)

 # figure size 정하기
 plt.figure(figsize=(10, 5))

 # 씨본의 스타일 지정
 sns.set(style='ticks', palette = 'pastel') # style = "ticks", "whitegrid"   / palette = "pastel", "Set3"

 # 박스플롯 그리기
 sns.boxplot(x='M/F', y="Pace", palette=['b', 'r'], data=USA_runner)

실제 통계치 확인

 USA_MALE_runner_stat = USA_MALE_runner['Pace'].describe()
 USA_MALE_runner_stat

count   33390.00000

mean      514.22944

std           97.99571

min        298.00000

25%        442.00000

50%        495.00000

75%        566.00000

max       1157.00000

Name: Pace, dtype: float64

 USA_FEMALE_runner_stat = USA_FEMALE_runner['Pace'].describe()
 USA_FEMALE_runner_stat

count    31084.000000

mean        561.858448

std             88.425649

min          328.000000

25%          499.000000

50%          541.000000

75%          607.000000

max         1470.000000

Name: Pace, dtype: float64

10. Geo chart with Folium

Folium 은 'Open Street Map'과 같은 지도데이터에 'Leaflet.js'를 이용하여 위치정보를 시각화 하기 위한 라이브러리

 import pandas as pd

 marathon_2017 = pd.read_csv('marathon_results_2017.csv')
 
 marathon_2017.loc[:, '10K':'Pace']

 print(marathon_results_2017.shape)
 marathon_2017.head(5)

 # for문 사용 안하는 방식
 marathon_2017['5K'] = pd.to_timedelta(marathon_2017['5K']).astype('m8[s]').astype(np.int64)
 marathon_2017['15K'] = pd.to_timedelta(marathon_2017['15K']).astype('m8[s]').astype(np.int64)
 marathon_2017['20K'] = pd.to_timedelta(marathon_2017['20K']).astype('m8[s]').astype(np.int64)
 marathon_2017['25K'] = pd.to_timedelta(marathon_2017['25K']).astype('m8[s]').astype(np.int64)
 marathon_2017['Half'] = pd.to_timedelta(marathon_2017['Half']).astype('m8[s]').astype(np.int64)
 marathon_2017['30K'] = pd.to_timedelta(marathon_2017['30K']).astype('m8[s]').astype(np.int64)
 marathon_2017['35K'] = pd.to_timedelta(marathon_2017['35K']).astype('m8[s]').astype(np.int64)
 marathon_2017['40K'] = pd.to_timedelta(marathon_2017['40K']).astype('m8[s]').astype(np.int64)
 marathon_2017['Pace'] = pd.to_timedelta(marathon_2017['Pace']).astype('m8[s]').astype(np.int64)
 marathon_2017['Official Time'] = pd.to_timedelta(marathon_2017['Official Time']).astype('m8[s]').astype(np.int64)
 
 marathon_2017.loc[:, '10K':'Pace']

 import numpy as np 

 # pd.to_timedelt() 적용하기
 # .astype('m8[s]').astype(np.int64) 적용하기 : 초 단위로 바꾼 후, int 형태로 변환

 points = ['5K', '10K', '15K', '20K', 'Half', '25K', '30K', '35K', '40K', 'Pace', 'Official Time']
 for point in points:
    marathon_2017[point] = pd.to_timedelta(marathon_2017[point]).astype('m8[s]').astype(np.int64)

 # 시간 데이터가 int 형태로 바뀌었는지 확인
 marathon_2017.loc[:, '10K':'Pace'].head(10)

 # 참가자별 위치 파악하기
 check_time = 7200    # 2시간
 Lat = 0
 Long = 0
 Location = ''

 # 5K, 10K, 15K, 20K, 25K, 30K, 35K, 40K
 points = [[42.247835,-71.474357], [42.274032,-71.423979], [42.282364,-71.364801], [42.297870,-71.284260],
          [42.324830,-71.259660], [42.345680,-71.215169], [42.352089,-71.124947], [42.351510,-71.086980]]
 %%time
 # 26000개 행을 돌면서 위치가 어디인지 판단한다.
 # iterrows() : 각각의 행을 돌아라는 뜻
 marathon_location = pd.DataFrame(columns=['Lat','Long'])

 for index, record in marathon_2017.iterrows():
    if (record['40K'] < check_time):
        Lat = points[7][0]
        Long = points[7][1]
    elif (record['35K'] < check_time):
        Lat = points[6][0]
        Long = points[6][1]
    elif (record['30K'] < check_time):
        Lat = points[5][0]
        Long = points[5][1]
    elif (record['25K'] < check_time):
        Lat = points[4][0]
        Long = points[4][1]
    elif (record['20K'] < check_time):
        Lat = points[3][0]
        Long = points[3][1]
    elif (record['15K'] < check_time):
        Lat = points[2][0]
        Long = points[2][1]
    elif (record['10K'] < check_time):
        Lat = points[1][0]
        Long = points[1][1]
    elif (record['5K'] < check_time):
        Lat = points[0][0]
        Long = points[0][1]
    else:    
        Lat = points[0][0]
        Long = points[0][1]
    marathon_location = marathon_location.append({'Lat' : Lat, 'Long' : Long}, ignore_index=True)

Wall time: 35.9 s

 print(marathon_location.shape)
 marathon_location.head(10) 

 marathon_count = marathon_location.groupby(['Lat', 'Long']).size().reset_index(name='Count')
 marathon_count

 import matplotlib.pyplot as plt

 # figure size 지정
 plt.figure(figsize=(20, 10))

 # scatter chart 적용
 plt.scatter(marathon_count.Lat, marathon_count.Long, s=marathon_count.Count, alpha=0.5)

 # 타이틀, 라벨 달기
 plt.title('Runners location at 2nd hours')
 plt.xlabel('Latitude')
 plt.ylabel('Longitude')

 # 위치 별 Count값 넣기
 for i, txt in enumerate(marathon_count.Count):
    plt.annotate(txt, (marathon_count.Lat[i], marathon_count.Long[i]), fontsize=18)

 plt.show()

Folium을 이용해서 지도 위에 그리기

!pip install folium 
# 다운로드
 import folium
 from folium.plugins import HeatMap

 # Folium marathon map 그리기
 marathon_map = folium.Map(location=[42.324830, -71.259660],
                         tiles='cartodbdark_matter',  
                         zoom_start=11)
 # 지도 타일 형태  # tiles='Stamen Toner', 'Stamen Terrain', 'OpenStreetMap'
 HeatMap(marathon_count, radius=20).add_to(marathon_map)

<folium.plugins.heat_map.HeatMap at 0x12dd880bd30>

 marathon_map

 folium - tiles에 적용할 수 있는 곳
 https://python-graph-gallery.com/288-map-background-with-folium/

반응형

'파이썬 응용' 카테고리의 다른 글

파이썬 마라톤 데이터 활용(marathon)  (0) 2021.04.30