본문 바로가기

Data_Analysis_Track_33/Python

Python_matplotlib_02(각종 그래프 그리기)

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

  • 1.1 선 그래프(꺽은선 그래프)
  • 점과 점을 선으로 연결한 그래프
  • 시간의 흐름에 따른 변화를 표현할 때 많이 사용한다. (시계열)
  • plot([x], y)
        - 1번인수 : x값(생략가능), 2번인수 y값
        - 인수가 하나인 경우 y 축의 값으로 설정되고 X값은 (0 ~ len(y)-1) 범위로 지정된다.
        - x와 y의 원소개수는 같아야 한다.
  • 하나의 axes(subplot)에 여러 개의 선 그리기
        - 같은 axes에 plot()를 여러번 실행한다.

 

linspace(시작, 끝, 개수) : 시작부터 끝값까지 간격이 동일한 개수를 나누어 제공한다.

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(1, 10, 100) # linspace(시작, 끝, 개수) 시작부터 끝값까지 간격이 동일한 개수를 나누어 제공한다.
x

 

 

 

- 직선 그래프 그리기 (선 스타일 적용)

# 선그래프 = plot(x, y)
plt.plot(x, x, label = '-')
plt.plot(x, x-1, linestyle=':', label=':') # x-1 : 원소단위 계산(모든 원소들의 값 -1)
plt.plot(x, x-2, linestyle='-.', label='-.')
plt.plot(x, x-3, linestyle='--', label='--')

plt.legend()
plt.show()

 

marker = '.' : 그래프의 기준점이 되는 값(실제 값)들을 점(dot)으로 표현한다

x = np.linspace(1, 10, 10)

plt.plot(x, x, marker='.') # marker : 실제 값의 위치를 점(dot)으로 표현
plt.show

 

 

 

import pandas as pd

df = pd.read_csv('data/서울시 연도별 황사 경보발령 현황.csv')
df.shape

 

마지막 열의 최대농도(㎍/㎥/시)를 최대농도로 변경 (원본 자체 변경 -> inplace = True)

df.rename(columns = {df.columns[-1] : "최대농도"}, inplace = True)
df

 

년도(x축)와 최대농도(y축)을 이용한 년도별 황사 최대농도의 변화흐름 그래프 그리기

- 겹치는 부분이 있을 때 양쪽의 그래프를 다 보고 싶다면 alpha(투명도)를 조절

# 년도에 따른 주의보/경보 발령횟수의 변화흐름을 비교
plt.figure(figsize = (10, 4))

# 겹치는 부분을 다 보고싶은 경우 alpha를 조절. (모든 plot의 공통 파라미터)
plt.plot(df['년도'],
         df['주의보 발령횟수'],
         label = '주의보',
         alpha = 0.5
        )

plt.plot(df['년도'],
         df['경보 발령횟수'],
         label = '경보',
         alpha = 0.5
        )

plt.title('발령횟수의 변화흐름', fontsize = 30)
plt.xticks(ticks = df['년도'], 
           fontsize = 10, # tick의 fontsize 조절
           rotation = 45  # 글자 각도 조절
          ) 

plt.legend()
plt.show()

 

 

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

  • 하나의 축을 공유하고 두개의 축을 가지는 그래프 그리기
  • 값의 범위(Scale)이 다른 두 값과 관련된 그래프를 한 Axes(subplot)에 그리는 경우
  • X축을 공유해 2개의 Y축을 가지는 그래프
  • axes.twinx() 를 이용해 axes를 복사
  • Y축을 공유해 2개의 X축을 가지는 그래프
  • axes.twiny() 를 이용해 axes를 복사

 

아래 코드로 실행하면 관측일수에 대한 그래프가 일자로 나온것을 확인할 수 있다. 이러한 이유는 관측일수에 대한 y값과 최대농도에 대한 y값의 차이가 너무 크기 때문이다.

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

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

plt.title('관측일수, 최대농도의 년도별 변화흐름')
plt.legend()
plt.show()

 

아래처럼 y축을 두개로 분리한다면 해결할 수 있다.

twinx() -> 두 개의 그래프가 x축을 공

plt.figure(figsize = (7, 4))
ax1 = plt.gca()
ax2 = ax1.twinx() # ax1과 x축을 공유하면서 오른쪽 spine이 y축이 axes를 생성

ax1.plot(df['년도']
        ,df['관측일수']
        ,color = 'red'
        ,label = '관측일수'
        )
ax2.plot(df['년도']
        ,df['최대농도']
        ,label = '최대농도'
        )
# x축의 label
ax1.set_xlabel('년도')
ax1.set_ylabel('일수')
ax2.set_ylabel('농도')

# 일수 ticks 조정
ax1.set_yticks(range(0,16,2))

# bbox : legend box
# anchor : 위치
# bbox_to_anchor = (x좌표, y좌표)
# 0 ~ 1 기준으로 위치를 지정. (x/y축의 시작 : 0, x/y축의 끝 : 1)
# loc : bbox의 어느 지점을 anchor 점에 맞출것인지 지정.
ax1.legend(bbox_to_anchor = (1.3, 0.8), loc = 'lower right', shadow = True) # 그래프 외부애 legend 위치 설정
ax2.legend(bbox_to_anchor = (1.3, 0.7), loc = 'lower right', shadow = True) # shadow - True -> legend 장식

plt.show()

 

legend box 설정

