7 분 소요

1. 선 그래프 (Line plot) 그리기

1.1 선 그래프(꺽은선 그래프)

  • 점과 점을 선으로 연결한 그래프
  • 시간의 흐름에 따른 변화를 표현할 때 많이 사용한다. (시계열)
  • plot([x], y)
    • 1번인수 : x값(생략가능), 2번인수 y값
    • 인수가 하나인 경우 y 축의 값으로 설정되고 X값은 (0 ~ len(y)-1) 범위로 지정된다.
    • x,y 의 인수는 리스트 형태의 객체들을 넣는다.
      • 리스트
      • 튜플
      • numpy 배열 (ndarray)
      • 판다스 Series
    • x와 y의 size는 같아야 한다.
  • 하나의 axes(subplot)에 여러 개의 선 그리기
    • 같은 axes에 plot()를 여러번 실행한다.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

1.2 선 스타일

  • https://matplotlib.org/3.0.3/gallery/lines_bars_and_markers/line_styles_reference.html
x = np.linspace(1, 10, num=100) # 1 ~ 10을 100등분(num) 한 분위값으로 이뤄진 1차원 배열을 생성.
x2 = pd.Series(x)
# plt 함수를 이용해서 선 그래프 그리기.
plt.plot(x, x, marker = ".", c = "purple")
plt.plot(x,x+1, linestyle = "--")
plt.plot(x,x+2, linestyle = ':')
plt.plot(x,x+3, linestyle = "-.", linewidth = 5) # linewidth 는 라인강고 가능.
plt.show()

v2-1.png

1.3 선 그래프 활용

df = pd.read_csv('data/서울시 연도별 황사 경보발령 현황.csv')
df.shape
(12, 7)
df.info
<bound method DataFrame.info of       년도  주의보 발령횟수  주의보 발령일수  경보 발령횟수  경보 발령일수  관측일수  최대농도
0   2006         4         5        1        2    11  2941
1   2007         3         4        1        1    12  1355
2   2008         1         1        1        1    11   933
3   2009         2         3        2        3     9  1157
4   2010         4         5        2        3    15  1354
5   2011         4         7        0        0     9   662
6   2012         0         0        0        0     1   338
7   2013         0         0        0        0     3   226
8   2014         0         0        0        0    10   259
9   2015         1         2        1        2    15   902
10  2016         0         0        0        0     7   481
11  2017         0         0        0        0    10   423>
  • ‘최대농도(㎍/㎥/시)’ => 최대농도
df.rename(columns = {'최대농도(㎍/㎥/시)':'최대농도'})
df.rename(columns = {df.columns[-1]:'최대농도'},inplace = True)
  • 년도에 따른 황사 최대 농도의 변화흐름
plt.figure(figsize = (10, 3))
plt.plot(df['년도'], df['최대농도'], marker = ".")


plt.title('서울시 년도별 황사 최대농도의 변화흐름')
plt.xlabel('년도', fontsize = 15)
plt.ylabel('최대농도', fontsize = 15)

plt.xticks(df["년도"],
           labels=[str(y)+'년' for y in df['년도']], # tick 라벨의 size == ticks 의 size
           rotation = 45
          ) # 눈근의 위치. labels = ticks 라벨에 사용할 문자열 리스트



plt.grid(True, linestyle=":")
plt.show()

v2-2.png

  • 년도에 따른 주의보/경보 발령횟수의 변화 ==> 하나의 subplot 에 같이 그리기.
plt.figure(figsize = (10,3))
plt.plot(df['년도'], df['주의보 발령횟수'], alpha = 0.7, label = '주의보 발령횟수') # alpha 는 투명도 : 0(투명) ~ 1(불투명)
plt.plot(df['년도'], df['경보 발령횟수'], alpha = 0.5, label = '경보 발령횟수')

plt.title('년도별 주의보/경보 발령횟수')
plt.xlabel('년도')
plt.ylabel('횟수')

plt.legend()
plt.grid(True, linestyle = '--')
plt.show()

v2-3.png

