Kursus
Pendahuluan
Rata-rata bergerak, juga disebut rata-rata gulir atau berjalan, digunakan untuk menganalisis data deret waktu dengan menghitung rata-rata dari berbagai subset dari keseluruhan dataset. Karena melibatkan pengambilan rata-rata dataset seiring waktu, ini juga disebut moving mean (MM) atau rolling mean.
Ada berbagai cara untuk menghitung rata-rata gulir, namun salah satunya adalah mengambil subset tetap dari satu rangkaian angka lengkap. Rata-rata bergerak pertama dihitung dengan merata-ratakan subset tetap pertama, lalu subset diubah dengan maju ke subset tetap berikutnya (menyertakan nilai berikutnya di subkelompok sekaligus mengecualikan angka sebelumnya dari rangkaian).
Moving average paling sering digunakan dengan data deret waktu untuk menangkap fluktuasi jangka pendek sambil berfokus pada tren yang lebih panjang.
Beberapa contoh data deret waktu antara lain harga saham, laporan cuaca, kualitas udara, produk domestik bruto, ketenagakerjaan, dan sebagainya.
Secara umum, moving average menghaluskan data.
Moving average menjadi tulang punggung banyak algoritme, dan salah satunya adalah Autoregressive Integrated Moving Average Model (ARIMA), yang menggunakan moving average untuk membuat prediksi data deret waktu.
Ada berbagai jenis moving average:
-
Simple Moving Average (SMA): Simple Moving Average (SMA) menggunakan jendela geser untuk mengambil rata-rata selama sejumlah periode waktu tertentu. Ini adalah mean berbobot sama dari n data sebelumnya.
Untuk memahami SMA lebih jauh, mari ambil contoh, sebuah urutan nilai n:

maka rolling average berbobot sama untuk n titik data pada dasarnya adalah mean dari M titik data sebelumnya, di mana M adalah ukuran jendela geser:

Demikian pula, untuk menghitung nilai rolling average berikutnya, nilai baru akan ditambahkan ke dalam jumlah, dan nilai periode waktu sebelumnya akan dikeluarkan, karena Anda sudah memiliki rata-rata periode waktu sebelumnya sehingga tidak diperlukan penjumlahan penuh setiap kali:

- Cumulative Moving Average (CMA): Berbeda dengan simple moving average yang membuang observasi tertua saat yang baru ditambahkan, cumulative moving average mempertimbangkan semua observasi sebelumnya. CMA bukan teknik yang sangat baik untuk menganalisis tren dan menghaluskan data. Alasannya, CMA merata-ratakan semua data sebelumnya hingga titik data saat ini, sehingga rata-rata berbobot sama dari urutan n nilai:
hingga waktu saat ini diberikan oleh:
Demikian pula, untuk memperbarui cumulative average untuk setiap nilai baru yang masuk dapat dihitung menggunakan rumus di bawah ini:

