ข้อมูลอนุกรมเวลา มีอะไรบ้าง

พยากรณ์แบบอนุกรมเวลา (Time Series Method) เป็นวิธีการที่ใช้พยากรณ์ยอดขายในอนาคตโดยคาดว่าจะมีลักษณะเช่นเดียวกับยอดขายในปัจจุบันหรืออนาคต ยอดขายหรืออุปสงค์ในความเป็นจริงได้รับอิทธิพลจากแนวโน้ม (Trend) ฤดูกาล (Seasonal) วัฎจักร (Cycle) และเหตุการณ์ผิดปกติ (Irregular Variation) การใช้อนุกรมเวลามี 3 วิธี คือ

Show
  • การพยากรณ์อย่างง่าย (naïve Forecast) เป็นการพยากรณ์ว่ายอดขายในอนาคตจะเท่ากับยอดขายปัจจุบัน เช่น เดือนมกราคมขายได้ 35 กล่อง เดือนกุมภาพันธ์ควรจะขายได้ 35 กล่อง เช่นกัน ถ้าเดือนกุมภาพันธ์ขายได้จริง 42 กล่อง ก็จะพยากรณ์ว่าเดือนมีนาคมว่าขายได้ 42 กล่องเช่นกัน
  • การหาค่าเฉลี่ยเคลื่อนที่ (Moving Average) เป็นการหาค่าเฉลี่ยของยอดขายโดยใช้จำนวนข้อมูล 3 ช่วงเวลาขึ้นไปในการคำนวณ เมื่อเวลาผ่านไป 1 ช่วงก็ใช้ข้อมูลใหม่มาเฉลี่ยแทนข้อมูลในช่วงเวลาไกลที่สุดซึ่งจะถูกตัดทิ้งไป
  • การปรับเรียบด้วยเอ็กซ์โปเนนเชียล (Exponential Smoothing) เป็นการหาค่าเฉลี่ยเคลื่อนที่แบบถ่วงน้ำหนักที่จัดค่าพยากรณ์ออกมาในรูปการใช้สมการคำนวณ ซึ่งจะใช้ค่าข้อมูลเริ่มต้นค่าเดียวและถ่วงน้ำหนักโดยใช้สัมประสิทธิ์เชิงเรียบ ที่มีค่าอยู่ระหว่าง 0 ถึง 1.00

Related Posts

การวิเคราะห์อนุกรมเวลา (Time Series Analysis) หมายถึง การวิเคราะห์ (ความผันแปร) ตามลำดับเวลา แบ่งออกเป็น Tค่าแนวโน้ม , Sค่าการผันแปรตามฤดูก , Cค่าการผันแปรตามวัฎจักร , Iการผันแปรเนื่องจากเหตุการณ์ไม่ปกติ

  • ค่าแนวโน้ม (Long Term Trend  : T)  ค่าแนวโน้มเป็นการแสดงถึงการเคลื่อนไหวหรือเปลี่ยนแปลงของข้อมูลในระยะยาว เช่น ปริมาณการใช้ไฟฟ้าของประเทศไทย, ปริมาณการนำเข้าน้ำมันดิบ เป็นต้น
  • ค่าการผันแปรตามฤดูก (Seasonal Variation : S) หมายถึงการเปลี่ยนแปลงตามฤดูกาล โดยเกิดขึ้นซ้ำ ๆ กันในรอบ 1 ปี จนกลายเป็นแบบแผนเดียวกัน เช่นผลผลิตข้าวจะสูงในช่วงไตรมาสแรกของปี , ยอดขายของห้างสรรพสินค้าจะสูงในช่วงปลายปี, เป็นต้น  ในการวิเคราะห์การผันแปรตามฤดูกาลนี้จะวัดออกมาในรูปของดัชนีฤดูกาล(Seasonal Index)
  • ค่าการผันแปรตามวัฎจักร (Cyclical Variation : C) หมายถึงการเคลื่อนไหวที่เป็นไปตามวัฎจักร(เช่นวัฎจักรธุรกิจ) ซึ่งการเคลื่อนไหวตามวัฎจักรนี้จะมีลักษณะคล้ายกับการผันแปรตามฤดูกาล แต่จะมีระยะเวลาที่ยาวนานกว่า
  • การผันแปรเนื่องจากเหตุการณ์ไม่ปกติ (Irregular Variation : I) การผันแปรชนิดนี้ไม่แน่นอน ไม่สามารถคาดการณ์ได้ล่วงหน้า เช่น ภัยธรรมชาติ, สงคราม, การนัดหยุดงาน, เป็นต้น

ข้อมูลอนุกรมเวลา อาจได้รับอิทธิพลของปัจจัยที่เป็นส่วนประกอบของอนุกรมเวลาทั้ง 4 ปัจจัยหรือเพียงปัจจัยใดปัจจัยหนึ่งเท่านั้น  การวิเคราะห์จึงควรแยกวิเคราะห์ทีละปัจจัย ซึ่งในที่นี้จะกล่าวถึงการวิเคราะห์ ปัจจัยค่าแนวโน้ม และค่าผันแปรตามฤดูกาลเท่านั้น

