PYTHON DATA 시각화 – MATPLOTLIB #2

Data 시각화 #2 (matplotlib)

matplotblib 에는 상상 가능한 거의 모든 종류의 도면을 그릴 수 있는 수십개의 도식화 메서드가 있다. 선, 막대, 히스토그램, 산포도, 상자, 바이올린, 등고선, 파이, 기타 많은 종류의 도면이 Axes 객체의 메서드로 제공된다.

1. alta 스키 리조트의 적설량의 데이터를 시각화

데이터 설명 : alta 스키 리조트의 데이터 정보|

In [1]:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
In [2]:
alta = pd.read_csv('data/alta-noaa-1980-2019.csv')
In [3]:
alta.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 14160 entries, 0 to 14159
Data columns (total 22 columns):
 #   Column     Non-Null Count  Dtype  
---  ------     --------------  -----  
 0   STATION    14160 non-null  object 
 1   NAME       14160 non-null  object 
 2   LATITUDE   14160 non-null  float64
 3   LONGITUDE  14160 non-null  float64
 4   ELEVATION  14160 non-null  float64
 5   DATE       14160 non-null  object 
 6   DAPR       25 non-null     float64
 7   DASF       5 non-null      float64
 8   MDPR       68 non-null     float64
 9   MDSF       27 non-null     float64
 10  PRCP       13830 non-null  float64
 11  SNOW       13795 non-null  float64
 12  SNWD       12912 non-null  float64
 13  TMAX       13914 non-null  float64
 14  TMIN       13857 non-null  float64
 15  TOBS       13641 non-null  float64
 16  WT01       85 non-null     float64
 17  WT03       226 non-null    float64
 18  WT04       20 non-null     float64
 19  WT05       49 non-null     float64
 20  WT06       3 non-null      float64
 21  WT11       21 non-null     float64
dtypes: float64(19), object(3)
memory usage: 2.4+ MB

alta 스키장의 SNWD 의 컬럼의 데이터를 이용하여 적설량 데이터를 그린다. alta DATE 컬럼을 datetime 형태로 변환해주고 index 로 만든다. DATE 2018-09 : 2019-08 에서의 적설량을 확인한다.

In [4]:
data = (alta
    .assign(DATE=pd.to_datetime(alta.DATE))
    .set_index('DATE')
    .loc['2018-09':'2019-08']
    .SNWD
)
data
Out[4]:
DATE
2018-09-01    0.0
2018-09-02    0.0
2018-09-03    0.0
2018-09-04    0.0
2018-09-05    0.0
             ... 
2019-08-27    0.0
2019-08-28    0.0
2019-08-29    0.0
2019-08-30    0.0
2019-08-31    0.0
Name: SNWD, Length: 364, dtype: float64

2. data 를 이용하여 시각화

In [5]:
blue = '#99ddee'
white = '#ffffff'
fig, ax = plt.subplots(figsize=(12,4),linewidth=5, facecolor=blue)
ax.set_facecolor(blue)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.tick_params(axis='x', colors=white)
ax.tick_params(axis='y', colors=white)
ax.set_ylabel('Snow Depth(in)', color=white)
ax.set_title('2009-2010', color=white, fontweight='bold')
ax.fill_between(data.index, data, color=white)
fig.savefig('c13-alta1.png', dpi=300, facecolor=blue)

3. 단일 figure 여러개의 도면 시각화

interpolate 메서드를 이용하여 누락된 데이터 정리

In [6]:
import matplotlib.dates as mdt
blue = '#99ddee'
white = '#ffffff'

def plot_year(ax, data, years):
    ax.set_facecolor(blue)
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.spines['bottom'].set_visible(False)
    ax.spines['left'].set_visible(False)
    ax.tick_params(axis='x', colors=white)
    ax.tick_params(axis='y', colors=white)
    ax.set_ylabel('Snow Depth (in)', color=white)
    ax.set_title(years, color=white, fontweight='bold')
    ax.fill_between(data.index, data, color=white)