최대 농도와 관측일 수의 연도별 변화를 시각화

  • 하나의 축을 공유하고 두개의 축을 가지는 그래프 그리기

  • 값의 범위(Scale)이 다른 두 값과 관련된 그래프를 한 Axes(subplot)에 그리는 경우
  • X축을 공유해 2개의 Y축을 가지는 그래프
    • axes.twinx() 를 이용해 axes를 복사
  • Y축을 공유해 2개의 X축을 가지는 그래프
    • axes.twiny() 를 이용해 axes를 복사
  • 년도별 관측일수와 최대농도의 변화르흠을 하나의 axes에 그리기.
plt.figure(figsize = (10,5))

plt.plot(df['년도'],df['관측일수'], label = '관측일수', marker = '.')
plt.plot(df['년도'],df['최대농도'], label = '최대농도', marker = ".")



plt.title('년도별 관측일수와 최대농도의 변화흐름')
plt.xlabel('년도')
plt.ylabel('최대농도 / 관측일수')

plt.legend()
plt.grid(True, linestyle = ':')
plt.show()

v2-4.png

df[['관측일수','최대농도']].agg(['min','max'])
관측일수 최대농도
min 1 226
max 15 2941
  • twinx()를 이용해서 x축은 같이 사용하고 ysms 따로 사용하도록 처리.
plt.figure(figsize = (15,5))

ax1 = plt.gca() # 관측일수
ax2 = ax1.twinx() # ax1과 x축을 공유하는 새로운 subplot을 생성.

ax1.plot(df['년도'], df['관측일수'], label = '관측일수', color = 'red', marker = ".")
ax2.plot(df['년도'], df['최대농도'], label = '최대농도', c = 'g', marker = '.')

ax1.set_title('년도에 따른 관측일수, 최대농도의 변화')
ax1.set_xlabel('년도')
ax1.set_ylabel('관측일수')

ax2.set_ylabel("최대농도")

ax1.legend(loc = 'upper left', bbox_to_anchor = (1.05, 1))
ax2.legend(loc = 'upper left', bbox_to_anchor = (1.05, 0.93))
plt.grid(True, linestyle = "--")
plt.show()

v2-5.png

legend 위치 지정

  • 미리 지정된 위치로 잡기.
    • legend(loc=”상하위치 좌우위치”)
      • 상하: upper, center, lower, 좌우: left, center, right
      • 정가운데 : ‘center’, ‘best’ : 최적의 위치를 알아서 잡아준다.(default)
  • 원하는 위치를 직접 설정.
    • legend(bbox_to_anchor=(x,y), loc = ‘box의 상하, 좌우 위치’)
    • bbox_to_anchor
      • 전체 subplot의 x축과 y축의 비율
          하단: (0,0), (1,0)
          상단: (0,1), (1,1)
        
    • loc -> bbox_to_anchor 좌표지점에 범례 box의 어느 지점을 붙일 것인지 지정.
      • ex) bbox_to_anchor = (1,1), loc = ‘upper left’ : subplot의 (1,1)지점의 범례박스의 위/왼쪽 점을 맞춘다.
      • 0 ~ 1 사이는 박스 안쪽, 1 이상이면 박스 바깥쪽.
x = [1, 2 ,3]
y = np.array([10,20,30])

plt.plot(x, y, label = 'plot1') 
plt.plot(x, y+1, label = 'plot2') 
plt.plot(x, y+2, label = 'plot3') 
plt.plot(x, y+3, label = 'plot4') 
plt.plot(x, y+4, label = 'plot5') 
plt.plot(x, y+5, label = 'plot6') 
plt.plot(x, y+6, label = 'plot7') 
plt.plot(x, y+7, label = 'plot8') 
plt.plot(x, y+8, label = 'plot9') 
plt.plot(x, y+9, label = 'plot10') 

plt.legend(bbox_to_anchor = (1,1), loc = 'upper left', 
          ncol = 2, shadow = True # ncol은 줄 나누기, shadow는 그림자 주기 
          )
plt.show()

v2-6.png

2. 산점도 (Scatter Plot) 그리기

2.1 산점도(산포도)

  • X와 Y축을 가지는 좌표평면상 관측값들을 점을 찍어 표시하는 그래프
  • 변수(Feature)간의 상관성이나 관측값들 간의 군집 분류를 확인할 수 있다.
  • scatter() 메소드 사용
    • 1번인수 : x값, 2번인수 y값
    • x와 y값들을 모두 매개변수로 전달해야 한다.
    • x,y 의 인수는 스칼라 실수나 리스트 형태의 객체들을 넣는다.
      • 리스트
      • 튜플
      • numpy 배열 (ndarray)
      • 판다스 Series
    • x와 y의 원소의 수는 같아야 한다.