- Exponential Moving Average (EMA): Tidak seperti SMA dan CMA, exponential moving average memberikan bobot lebih besar pada harga terbaru dan sebagai akibatnya, dapat menjadi model yang lebih baik atau menangkap pergerakan tren dengan lebih cepat. Reaksi EMA berbanding lurus dengan pola data.
Karena EMA memberikan bobot lebih tinggi pada data terbaru dibanding data lama, EMA lebih responsif terhadap perubahan harga terkini dibandingkan SMA, yang membuat hasil dari EMA lebih tepat waktu dan karenanya EMA lebih disukai dibanding teknik lainnya.
Cukup teori, bukan? Mari langsung ke implementasi praktis moving average.
Mengimplementasikan Moving Average pada Data Deret Waktu
Simple Moving Average (SMA)
Pertama, mari buat data deret waktu dummy dan coba mengimplementasikan SMA hanya dengan Python.
Asumsikan ada permintaan untuk suatu produk dan diamati selama 12 bulan (1 Tahun), dan Anda perlu mencari moving average untuk periode jendela 3 dan 4 bulan.
Impor modul
import pandas as pd
import numpy as np
product = {'month' : [1,2,3,4,5,6,7,8,9,10,11,12],'demand':[290,260,288,300,310,303,329,340,316,330,308,310]}
df = pd.DataFrame(product)
df.head()
Jalankan dan edit kode dari Tutorial ini secara online
Jalankan kode| month | demand | |
|---|---|---|
| 0 | 1 | 290 |
| 1 | 2 | 260 |
| 2 | 3 | 288 |
| 3 | 4 | 300 |
| 4 | 5 | 310 |
Mari hitung SMA untuk ukuran jendela 3, yang berarti Anda akan mempertimbangkan tiga nilai setiap kali untuk menghitung moving average, dan untuk setiap nilai baru, nilai tertua akan diabaikan.
Untuk mengimplementasikannya, Anda akan menggunakan fungsi pandas iloc, karena kolom demand yang Anda butuhkan, Anda akan memfiksasi posisi kolom itu di fungsi iloc sementara baris akan berupa variabel i yang akan terus Anda iterasi sampai mencapai akhir dataframe.
for i in range(0,df.shape[0]-2):
df.loc[df.index[i+2],'SMA_3'] = np.round(((df.iloc[i,1]+ df.iloc[i+1,1] +df.iloc[i+2,1])/3),1)
| month | demand | SMA_3 | |
|---|---|---|---|
| 0 | 1 | 290 | NaN |
| 1 | 2 | 260 | NaN |
| 2 | 3 | 288 | 279.3 |
| 3 | 4 | 300 | 282.7 |
| 4 | 5 | 310 | 299.3 |
Untuk pengecekan cepat, mari juga gunakan fungsi bawaan pandas yaitu rolling dan lihat apakah hasilnya cocok dengan simple moving average kustom berbasis Python kita.
df['pandas_SMA_3'] = df.iloc[:,1].rolling(window=3).mean()
df.head()
| month | demand | SMA_3 | pandas_SMA_3 | |
|---|---|---|---|---|
| 0 | 1 | 290 | NaN | NaN |
| 1 | 2 | 260 | NaN | NaN |
| 2 | 3 | 288 | 279.3 | 279.333333 |
| 3 | 4 | 300 | 282.7 | 282.666667 |
| 4 | 5 | 310 | 299.3 | 299.333333 |
Keren, seperti yang Anda lihat, moving average kustom dan pandas cocok persis, yang berarti implementasi SMA Anda benar.
Mari juga cepat menghitung simple moving average untuk window_size 4.
for i in range(0,df.shape[0]-3):
df.loc[df.index[i+3],'SMA_4'] = np.round(((df.iloc[i,1]+ df.iloc[i+1,1] +df.iloc[i+2,1]+df.iloc[i+3,1])/4),1)
df.head()
| month | demand | SMA_3 | pandas_SMA_3 | SMA_4 | |
|---|---|---|---|---|---|
| 0 | 1 | 290 | NaN | NaN | NaN |
| 1 | 2 | 260 | NaN | NaN | NaN |
| 2 | 3 | 288 | 279.3 | 279.333333 | NaN |
| 3 | 4 | 300 | 282.7 | 282.666667 | 284.5 |
| 4 | 5 | 310 | 299.3 | 299.333333 | 289.5 |
df['pandas_SMA_4'] = df.iloc[:,1].rolling(window=4).mean()
df.head()
| month | demand | SMA_3 | pandas_SMA_3 | SMA_4 | pandas_SMA_4 | |
|---|---|---|---|---|---|---|
| 0 | 1 | 290 | NaN | NaN | NaN | NaN |
| 1 | 2 | 260 | NaN | NaN | NaN | NaN |
| 2 | 3 | 288 | 279.3 | 279.333333 | NaN | NaN |
| 3 | 4 | 300 | 282.7 | 282.666667 | 284.5 | 284.5 |
| 4 | 5 | 310 | 299.3 | 299.333333 | 289.5 | 289.5 |
Sekarang, Anda akan memplot data moving average yang telah Anda hitung.
import matplotlib.pyplot as plt
%matplotlib inline
plt.figure(figsize=[15,10])
plt.grid(True)
plt.plot(df['demand'],label='data')
plt.plot(df['SMA_3'],label='SMA 3 Months')
plt.plot(df['SMA_4'],label='SMA 4 Months')
plt.legend(loc=2)
<matplotlib.legend.Legend at 0x11fe15080>