Related Posts

สรุป Time Series Analysis in Python — A Comprehensive Guide with Examples

ข้อมูลอนุกรมเวลา(Time Series data) คือชุดของข้อมูลที่เก็บรวบรวมตามระยะเวลาเป็นช่วง ๆ การคาดการณ์อนุกรมเวลามีความสำคัญเชิงธุรกิจอย่างมาก ข้อมูลที่ธุรกิจเก็บและต้องการพยากรณ์มักมาในรูปแบบอนุกรมเวลา เช่นอุปสงค์และยอดขายจำนวนผู้เข้าชมเว็บไซต์ราคาหุ้น ฯลฯ เป็นข้อมูลอนุกรมเวลา

การวิเคราะห์อนุกรมเวลาเกี่ยวข้องกับการทำความเข้าใจกับแง่มุมต่าง ๆ เกี่ยวกับการเปลี่ยนแปลงตามธรรมชาติของข้อมูล เพื่อให้สามารถพยากรณ์ข้อมูลในอนาคตได้เเม่นยำขึ้น

ตัวอย่างข้อมูลอนุกรมเวลา (Time Series data)

from dateutil.parser import parse 
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
# Import as Dataframe
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'])
df.head()

panel data

คือ ข้อมูลที่เก็บจากหน่วยตัวอย่าง i ในช่วงเวลาต่างๆ ทำให้ข้อมูลแต่ละช่วงเวลา ไม่เป็นอิสระต่อกัน ความแตกต่างคือนอกเหนือจากอนุกรมเวลายังมีตัวแปรที่เกี่ยวข้องอย่างน้อยหนึ่งตัวที่วัดในช่วงเวลาเดียวกัน โดยทั่วไปคอลัมน์ที่อยู่ในข้อมูลพาเนลจะมีตัวแปรอธิบายซึ่งมีประโยชน์ในการทำนาย Y โดยที่คอลัมน์เหล่านั้นจะพร้อมใช้งานในช่วงการคาดการณ์ในอนาคต

ตัวอย่างข้อมูล panel

# dataset source: https://github.com/rouseguy
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/MarketArrivals.csv')
df = df.loc[df.market=='MUMBAI', :]
df.head()

การแสดงข้อมูลอนุกรมเวลา

มาใช้ matplotlib เพื่อแสดงข้อมูลอนุกรมเวลา

# Time series data source: fpp pacakge in R.
import matplotlib.pyplot as plt
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')

# Draw Plot
def plot_df(df, x, y, title="", xlabel='Date', ylabel='Value', dpi=100):
plt.figure(figsize=(16,5), dpi=dpi)
plt.plot(x, y, color='tab:red')
plt.gca().set(title=title, xlabel=xlabel, ylabel=ylabel)
plt.show()

plot_df(df, x=df.index, y=df.value, title='Monthly anti-diabetic drug sales in Australia from 1992 to 2008.')

เนื่องจากค่าทั้งหมดเป็นค่าบวก เราสามารถแสดงสิ่งนี้บนทั้งสองด้านของแกน Y เพื่อเน้นการเติบโต

# Import data
df = pd.read_csv('datasets/AirPassengers.csv', parse_dates=['date'])
x = df['date'].values
y1 = df['value'].values

# Plot
fig, ax = plt.subplots(1, 1, figsize=(16,5), dpi= 120)
plt.fill_between(x, y1=y1, y2=-y1, alpha=0.5, linewidth=2, color='seagreen')
plt.ylim(-800, 800)
plt.title('Air Passengers (Two Side View)', fontsize=16)
plt.hlines(y=0, xmin=np.min(df.date), xmax=np.max(df.date), linewidth=.5)
plt.show()

การเปรียบเทียบรายปีบ้างครั้งเนื่องจากข้อมูลเป็นฤดูกาลเราอาจต้องเปลี่ยบเทียบในช่วงเดือนเดี่ยวกัน

# Import Datadf = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')df.reset_index(inplace=True)# Prepare datadf['year'] = [d.year for d in df.date]df['month'] = [d.strftime('%b') for d in df.date]years = df['year'].unique()# Prep Colorsnp.random.seed(100)mycolors = np.random.choice(list(mpl.colors.XKCD_COLORS.keys()), len(years), replace=False)# Draw Plotplt.figure(figsize=(16,12), dpi= 80)for i, y in enumerate(years):if i > 0:plt.plot('month', 'value', data=df.loc[df.year==y, :], color=mycolors[i], label=y)plt.text(df.loc[df.year==y, :].shape[0]-.9, df.loc[df.year==y, 'value'][-1:].values[0], y, fontsize=12, color=mycolors[i])# Decorationplt.gca().set(xlim=(-0.3, 11), ylim=(2, 30), ylabel='$Drug Sales$', xlabel='$Month$')plt.yticks(fontsize=12, alpha=.7)plt.title("Seasonal Plot of Drug Sales Time Series", fontsize=20)plt.show()

Boxplot ของการกระจายแบบ Month-wise (Seasonal) และ Year-wise (trend)