x = range(1, 1001, 50)
y = range(1001, 1, -50)
y2 = range(1, 1001, 50)

print(len(x), len(y))
20 20
plt.scatter(x, y, label = 'A', marker = '<') # 비례적인 관계
plt.scatter(x, y2, label = 'B', marker = '*', s = 100) # 반비례적인 관계

# plt.legend(['A라벨', 'B라벨']) 이런식으로 A와 B의 라벨 표시를 동시에 할 수 있다.
plt.legend(bbox_to_anchor = (1,1))
plt.grid(True, linestyle = ':')
plt.show()

v2-7.png

2.2 설정

  • marker (마커)
    • marker란 점의 모양을 말하며 미리정의된 값으로 변경할 수있다.
    • scatter() 메소드의 marker 매개변수를 이용해 변경한다.
    • https://matplotlib.org/stable/api/markers_api.html
  • s
    • 정수: 마커의 크기
  • alpha
    • 하나의 마커에 대한 투명도
    • 0 ~ 1 사이 실수를 지정 (default 1)

2.3 산점도 활용

df = pd.read_csv('data/diamonds.csv')
df.shape
(53940, 10)
df.info
<bound method DataFrame.info of        carat        cut color clarity  depth  table  price     x     y     z
0       0.23      Ideal     E     SI2   61.5   55.0    326  3.95  3.98  2.43
1       0.21    Premium     E     SI1   59.8   61.0    326  3.89  3.84  2.31
2       0.23       Good     E     VS1   56.9   65.0    327  4.05  4.07  2.31
3       0.29    Premium     I     VS2   62.4   58.0    334  4.20  4.23  2.63
4       0.31       Good     J     SI2   63.3   58.0    335  4.34  4.35  2.75
...      ...        ...   ...     ...    ...    ...    ...   ...   ...   ...
53935   0.72      Ideal     D     SI1   60.8   57.0   2757  5.75  5.76  3.50
53936   0.72       Good     D     SI1   63.1   55.0   2757  5.69  5.75  3.61
53937   0.70  Very Good     D     SI1   62.8   60.0   2757  5.66  5.68  3.56
53938   0.86    Premium     H     SI2   61.0   58.0   2757  6.15  6.12  3.74
53939   0.75      Ideal     D     SI2   62.2   55.0   2757  5.83  5.87  3.64

[53940 rows x 10 columns]>
plt.figure(figsize = (10,7))
plt.scatter(df["carat"], df['price'],
           alpha = 0.1
           ) # 보통 x: 원인, y: 결과를 넣는다.

plt.title("캐럿과 가격간의 상관관계")
plt.xlabel('캐럿')
plt.ylabel('가격')

# plt.grid(True, linestyle = ":")
plt.show()

v2-8.png

캐럿(carat)과 가격(Price)간의 상관관계 시각화

  • 상관계수 계산
df[['carat', 'price']].corr()
carat price
carat 1.000000 0.921591
price 0.921591 1.000000
x 가 증가하면 y도 증가 - 비례적관계 (0 ~ 1)
x 가 증가하면 y는 감소 - 반비례적 관계 (-1 ~ 0)

# 회귀선 
  • 상관계수
    • 두 변수간의 상관관계(비례/반비례)를 정량적(수치적)으로 계산한 값.
      • 양수: 양의 상관관계(비례관계), 음수: 음의 상관관계(반비례관계)
        • 양: 0 ~ 1, 음: -1 ~ 0
      • 절대값 기준 1로 갈수록 강한상관관계, 0으로 갈수록 약한 상관관계
        • 1 ~ 0.7: 아주 강한 상관관계
        • 0.7 ~ 0.3 : 강한 상관관계
        • 0.3 ~ 0.1 : 약한 상관관계
        • 0.1 ~ 0 : 관계없다.

3. 막대그래프 (Bar plot) 그리기