Cumulative Moving Average
Saya rasa kini kita siap beralih ke dataset nyata.
Untuk cumulative moving average, mari gunakan air quality dataset yang dapat diunduh dari tautan ini.
df = pd.read_csv("AirQualityUCI/AirQualityUCI.csv", sep = ";", decimal = ",")
df = df.iloc[ : , 0:14]
df.head()
| Date | Time | CO(GT) | PT08.S1(CO) | NMHC(GT) | C6H6(GT) | PT08.S2(NMHC) | NOx(GT) | PT08.S3(NOx) | NO2(GT) | PT08.S4(NO2) | PT08.S5(O3) | T | RH | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 10/03/2004 | 18.00.00 | 2.6 | 1360.0 | 150.0 | 11.9 | 1046.0 | 166.0 | 1056.0 | 113.0 | 1692.0 | 1268.0 | 13.6 | 48.9 |
| 1 | 10/03/2004 | 19.00.00 | 2.0 | 1292.0 | 112.0 | 9.4 | 955.0 | 103.0 | 1174.0 | 92.0 | 1559.0 | 972.0 | 13.3 | 47.7 |
| 2 | 10/03/2004 | 20.00.00 | 2.2 | 1402.0 | 88.0 | 9.0 | 939.0 | 131.0 | 1140.0 | 114.0 | 1555.0 | 1074.0 | 11.9 | 54.0 |
| 3 | 10/03/2004 | 21.00.00 | 2.2 | 1376.0 | 80.0 | 9.2 | 948.0 | 172.0 | 1092.0 | 122.0 | 1584.0 | 1203.0 | 11.0 | 60.0 |
| 4 | 10/03/2004 | 22.00.00 | 1.6 | 1272.0 | 51.0 | 6.5 | 836.0 | 131.0 | 1205.0 | 116.0 | 1490.0 | 1110.0 | 11.2 | 59.6 |
Prapemrosesan adalah langkah penting setiap kali Anda bekerja dengan data. Untuk data numerik salah satu langkah prapemrosesan yang paling umum adalah memeriksa nilai NaN (Null). Jika ada nilai NaN, Anda dapat menggantinya dengan 0 atau rata-rata atau nilai sebelumnya atau sesudahnya, atau bahkan menghapusnya. Meskipun penggantian biasanya lebih baik daripada menghapus, karena dataset ini hanya memiliki beberapa nilai NULL, menghapusnya tidak akan memengaruhi kesinambungan deret.
df.isna().sum()
Date 114
Time 114
CO(GT) 114
PT08.S1(CO) 114
NMHC(GT) 114
C6H6(GT) 114
PT08.S2(NMHC) 114
NOx(GT) 114
PT08.S3(NOx) 114
NO2(GT) 114
PT08.S4(NO2) 114
PT08.S5(O3) 114
T 114
RH 114
dtype: int64
Dari keluaran di atas, Anda dapat melihat bahwa ada sekitar 114 nilai NaN di semua kolom, namun Anda akan mengetahui bahwa semuanya berada di akhir deret waktu, jadi mari cepat hapus.
df.dropna(inplace=True)
df.isna().sum()
Date 0
Time 0
CO(GT) 0
PT08.S1(CO) 0
NMHC(GT) 0
C6H6(GT) 0
PT08.S2(NMHC) 0
NOx(GT) 0
PT08.S3(NOx) 0
NO2(GT) 0
PT08.S4(NO2) 0
PT08.S5(O3) 0
T 0
RH 0
dtype: int64
Anda akan menerapkan cumulative moving average pada kolom Suhu (T), jadi mari pisahkan kolom itu dari keseluruhan data.
df_T = pd.DataFrame(df.iloc[:,-2])
df_T.head()
| T | |
|---|---|
| 0 | 13.6 |
| 1 | 13.3 |
| 2 | 11.9 |
| 3 | 11.0 |
| 4 | 11.2 |
Sekarang, Anda akan menggunakan metode pandas expanding untuk mencari rata-rata kumulatif dari data di atas. Jika Anda ingat dari pendahuluan, berbeda dengan simple moving average, cumulative moving average mempertimbangkan semua nilai sebelumnya saat menghitung rata-rata.
df_T['CMA_4'] = df_T.expanding(min_periods=4).mean()
df_T.head(10)
| T | CMA_4 | |
|---|---|---|
| 0 | 13.6 | NaN |
| 1 | 13.3 | NaN |
| 2 | 11.9 | NaN |
| 3 | 11.0 | 12.450000 |
| 4 | 11.2 | 12.200000 |
| 5 | 11.2 | 12.033333 |
| 6 | 11.3 | 11.928571 |
| 7 | 10.7 | 11.775000 |
| 8 | 10.7 | 11.655556 |
| 9 | 10.3 | 11.520000 |
Data deret waktu diplot terhadap waktu, jadi mari gabungkan kolom tanggal dan waktu lalu konversi menjadi objek datetime. Untuk mencapainya, Anda akan menggunakan modul datetime dari Python (Sumber: Time Series Tutorial).
import datetime
df['DateTime'] = (df.Date) + ' ' + (df.Time)
df.DateTime = df.DateTime.apply(lambda x: datetime.datetime.strptime(x, '%d/%m/%Y %H.%M.%S'))
Mari ubah indeks dataframe temperature dengan datetime.
df_T.index = df.DateTime
Sekarang mari plot suhu aktual dan cumulative moving average terhadap waktu.
plt.figure(figsize=[15,10])
plt.grid(True)
plt.plot(df_T['T'],label='temperature')
plt.plot(df_T['CMA_4'],label='CMA_4')
plt.legend(loc=2)
<matplotlib.legend.Legend at 0x1210a2d30>