เราสามารถจัดกลุ่มข้อมูลตามช่วงเวลาตามฤดูกาลและดูว่ามีการกระจายค่าภายในปีหรือเดือนที่กำหนดอย่างไรและเปรียบเทียบได้อย่างไรเมื่อเวลาผ่านไป

# Import Data
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/mast er/a10.csv', parse_dates=['date'], index_col='date')
df.reset_index(inplace=True)

# Prepare data
df['year'] = [d.year for d in df.date]
df['month'] = [d.strftime('%b') for d in df.date]
years = df['year'].unique()

# Draw Plot
fig, axes = plt.subplots(1, 2, figsize=(20,7), dpi= 80)
sns.boxplot(x='year', y='value', data=df, ax=axes[0])
sns.boxplot(x='month', y='value', data=df.loc[~df.year.isin([1991, 2008]), :])

# Set Title
axes[0].set_title('Year-wise Box Plot\n(The Trend)', fontsize=18);
axes[1].set_title('Month-wise Box Plot\n(The Seasonality)', fontsize=18)
plt.show()

บ็อกซ์พล็อตทำให้การกระจายรายปีและรายเดือนชัดเจน นอกจากนี้ในบ็อกซ์พล็อตแบบเดือนต่อเดือนของเดือนธันวาคมและมกราคมมีการขายยาที่สูงขึ้นอย่างชัดเจนซึ่งสามารถนำมาประกอบกับฤดูส่วนลดวันหยุด

การหา PATTERN ของข้อมูลอนุกรมเวลา

การหารูปแบบการเคลื่อนไหวของข้อมูลอนุกรมเวลาอย่างๆ ง่ายทำได้โดยการหาแนวโน้ม

การคาดการณ์เส้นแนวโน้มจากสมการต่างๆ โดยปกติมักใช้สมการดังต่อไปนี้

สมการเชิงเส้นตรง

Y = aX +b

สมการ Polynominal

Y =aX**n + aX**(n-1) …..aX +b

สมการ Logistic

Y = aIn(X) + b

สมการ exponential

Y = a* *x + b

#import libery
!pip install -q requests
import requeste
import pandas as pd
import datetime as dt
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
#import Dataset
dataurl = "https://covid19.th-stat.com/"
htmlsource = requests.get(dataurl).content
odat = pd.read_html(htmlsource)[0]
#chang colum name
daycount = odat['หมายเลข'].values
daycount = [int(d.split('-')[-1].strip()) for d in daycount]
odat['daycount'] = daycount
dat = odat[['วันที่ยืนยัน','daycount']]
dat = dat.groupby('วันที่ยืนยัน').max()
dat = dat.sort_values(by='daycount')
dat['date'] = list(dat.index.values)
dat['date'] = dat['date'].astype('datetime64[ns]')
dat.index = range(len(dat))
import pylab as py
xdata = list(dat.index.values)
ydata = list(dat['daycount'].values)
py.plot(xdata,ydata)

ขั้นตอนต่อมาคือประกาศฟังชั่นที่จะใช้ในการพยากรณ์ ในที่นี้จะใช้ สมการ exponential และสมการ Polynominal กำลัง2,3

import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
def expofunc(x, a, b, c):
return a * np.exp(b * x) + c
def polyfunc(x,a,b,c):
return a*x**2+b*x+c
def polyfunc2(x,a,b,c,d):
return a*x**3+b*x**2+c*x+d
expoparam, _ = curve_fit(expofunc, xdata, ydata)
polyparam, _ = curve_fit(polyfunc, xdata, ydata)
polyparam2, _ = curve_fit(polyfunc2, xdata, ydata)

a,b,c=polyparam
predictfrompoly = []
daylist = list(range(0,xrange))
for xi in daylist:
predictfrompoly.append(polyfunc(xi,a,b,c))

xrange = 100
predictfromexpo = []
daylist = list(range(0,xrange))
for xi in daylist:
predictfromexpo.append(expofunc(xi,a,b,c))
a,b,c=polyparam
predictfrompoly = []
daylist = list(range(0,xrange))
for xi in daylist:
predictfrompoly.append(polyfunc(xi,a,b,c))
a,b,c,d=polyparam2predictfrompoly2 = []
daylist = list(range(0,xrange))
for xi in daylist:
predictfrompoly2.append(polyfunc2(xi,a,b,c,d))
def funcplot. (xlim,predictfrompoly,predictfromexpo,daylist,xdata,ydata):py.plot(daylist[0:xlim],predictfrompoly[0:xlim],label='Predicted Polyfit')
py.plot(daylist[0:xlim],predictfromexpo[0:xlim],label='Predicted Expofit')
py.plot(xdata,ydata,label='Actual')
py.legend()
py.grid()

เปรียบเทียบแต่ละสมการที่เราทำนายได้