years = range(2009, 2019)
fig, axs = plt.subplots(ncols=2, nrows=int(len(years)/2), figsize=(16,10), linewidth=5, facecolor=blue)
axs = axs.flatten()
max_val = None
max_data = None
max_ax = None
for i, y in enumerate(years):
    ax = axs[i]
    data = (alta
            .assign(DATE=pd.to_datetime(alta.DATE))
            .set_index('DATE')
            .loc[f'{y}-09':f'{y+1}-08']
            .SNWD
            .interpolate()
    )

    if max_val is None or max_val < data.max():
        max_val = data.max()
        max_data = data
        max_ax = ax
    ax.set_ylim(0, 180)
    years = f'{y}-{y+1}'
    plot_year(ax,data,years)

max_ax.annotate(f'Max Snow {max_val}', xy=(mdt.date2num(max_data.idxmax()), max_val), color=white)

fig.suptitle('Alta Snowfalll', color=white, fontweight='bold')
fig.tight_layout(rect=[0,0.03,1,0.95])

fig.savefig('c13-alta2.png', dpi=300, facecolor=blue)

4. 데이터 확인(그래프가 제대로 그려지지 않고 빈공간이 생기는 문제점)

겨울시즌중에 적설량이 너무 많이 떨어지는 지점이 있는 경우가 있다. 연속된 데이터를 비교하여 50 이상 차이가 나는 지점을 찾아보자

In [7]:
(alta
    .assign(DATE=pd.to_datetime(alta.DATE))
    .set_index('DATE')
    .SNWD
    .to_frame()
    .assign(next=lambda df_:df_.SNWD.shift(-1),
            snwd_diff=lambda df_:df_.next-df_.SNWD)
    .pipe(lambda df_:df_[df_.snwd_diff.abs() > 50])
    )
Out[7]:
SNWD next snwd_diff
DATE
1989-11-27 60.0 0.0 -60.0
2007-02-28 87.0 9.0 -78.0
2008-05-22 62.0 0.0 -62.0
2008-05-23 0.0 66.0 66.0
2009-01-16 76.0 0.0 -76.0
2009-01-17 0.0 70.0 70.0
2009-05-14 52.0 0.0 -52.0
2009-05-15 0.0 51.0 51.0
2009-05-17 55.0 0.0 -55.0
2010-02-15 75.0 0.0 -75.0
2010-02-16 0.0 73.0 73.0
2011-01-03 88.0 0.0 -88.0
2011-01-04 0.0 87.0 87.0
2011-05-02 155.0 0.0 -155.0
2011-05-03 0.0 146.0 146.0
2011-05-17 134.0 0.0 -134.0
2011-05-18 0.0 136.0 136.0
2012-02-09 58.0 0.0 -58.0
2012-02-10 0.0 56.0 56.0
2013-03-01 75.0 0.0 -75.0
2013-03-02 0.0 78.0 78.0

5. 데이터 처리(0 이 되는 데이터 삭제)

시즌중에 np.nan 데이터가 아닌 데이터가 실제로 0이 되는 지점이 있다.

In [8]:
def fix_gaps(ser, threshold=50):
    mask = (ser
            .to_frame()
            .assign(next=lambda df_:df_.SNWD.shift(-1),
                    snwd_diff=lambda df_:df_.next - df_.SNWD)
            .pipe(lambda df_:df_.snwd_diff.abs() > threshold)
    )

    return ser.where(-mask, np.nan)

years = range(2009, 2019)
fig, axs = plt.subplots(ncols=2, nrows=int(len(years)/2), figsize=(16,10), linewidth=5, facecolor=blue)
axs = axs.flatten()
max_val = None
max_data = None
max_ax = None

for i,y in enumerate(years):
    ax = axs[i]
    data = (alta
            .assign(DATE=pd.to_datetime(alta.DATE))
            .set_index('DATE')
            .loc[f'{y}-09':f'{y+1}-08']
            .SNWD
            .pipe(fix_gaps)
            .interpolate()
    )

    if max_val is None or max_val < data.max():
        max_val = data.max()
        max_data = data
        max_ax = ax
    ax.set_ylim(0, 180)
    years = f'{y}-{y+1}'
    plot_year(ax,data,years)

max_ax.annotate(f'Max Snow {max_val}', xy=(mdt.date2num(max_data.idxmax()), max_val), color=white)

fig.suptitle('Alta Snowfalll', color=white, fontweight='bold')
fig.tight_layout(rect=[0,0.03,1,0.95])

fig.savefig('c13-alta2.png', dpi=300, facecolor=blue)

답글 남기기

이메일 주소는 공개되지 않습니다.