# legend box 설정
plt.plot([1, 2, 3], np.array([10, 20, 30]), label = 'line plot1')
plt.plot([1, 2, 3], np.array([10, 20, 30])+1, label = 'line plot1')
plt.plot([1, 2, 3], np.array([10, 20, 30])+2, label = 'line plot1')
plt.plot([1, 2, 3], np.array([10, 20, 30])+3, label = 'line plot1')
plt.plot([1, 2, 3], np.array([10, 20, 30])+4, label = 'line plot1')
plt.plot([1, 2, 3], np.array([10, 20, 30])+5, label = 'line plot1')
plt.plot([1, 2, 3], np.array([10, 20, 30])+6, label = 'line plot1')

plt.legend(fontsize=10
           ,ncol = 2 # 지정한 열수에 나눠서 출력
           ,bbox_to_anchor = (1, 1)
           ,loc = 'upper left'
           ,shadow = True
          )
plt.show()

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

  • 2.1 산점도(산포도)
  • X와 Y축을 가지는 좌표평면상 관측값들을 점을 찍어 표시하는 그래프
  • 변수(Feature)간의 상관성이나 관측값들 간의 군집 분류를 확인할 수 있다.
  • scatter() 메소드 사용
        - 1번인수 : x축 값, 2번인수 y축 값
        - x와 y값들을 모두 매개변수로 전달해야 한다.
            - x와 y의 원소의 수는 같아야 한다.
        - c/color: 색지정
            - c와 x, y와 같은 원소수를 가지는 Iterable 타입 객체로 설정할 경우 각 마커마다 다른 색상을 설정할 수 있다
        - s: 점 크기 지정

 

import numpy as np
import matplotlib.pyplot as plt

 

x = range(1, 1001, 50)
y = range(1, 1001, 50)
y2 = range(1000, 0, -50)

 

plt.scatter(x, y)
plt.scatter(x, y2)
plt.show()

 

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

 

np.random.randint(1, 5, 30)  # 랜덤값: 1 ~ 5 사이 정수 30개

 

marker

plt.figure(figsize = (8, 8))
plt.scatter(x = np.random.randint(1, 5, 30)
           ,y = np.random.randint(1, 5, 30)
           ,marker = 'v'
           )

plt.scatter(x = np.random.randint(5, 10, 30)
           ,y = np.random.randint(5, 10, 30)
           ,marker = '4'
           ,s = 200
           )

plt.show()

 

  • 2.3 산점도 활용

 

파일 불러오기

df = pd.read_csv('data/diamonds.csv')
df.shape

 

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

plt.figure(figsize = (10, 7))
plt.scatter(df['carat']
            ,df['price']  # x, y 연속형 값 -> 상관관계(비례, 반비례)를 시각적으로 확인
            ,alpha = 0.1 # 값들의 빈도수를 대충 확인할 수 있다.
           )
plt.xlabel('carat')
plt.ylabel('price($)')
plt.show()

 

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

 

# 상관계수 계산
# numpy의 함수
import numpy as np
r = np.corrcoef(df['price'], df['carat'])
r

pd.DataFrame(r, index=['price', 'carat'], columns = ['price', 'carat'])

# pandas - dataframe
df[['carat', 'price']].corr()

 

plt.scatter(df['carat'], df['depth'])
plt.show()

 

plt.scatter(df['carat'], df['x'])
plt.show()

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

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

 

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

fruit = ['사과', '귤', '배', '복숭아']
amount = [150, 70, 65, 130]
# 막대그래프 데이터 - 분류값들, 개수들

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

plt.subplot(1, 2, 1)
plt.bar(fruit, amount) # (x = fruit, width = amount)
plt.title('수직막대그래프-bar()')
plt.xlabel('과일')
plt.ylabel('개수')
# 개수를 막대 위에 text로 표시.
for x, y in enumerate(amount): # (0, 150), (1, 70), ...
    plt.text(x-0.1, y+1, str(y))

# y축의 범위를 변경
plt.ylim(0, 170)
# x축의 범위를 변경
# plt.xlim(0, 7)


plt.subplot(1, 2, 2)
plt.barh(fruit, amount) # (y = fruit, width = amount)
plt.title('수평막대그래프')
plt.xlabel('개수')
plt.ylabel('과일')

plt.tight_layout()
plt.show()

 

# axes에 글씨 쓰기
plt.text(0.5 # 글씨를 쓸 x좌표
         ,0.2 # y좌표
         ,'안녕하세요' # 문자열
         ,fontsize = 30
        )
plt.grid(True)
plt.show()

 

# 급격한 값의 변화때문에 작은 변화가 안보일 경우 범위를 줄여준다.(lim)
a = [1, 0.1, 0.08, 0.07, 0.09, 0.1, 0.08, 0.11]
plt.plot(range(8), a)
plt.ylim(0, 0.1)
plt.show()

 

# 범주형 컬럼의 빈도수글 시각화.
v = df['color'].value_counts()
v

 

plt.bar(v.index, v, width = 0.5) # 막대의 굵기 설정
plt.show()

 

v.plot(kind='bar', rot = 0);

 

  • 3.2 막대그래프 활용
  • 강수량추이

강수량 excel 파일 사용

import pandas as pd
df = pd.read_excel('data/강수량.xlsx')
df.set_index('계절', inplace = True)

df

 

# 2009년 계절별 강수량 크기 비교
plt.bar(df.index   # 양적 비교
         ,df[2009]
       )
plt.plot(df.index  # 변화 흐름
         ,df[2009]
         ,color = 'red'
         ,marker = '.'
        )

for x, y in enumerate(df[2009]):
    plt.text(x-0.15, y+5, str(y))

plt.ylim(0, 800)
    
plt.show()