nextday = 0xlim = 39 + nextdaypy.plot(daylist[0:xlim],predictfrompoly[0:xlim],label='Predicted Polyfit')py.plot(daylist[0:xlim],predictfrompoly2[0:xlim],label='Predicted Polyfit#2')py.plot(daylist[0:xlim],predictfromexpo[0:xlim],label='Predicted Expofit')py.plot(xdata,ydata,label='Actual')
py.legend()
py.grid()

จะสังเกตเห็นได้ว่าจำนวนผู้ติดเชื่อมีความใกล้เคียงกับ Polynominal กำลัง3 มากที่สุด

ต่อมาเราก็มาพยากรณ์จำนวนผู้ติดเชื่อในอีก 30 วันข้างหน้า

nextday = 30xlim = 40 + nextdaypy.plot(daylist[0:xlim],predictfrompoly[0:xlim],label='Predicted Polyfit')py.plot(daylist[0:xlim],predictfrompoly2[0:xlim],label='Predicted Polyfit#2')py.plot(daylist[0:xlim],predictfromexpo[0:xlim],label='Predicted Expofit')py.plot(xdata,ydata,label='Actual')
py.legend()
py.grid()

ข้อมูลอนุกรมเวลาประกอบไปด้วย: ค่าพื้นฐาน+ แนวโน้ม + ฤดูกาล + ข้อผิดพลาด

มีการสังเกตแนวโน้มเมื่อมีการเพิ่มหรือลดความชันที่สังเกตได้ในอนุกรมเวลา ในขณะที่ฤดูกาลมีการสังเกตเมื่อมีรูปแบบการทำซ้ำที่ชัดเจนสังเกตได้ระหว่างช่วงเวลาปกติเนื่องจากปัจจัยตามฤดูกาล อาจเป็นเพราะเดือนของปี, วันที่ของเดือน, วันธรรมดาหรือแม้แต่เวลาของวัน

อย่างไรก็ตามไม่ได้บังคับว่าอนุกรมเวลาทั้งหมดจะต้องมีแนวโน้มและ / หรือฤดูกาล อนุกรมเวลาอาจไม่มีแนวโน้มที่ชัดเจน แต่มีฤดูกาล ตรงกันข้ามอาจมีแต่แนวโน้มไม่มีฤดูกาลก็ได้

ดังนั้นอนุกรมเวลาอาจถูกจินตนาการว่าเป็นการรวมกันของแนวโน้มฤดูกาลและข้อผิดพลาด

fig, axes = plt.subplots(1,3, figsize=(20,4), dpi=100)
pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/guinearice.csv', parse_dates=['date'], index_col='date').plot(title='Trend Only', legend=False, ax=axes[0])

pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/sunspotarea.csv', parse_dates=['date'], index_col='date').plot(title='Seasonality Only', legend=False, ax=axes[1])

pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/AirPassengers.csv', parse_dates=['date'], index_col='date').plot(title='Trend and Seasonality', legend=False, ax=axes[2])

อีกแง่มุมที่ควรพิจารณาก็คือพฤติกรรมแบบวนรอบ ที่เกิดขึ้นเมื่อรูปแบบการขึ้นและลงในซีรีส์ไม่ได้เกิดขึ้นในช่วงเวลาที่กำหนดตามปฏิทิน ควรใช้ความระมัดระวังเพื่อไม่ให้เกิดความสับสน ‘เอฟเฟกต์’ กับเอฟเฟกต์ “ซีซัน”

ดังนั้นจะแยกความแตกต่างระหว่างรูปแบบ “วงจร” กับ “ฤดูกาล” อย่างไรหากรูปแบบไม่ใช่ความถี่ตามปฏิทินที่แน่นอนก็เป็นวงจร เพราะต่างจากฤดูกาลฤดูกาลผลกระทบตามวงจรมักจะได้รับอิทธิพลจากธุรกิจและปัจจัยทางเศรษฐกิจและสังคมอื่น ๆ

อนุกรมเวลาแบบเพิ่มและแบบคูณ

ขึ้นอยู่กับลักษณะของแนวโน้มและฤดูกาลอนุกรมเวลาสามารถสร้างแบบจำลองเป็นAdditiveหรือแบบMultiplicativeซึ่งการสังเกตแต่ละครั้งในชุดสามารถแสดงได้ทั้งผลรวมหรือผลคูณของส่วนประกอบ:

Additive time series:
Value = Base Level + Trend + Seasonality + Error

Multiplicative Time Series:
Value = Base Level x Trend x Seasonality x Error

7.จะแยกอนุกรมเวลาออกเป็นส่วนประกอบได้อย่างไร

เราสามารถสามารถแยกอนุกรมเวลาโดยพิจารณาว่าอนุกรมเป็นการรวมกันของBase Levelแนวโน้มดัชนีตามฤดูกาลและError โดยใช้ seasonal_decompose ในstatsmodels

from statsmodels.tsa.seasonal import seasonal_decompose
from dateutil.parser import parse

# Import Data
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')

# Multiplicative Decomposition
result_mul = seasonal_decompose(df['value'], model='multiplicative', extrapolate_trend='freq')

# Additive Decomposition
result_add = seasonal_decompose(df['value'], model='additive', extrapolate_trend='freq')