Exponential Moving Average
df_T['EMA'] = df_T.iloc[:,0].ewm(span=40,adjust=False).mean()
df_T.head()
| T | CMA_4 | EMA | |
|---|---|---|---|
| DateTime | |||
| 2004-03-10 18:00:00 | 13.6 | NaN | 13.600000 |
| 2004-03-10 19:00:00 | 13.3 | NaN | 13.585366 |
| 2004-03-10 20:00:00 | 11.9 | NaN | 13.503153 |
| 2004-03-10 21:00:00 | 11.0 | 12.45 | 13.381048 |
| 2004-03-10 22:00:00 | 11.2 | 12.20 | 13.274655 |
plt.figure(figsize=[15,10])
plt.grid(True)
plt.plot(df_T['T'],label='temperature')
plt.plot(df_T['CMA_4'],label='CMA_4')
plt.plot(df_T['EMA'],label='EMA')
plt.legend(loc=2)
<matplotlib.legend.Legend at 0x14b2a41d0>

Wah! Seperti yang dapat Anda amati dari grafik di atas, Exponential Moving Average (EMA) melakukan pekerjaan yang sangat baik dalam menangkap pola data sementara Cumulative Moving Average (CMA) tertinggal cukup jauh.
Lanjutkan!
Selamat telah menyelesaikan tutorial ini.
Tutorial ini merupakan titik awal yang baik tentang cara menghitung moving average dari data Anda dan memahaminya.
Cobalah menulis kode Python untuk cumulative dan exponential moving average tanpa menggunakan pustaka pandas. Itu akan memberi Anda pemahaman yang jauh lebih mendalam tentang bagaimana keduanya dihitung dan dalam hal apa mereka berbeda satu sama lain.
Masih banyak yang bisa dieksplorasi. Cobalah menghitung partial auto-correlation antara data masukan dan moving average, dan coba temukan hubungan di antara keduanya.
Jika Anda ingin mempelajari lebih lanjut tentang DataFrame di pandas, ikuti kursus interaktif Fondasi pandas dari DataCamp.
Referensi:
Silakan ajukan pertanyaan apa pun terkait tutorial ini di kolom komentar di bawah.