3.1 막대그래프(Bar plot)

  • 수량/값의 크기를 비교하기 위해 막대 형식으로 나타낸 그래프
  • 범주형 데이터의 class별 개수를 확인할 때 사용
  • bar(x, height) 메소드 사용
    • x : x값, height: 막대 높이
      • X는 분류값, height는 개수
  • barh(y, width) 메소드
    • 수평막대 그래프
    • 1번인수: y값, 2번인수: 막대 너비
  • 매개변수
    • 첫번째: 수량을 셀 대상
    • 두번째: 수량
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

fruits = ['사과', '배', '귤']
counts = [150, 70, 200]

plt.figure(figsize = (16,5))

plt.subplot(1, 2, 1)
plt.bar(fruits, counts, width = 0.5) # width : 막대의 0 ~ 1


# plt.text(x좌표, y좌표, '출력할 텍스트')
for x,y in enumerate(counts):
    plt.text(x - 0.05, y, str(y))

plt.title('과일 개수')
plt.xlabel('과일')
plt.ylabel('수량')
# y축의 값의 범위를 변경
plt.ylim(0, 250)

plt.grid(True)

plt.subplot(1, 2, 2)
plt.barh(fruits, counts, height = 0.4)
plt.title('과일 개수') # subplot(axes)의 title 을 설정,
plt.xlabel('수량')
plt.ylabel('과일')

plt.xlim(0, 250) # X축의 값의 범위를 지정

plt.grid(True)

plt.suptitle('막대그래프', fontsize = 20) # figure 의 title 을 설정.
plt.tight_layout()
plt.show()

v2-9.png

  • xticks(), yticks() : 축의 눈금을 재정의 할때 사용.
  • xlim(), ylim(): 축의 값의 범위를 재정의 할 때 사용.
x = [1, 2, 3, 4, 5, 6, 7]
y = [100.0, 50.0, 48.3, 45.2, 47.3, 43.2, 45.1]
plt.plot(x,y)
plt.ylim(40, 50) # 40 ~ 50 사이의 변화만 확인.

plt.show()

v2-10.png

3.2 막대그래프 활용

df = pd.read_excel('data/강수량.xlsx')
df.shape
(4, 10)
df.set_index('계절', inplace = True)
df
2009 2010 2011 2012 2013 2014 2015 2016 2017
계절
봄 231.3 302.9 256.9 256.5 264.3 215.9 223.2 312.8 118.6
여름 752.0 692.6 1053.6 770.6 567.5 599.8 387.1 446.2 609.7
가을 143.1 307.6 225.5 363.5 231.2 293.1 247.7 381.6 172.5
겨울 142.3 98.7 45.6 139.3 59.9 76.9 109.1 108.1 75.6
  • 2009년 계절별 강수량을 막대그래프로 비교
plt.bar(df.index, df[2009], width = 0.7)
plt.title('2009년 계절별 강수량')

for x,y in enumerate(df[2009]):
    plt.text(x - 0.16 , y + 5, str(y))
    
plt.ylim(0,800)
plt.ylabel('강수량')
plt.xlabel('계절')

# plt.grid(True, linestyle =":")
plt.show()

v2-11.png

  • 여름 년도별 강수량의 변화 => 주관심사 - 변화 흐름 –> line plot
plt.figure(figsize = (10,4))
plt.plot(df.columns, df.loc['여름'], marker = '.', c = 'r')
plt.bar(df.columns, df.loc['여름'])

for x,y in zip(df.columns, df.loc['여름']):
    plt.text(x - 0.25, y + 6, str(y))

plt.xlabel('년도')
plt.ylabel('강수량')
plt.ylim(0,1200)


# plt.grid(True, linestyle = ':')
plt.show()

v2-12.png

  • 2010, 2011 년도 계절별 강수량을 확인 => 누적 막대 그래프
df.index # x
df[2010], df[2011] #y
len(df.index)
4
width = 0.3
x = np.arange(4)
plt.bar(x - width/2, df[2010], width = width, label = '2010')
plt.bar(x + width/2, df[2011], width = width, label = '2011')



plt.xticks(x, labels = df.index) # X: 눈금의 위치값. label: 눈금의 라벨
plt.legend()
plt.show()

v2-13.png

df[[2010,2011]].plot(kind='bar')
<AxesSubplot: xlabel='계절'>

v2-14.png

댓글남기기