# Plot
plt.rcParams.update({'figure.figsize': (10,10)})
result_mul.plot().suptitle('Multiplicative Decompose', fontsize=22)
result_add.plot().suptitle('Additive Decompose', fontsize=22)
plt.show()

หากต้องการเอาผลลัพธ์มาแยกใน datafram ก็ทำได้ดังนี้

# Extract the Components — —

# Actual Values = Product of (Seasonal * Trend * Resid)df_reconstructed = pd.concat([result_mul.seasonal, result_mul.trend, result_mul.resid, result_mul.observed], axis=1)df_reconstructed.columns = [‘seas’, ‘trend’, ‘resid’, ‘actual_values’]df_reconstructed.head()

ผลรวมของ seas, trend and resid จะเท่ากับ actual_values.

Stationary and Non-Stationary Time Series

Stationarity เป็นคุณสมบัติของอนุกรมเวลา อนุกรมที่อยู่กับที่นั้นเป็นค่าที่ค่าของอนุกรมไม่ใช่ฟังก์ชันของเวลา

นั่นคือคุณสมบัติทางสถิติของข้อมูลเช่นค่าเฉลี่ยความแปรปรวนและความสัมพันธ์อัตโนมัติมีค่าคงที่เมื่อเวลาผ่านไป Autocorrelation ของซีรี่ย์นั้นไม่มีอะไรนอกจากความสัมพันธ์ของซีรี่ย์กับค่าก่อนหน้านี้

ดังนั้นวิธีการระบุว่าชุดอยู่กับที่หรือไม่? ลองพล็อตตัวอย่างเพื่อทำให้ชัดเจน

วิธีการพยากรณ์ทางสถิติส่วนใหญ่ออกแบบมาเพื่อทำงานกับอนุกรมเวลาแบบ non-stationary ขั้นตอนแรกในกระบวนการคาดการณ์คือโดยทั่วไปแล้วจะทำการแปลงบางอย่างเพื่อแปลงข้อมูลให้เป็น stationary

วิธีสร้างข้อมูลอนุกรมเวลาแบบ stationary?

เราสามารถสร้าง stationary โดย:

  1. ความแตกต่างของซีรี่ส์ (หนึ่งครั้งหรือมากกว่า)Differencing the Series (once or more)
  2. ใส่ Logarithm ในข้อมูล
  3. ใส่รากที่ n ให้ข้อมูล

วิธีที่นิยมใช้ในการแปลงข้อมูลอนุกรมเวลาให้เป็น time series โดย การดําเนินการหาผลต่างระหว่างช่วงเวลา ของข้อมูลอย่างน้อยหนึ่งครั้งจนกว่าจะกลายเป็นประมาณนิ่ง

ถ้า 𝑦𝑡 เป็นตัวแปรที่เราสนใจแล้ว first differencing ของ 𝑦𝑡 จะเท่ากับ 𝑦𝑡 − 𝑦𝑡−1 = 𝑦𝑡 − 𝐿𝑦𝑡 = (1 − 𝐿)𝑦𝑡

ตัวอย่างให้ข้อมูล: [1, 5, 2, 12, 20]

เราสามารถแปลงขั้นที่ 1: [5–1, 2–5, 12–2, 20–12] = [4, -3, 10, 8]

Seเราสามารถแปลงขั้นที่ 2: [-3–4, -10–3, 8–10] = [-7, -13, -2]

ทำใมต้องทำข้อมูลให้เป็น non-stationary series stationary ก่อนพยากรณ์?

การถดถอยเชิงเส้นจะเเม่นยำที่สุดเมื่อตัวแปร X ไม่สัมพันธ์กับตัวแปรเป้าหมาย ดังนั้นการแก้ปัญหาให้กับ stationary จะช่วยแก้ปัญหานี้ได้เนื่องจากจะลบความสัมพันธ์โดยธรรมชาติใดๆออกไป ทำให้ตัวแปรในการทำนายในแบบจำลองการพยากรณ์เป็นอิสระ

วิธีการทดสอบ stationary

วิธีทดสอบ stationary อาจทำง่ายๆด้วยการพล็อตกราฟ

อีกวิธีหนึ่งคือการแบ่งชุดข้อมูลออกเป็น 2 ส่วนหรือมากกว่านั้นและคำนวณสถิติสรุปเช่นค่าเฉลี่ยความแปรปรวนและค่าความสัมพันธ์อัตโนมัติ หากสถิติแตกต่างกันมากแสดงว่าซีรีส์ไม่น่าจะstationary

อย่างไรก็ตามคุณจำเป็นต้องมีวิธีในการพิจารณาเชิงปริมาณว่าชุดข้อมูล stationary หรือไม่ ซึ่งสามารถทำได้โดยใช้การทดสอบทางสถิติที่เรียกว่า ‘Unit Root Tests’ มีหลายรูปแบบของสิ่งนี้ซึ่งการทดสอบตรวจสอบว่าอนุกรมเวลาแบบ non-stationary และมี unit root

มีการทำสอบ Unit Root หลายวิธีเช่น

  1. Augmented Dickey Fuller test (ADH Test)
  2. Kwiatkowski-Phillips-Schmidt-Shin — KPSS test (trend stationary)
  3. Philips Perron test (PP Test)

ที่ใช้กันมากที่สุดคือการทดสอบ ADF Test ที่สร้างสมมติฐาน null hypothesis ว่าข้อมูลเป็น non-stationary ดังนั้นถ้าค่าระดับนัยสำคัญ (0.05) เราจะปฏิเสธ null hypothesis

การทดสอบ KPSS นั้นใช้สำหรับทดสอบแนวโน้มstationary สมมติฐาน null hypothesis และการตีความค่า P เป็นค่าที่ตรงกันข้ามกับการทดสอบ ADH โค้ดด้านล่างใช้การทดสอบสองรายการนี้โดยใช้แพคเกจ statsmodels ด้วย Python

from statsmodels.tsa.stattools import adfuller, kpss
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'])

# ADF Test
result = adfuller(df.value.values, autolag='AIC')
print(f'ADF Statistic: {result[0]}')
print(f'p-value: {result[1]}')
for key, value in result[4].items():
print('Critial Values:')
print(f' {key}, {value}')

# KPSS Test
result = kpss(df.value.values, regression='c')
print('\nKPSS Statistic: %f' % result[0])
print('p-value: %f' % result[1])
for key, value in result[3].items():
print('Critial Values:')
print(f' {key}, {value}')

การขจัดแนวโน้มออกจากชุดข้อมูลอนุกรณ์เวลา

การขจัดแนวโน้มออกจากชุดข้อมูลอนุกรณ์เวลา มีหลายวิธี

  1. ลบเส้นแนวโน้มที่เหมาะสมที่สุดออกจากข้อมูลอนุกรมเวลา เส้นแนวโน้มที่เหมาะสมที่สุดหาได้จากแบบจำลองการถดถอยเชิงเส้นพร้อม
  2. ลบด้วยค่าเฉลี่ย
  3. ใช้วิธีการทางสถิติอื่นเช่น Baxter-King (statsmodels.tsa.filters.bkfilter) Hodrick-Prescott (statsmodels.tsa.filters.hpfilter) เพื่อลบเส้นค่าเฉลี่ยเคลื่อนที่หรือองค์ประกอบวัฏจักร
# Using scipy: Subtract the line of best fit
from scipy import signal
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'])
detrended = signal.detrend(df.value.values)
plt.plot(detrended)
plt.title('Drug Sales detrended by subtracting the least squares fit', fontsize=16)
# Using scipy: Subtract the line of best fit
from scipy import signal
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'])
detrended = signal.detrend(df.value.values)
plt.plot(detrended)
plt.title('Drug Sales detrended by subtracting the least squares fit', fontsize=16)

วิธีขจัดฤดูกาลออกจากข้อมูลอนุกรมเวลา

มีหลายวิธีในการขจัดฤดูกาลออกจากข้อมูลอนุกรมเวลา

  1. ใช้ค่าเฉลี่ยเคลื่อนที่
  2. ลบด้วยค่าของฤดูกาลก่อนหน้า
  3. แบ่งชุดข้อมูลด้วยดัชนีตามฤดูกาลที่ได้จากการแยก STL
# Subtracting the Trend Component.
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'], index_col='date')

# Time Series Decomposition
result_mul = seasonal_decompose(df['value'], model='multiplicative', extrapolate_trend='freq')

# Deseasonalize
deseasonalized = df.value.values / result_mul.seasonal

# Plot
plt.plot(deseasonalized)
plt.title('Drug Sales Deseasonalized', fontsize=16)
plt.plot()

วิธีทดสอบฤดูกาลตามในข้อมูลอนุกรมเวลา

หากคเราต้องการการตรวจสอบฤดูกาลที่ชัดเจนยิ่งขึ้นให้ใช้พล็อต Autocorrelation Function (ACF) เพิ่มเติมเกี่ยวกับ ACF ในส่วนที่จะเกิดขึ้น แต่เมื่อมีรูปแบบตามฤดูกาลที่แข็งแกร่งพล็อต ACF มักจะแสดงให้เห็นถึงหนามแหลมที่ซ้ำแล้วซ้ำอีกที่ทวีคูณของหน้าต่างตามฤดูกาล

from pandas.plotting import autocorrelation_plot
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv')

# Draw Plot
plt.rcParams.update({'figure.figsize':(9,5), 'figure.dpi':120})
autocorrelation_plot(df.value.tolist())

วิธีการจัดการกับค่าที่หายไปในอนุกรมเวลา?

ในบ้างครั้งข้อมูลที่เราได้มาอาจมีข้อมูลที่ขาดหายไป เรามีทางเลือกมากมายในการเติบค่าที่หายไปอาทิเช่น

  • Backward Fill
  • Linear Interpolation
  • Quadratic interpolation
  • Mean of nearest neighbors
  • Mean of seasonal couterparts

เราจะเลือกวิธีใหนนั้นขึ้นอยู่กัว่าเราต้องการความเชื่อมั่นในค่านั้นขนาดใหน

  1. หากเรามีตัวแปรอธิบายให้ใช้แบบจำลองการทำนาย เช่นฟอเรสต์แบบสุ่มหรือเพื่อนบ้าน k- ที่ใกล้ที่สุดเพื่อทำนาย
  2. หากการสังเกตการณ์ในอดีตเพียงพอให้คาดการณ์ค่าที่หายไป
  3. หากมีข้อสังเกตในอนาคตมากพอให้ย้อนกลับค่าที่หายไป
    การคาดการณ์ของคู่จากรอบก่อนหน้า

autocorrelation

Autocorrelation เป็นความสัมพันธ์ของชุดข้อมูลที่เกิดจากตัวข้อมูลเอง หากชุดข้อมูลมีความสัมพันธ์กันอย่างมีนัยสำคัญ นั่นหมายความว่าค่าก่อนหน้าของชุดข้อมูล อาจมีประโยชน์ในการทำนายค่าปัจจุบัน

การประเมินการพยากรณ์

ยิ่งมีรูปแบบเวลาปกติและทำซ้ำได้มากเท่าไหร่ก็ยิ่งง่ายต่อการคาดการณ์เท่านั้น ‘Entropimate Entropy’ สามารถใช้ในการกำหนดปริมาณความสม่ำเสมอและความไม่แน่นอนของความผันผวนในอนุกรมเวลา

ยิ่งค่าเอนโทรปีโดยประมาณสูงเท่าไหร่ก็ยากที่จะคาดการณ์ได้

# https://en.wikipedia.org/wiki/Approximate_entropy
ss = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/sunspotarea.csv')
a10 = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv')
rand_small = np.random.randint(0, 100, size=36)
rand_big = np.random.randint(0, 100, size=136)

def ApEn(U, m, r):
"""Compute Aproximate entropy"""
def _maxdist(x_i, x_j):
return max([abs(ua - va) for ua, va in zip(x_i, x_j)])

def _phi(m):
x = [[U[j] for j in range(i, i + m - 1 + 1)] for i in range(N - m + 1)]
C = [len([1 for x_j in x if _maxdist(x_i, x_j) <= r]) / (N - m + 1.0) for x_i in x]
return (N - m + 1.0)**(-1) * sum(np.log(C))

N = len(U)
return abs(_phi(m+1) - _phi(m))

print(ApEn(ss.value, m=2, r=0.2*np.std(ss.value))) # 0.651
print(ApEn(a10.value, m=2, r=0.2*np.std(a10.value))) # 0.537
print(ApEn(rand_small, m=2, r=0.2*np.std(rand_small))) # 0.143
print(ApEn(rand_big, m=2, r=0.2*np.std(rand_big))) # 0.716

การปรับค่าอนุกรมเวลาให้ราบเรียบ

การทำให้เรียบของอนุกรมเวลาอาจมีประโยชน์ใน: การลดเอฟเฟกต์ของการรบกวนในในการประมาณค่าวิธีการทำในการปรับค่าข้อมูลให้ราบเรียบ มีวิธีการต่อไปนี้:

  1. ค่าเฉลี่ยเคลื่อนที่ ค่าเฉลี่ยเคลื่อนที่คือ ค่าเฉลี่ยของชุดข้อมูเป็นช่วงๆเช่น: 12 มักมีประโยชน์ในการเปรียบเทียบข้อมูลที่มีทั้งแนวโน้มและฤดูกา
  2. Localized Regression LOESS ย่อมาจาก ‘regression LOcalized’ เหมาะกับการถดถอยหลายจุดในพื้นที่ใกล้เคียงของแต่ละจุด. ถูกนำมาใช้ในแพคเกจ statsmodels ซึ่งสามารถควบคุมระดับของการปรับให้เรียบโดยใช้อาร์กิวเมนต์ frac ซึ่งระบุเปอร์เซ็นต์ของจุดข้อมูลในบริเวณใกล้เคียงที่ควรได้รับการพิจารณาว่าเหมาะสมกับแบบจำลองการถดถอย
  3. Locally Weighted Regression
from statsmodels.nonparametric.smoothers_lowess import lowess
plt.rcParams.update({'xtick.bottom' : False, 'axes.titlepad':5})

# Import
df_orig = pd.read_csv('datasets/elecequip.csv', parse_dates=['date'], index_col='date')

# 1. Moving Average
df_ma = df_orig.value.rolling(3, center=True, closed='both').mean()

# 2. Loess Smoothing (5% and 15%)
df_loess_5 = pd.DataFrame(lowess(df_orig.value, np.arange(len(df_orig.value)), frac=0.05)[:, 1], index=df_orig.index, columns=['value'])
df_loess_15 = pd.DataFrame(lowess(df_orig.value, np.arange(len(df_orig.value)), frac=0.15)[:, 1], index=df_orig.index, columns=['value'])

# Plot
fig, axes = plt.subplots(4,1, figsize=(7, 7), sharex=True, dpi=120)
df_orig['value'].plot(ax=axes[0], color='k', title='Original Series')
df_loess_5['value'].plot(ax=axes[1], title='Loess Smoothed 5%')
df_loess_15['value'].plot(ax=axes[2], title='Loess Smoothed 15%')
df_ma.plot(ax=axes[3], title='Moving Average (3)')
fig.suptitle('How to Smoothen a Time Series', y=0.95, fontsize=14)
plt.show()

การทดสอบความเป็นเหตุเป็นผลของ Granger

การทดสอบความเป็นเหตุเป็นผลของ Granger ใช้เพื่อพิจารณาว่าอนุกรมเวลาหนึ่งจะมีประโยชน์ในการคาดการณ์แบบอื่น

โดยมีแนวคิดที่ว่าถ้า X ทำให้ Y ดังนั้นการคาดการณ์ของ Y ตามค่าก่อนหน้าของ Y และค่าก่อนหน้าของ X ความเชื่อมั่นควรสูงกว่าการคาดการณ์ของ Y ตามค่าก่อนหน้าของ Y เพียงอย่างเดียว

ดังนั้นเข้าใจว่า Granger causality ไม่ควรใช้เพื่อทดสอบว่าความล่าช้าของ Y เป็นสาเหตุของ Y หรือไม่โดยทั่วไปจะใช้กับตัวแปรภายนอก (ไม่ใช่ Y lag) เท่านั้น

สมมติฐาน Null คือ: ซีรีส์ในคอลัมน์ที่สองไม่เกรนเจอร์ทำให้เกิดซีรีส์ในครั้งแรก หากค่า P-Value มีค่าน้อยกว่าระดับนัยสำคัญ (0.05) คุณก็จะปฏิเสธสมมติฐานว่างแล้วสรุปได้ว่าความล่าช้าของ X นั้นมีประโยชน์จริง ๆ

อาร์กิวเมนต์ที่สอง maxlag บอกว่าจนถึงจำนวน lags ของ Y ที่ควรรวมในการทดสอบ

from statsmodels.tsa.stattools import grangercausalitytests
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/a10.csv', parse_dates=['date'])
df['month'] = df.date.dt.month
grangercausalitytests(df[['value', 'month']], maxlag=2)

ในกรณีข้างต้นค่า P เป็นศูนย์สำหรับการทดสอบทั้งหมด ดังนั้น ‘เดือน’ จึงสามารถใช้ในการคาดการณ์ผู้โดยสารได้

Note book

https://colab.research.google.com/drive/1dpkarE1ESU0Pe56cde4_yqt86BGhi-Yc

อ้างอิง

ข้อมูลแบบอนุกรมเวลามีทั้งหมดกี่องค์ประกอบ

อนุกรมเวลา คือ เซตของข้อมูลเชิงปริมาณที่มีการจัดเก็บในช่วงเวลาที่ติดต่อกัน ส่วนข้อมูล อนุกรมเวลา (Time Series Data) คือ ชุดของข้อมูลที่มีการเก็บรวบรวมตามระยะเวลาที่ติดต่อกัน อย่างเป็นระบบโดยทั่วไปข้อมูลอนุกรเวลาประกอบด้วยองค์ประกอบ 4 ส่วน คือ แนวโน้ม (Trend: T), ฤดูกาล (Seasonal: S), วัฏจักร (Cycle: C) และเหตุการณ์ที่ ...

ข้อมูลใดเป็นข้อมูลอนุกรมเวลา

ข้อมูลอนุกรมเวลา คือ ข้อมูลที่เก็บค่าต่อเนื่องในแต่ละเวลา เช่น รายจ่ายของแต่ละวันในหนึ่งเดือน ข้อมูลแบบตัดขวาง คือ ข้อมูลที่เจาะจงเวลาลงไปว่าสนใจค่าของเวลาไหน เช่น ข้อมูลปริมาณน้ำฝนของวันนี้ในแต่ละจังหวัด

ข้อมูลตัดขวาง มีอะไรบ้าง

ข้อมูลที่บอกลักษณะ สถานะ หรือ สภาพของสิ่งที่นักเรียนสนใจ ณ เวลาใดเวลาหนึ่ง เช่น จำนวนนักเรียนชายและนักเรียนหญิงของโรงเรียนแห่งหนึ่ง ณ วันที่ 20 มีนาคม พ.ศ.2563. จำนวนเด็กแรกเกิดของประเทศ ณ วันที่ 27 ธันวาคม พ.ศ.2564.

Time Series ใช้ทำอะไร

Time Series Analysis (การวิเคราะห์อนุกรมเวลา) เมื่อนำข้อมูลที่มีลักษณะเป็นอนุกรมเวลาเหล่านั้นมา วิเคราะห์ หรือสร้างกราฟ จะเห็นแนวโน้มของการเปลี่ยนแปลงข้อมูล ดังนั้น ด้วยการวิเคราะห์แบบใช้ อนุกรมเวลา สามารถช่วยในการ พยากรณ์ค่าที่กำลังจะเปลี่ยนแปลงในอนาคต โดยอาศัยดูการเคลื่อนไหวจากอดีตได้