python 時間序列處理

數(shù)據(jù)說明:’./data/raw/pm25.csv’文件為某地2017年一段時間內(nèi)的PM2.5的每小時監(jiān)測數(shù)據(jù),數(shù)據(jù)按時間順序記錄(從2017-01-01 00:00:00開始,中間不間斷),由于各種原因造成了某些時刻的數(shù)據(jù)缺失。

要求:

1.利用已有的記錄數(shù)據(jù)進行建模,將缺失值填充完整,評估指標采用RMSE、MAE和;

2.嘗試多種方法進行建模對比各種模型的性能;

3.希望你不要直接用中值、均值、前一時刻、后一時刻等常數(shù)填充法進行填充(方法對比中可用做簡單對比,如表 2所示);

4.將數(shù)據(jù)填充完整后保存至’pm25_predicted.csv’文件(只保存缺失時刻的數(shù)據(jù),不按要求則作廢),數(shù)據(jù)格式如表 3所示(列名、文件名不按要求則作廢)。

題解:

(1)完成時間序列缺失數(shù)據(jù)填充,一般來說有如下幾種方式:常數(shù)填充有均值填充,中位數(shù)填充,眾數(shù)填充,前一時刻和后一時刻填充,傳統(tǒng)回歸模型方式有自回歸模型,移動平均模型,自回歸移動平均模型和差分自回歸移動平均模型,一般采用插值法填充數(shù)據(jù),插值辦法一般有滑動平均插值,線性插值,拉格朗日多項式插值;

(2)每個函數(shù)對應(yīng)一種辦法,先將數(shù)據(jù)用pandas從csv文件中讀取為df,然后進行數(shù)據(jù)插值的算法操作,最后將插值后的數(shù)據(jù)集用matplotlib呈現(xiàn)出來,最后將插值的數(shù)據(jù)轉(zhuǎn)化為df,用pandas重新寫回csv之中;

代碼:

1.time_series_fill.py

# -*- coding:utf-8 -*-

from pandas.compat import reduce

__author__ = 'gin.chen'

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

from scipy.interpolate import lagrange

# from fbprophet import Prophet

#

# 加載數(shù)據(jù)

def load_data():

? ? df = pd.read_csv('F:/muke/super_mali/data/raw/pm25.csv')

? ? # return df.head(100)

? ? return df

# 畫散點圖

def draw_scatte_diagram(df):

? ? plt.plot(df['index'].to_list(), df['PM2.5'].to_list())

? ? plt.show()

# 均值填充

def mean_method():

? ? df = load_data()

? ? df.fillna(df['PM2.5'].mean(), inplace=True)

? ? draw_scatte_diagram(df)

# 中位數(shù)填充

def median_method():

? ? df = load_data()

? ? df.fillna(df['PM2.5'].median(), inplace=True)

? ? draw_scatte_diagram(df)

# 眾數(shù)填充

def mode_method():

? ? df = load_data()

? ? df.fillna(df['PM2.5'].mode(), inplace=True)

? ? draw_scatte_diagram(df)

# 前一時刻填充

def ffill_method():

? ? df = load_data()

? ? df['PM2.5'].fillna(method='ffill', inplace=True)

? ? draw_scatte_diagram(df)

# 后一時刻填充

def bfill_method():

? ? df = load_data()

? ? df['PM2.5'].fillna(method='bfill', inplace=True)

? ? draw_scatte_diagram(df)

# 前后時刻平均值插值

def mean_by_before_after_method():

? ? df = load_data()

? ? # data_index = df['index'].to_list()

? ? # data_value = df['PM2.5'].to_list()

? ? fill = []

? ? for i in range(len(df)):

? ? ? ? if np.math.isnan(df.iloc[i - 1][1]):

? ? ? ? ? ? left = df.iloc[i - 2][1]

? ? ? ? ? ? for j in range(i, len(df)):

? ? ? ? ? ? ? ? if np.math.isnan(df.iloc[j][1]):

? ? ? ? ? ? ? ? ? ? continue

? ? ? ? ? ? ? ? else:

? ? ? ? ? ? ? ? ? ? right = df.iloc[j][1]

? ? ? ? ? ? ? ? ? ? break

? ? ? ? ? ? df.iloc[i - 1, 1] = (left + right) / 2

? ? ? ? ? ? fill_tuple = i, df.iloc[i - 1][1]

? ? ? ? ? ? fill.append(fill_tuple)

? ? draw_scatte_diagram(df)

? ? df = pd.DataFrame(fill, columns=['index', 'PM2.5'])

? ? df.to_csv('pm25_predicted_mean.csv', index=False)

# 線性插值詳細

def linear_detail(x1, y1, x2, y2):

? ? k = (y2 - y1) / (x2 - x1)

? ? b = y1 - k * x1

? ? return lambda x: b + k * x

# 線性插值

def linear_method():

? ? # global j

? ? df = load_data()

? ? fill = []

? ? for i in range(len(df)):

? ? ? ? if np.isnan(df.iloc[i][1]):

? ? ? ? ? ? for j in range(i, len(df)):

? ? ? ? ? ? ? ? if np.isnan(df.iloc[j][1]):

? ? ? ? ? ? ? ? ? ? continue

? ? ? ? ? ? ? ? else:

? ? ? ? ? ? ? ? ? ? break

? ? ? ? ? ? df.iloc[i, 1] = (linear_detail(i, df.iloc[i - 1][1], j + 1, df.iloc[j][1]))(i + 1)

? ? ? ? ? ? fill_tuple = i + 1, df.iloc[i][1]

? ? ? ? ? ? fill.append(fill_tuple)

? ? draw_scatte_diagram(df)

? ? df = pd.DataFrame(fill, columns=['index', 'PM2.5'])

? ? df.to_csv('pm25_predicted_linear.csv', index=False)

# 平滑插值詳細

def smooth_detail(series, pos, window=5):

? ? """

? ? :param series: 列向量

? ? :param pos: 被插值的位置

? ? :param window: 為取前后的數(shù)據(jù)個數(shù)

? ? :return:

? ? """

? ? y = series[list(range(pos - window, pos)) + list(range(pos + 1, pos + 1 + window))]? # 取數(shù)

? ? y = y[y.notnull()]

? ? return reduce(lambda a, b: a + b, y) / len(y)

# 平滑插值

def smooth_method(show=1):

? ? df_raw = load_data()

? ? df = df_raw['PM2.5'].copy()

? ? full = []

? ? for j in range(len(df)):

? ? ? ? if (df.isnull())[j]:? # 如果為空即插值。

? ? ? ? ? ? df[j] = smooth_detail(df, j)

? ? ? ? ? ? df_raw.loc[j, 'PM2.5'] = df[j]

? ? ? ? ? ? # print(j, df_raw.loc[j, 'index'], df_raw.loc[j, 'PM2.5'])

? ? ? ? ? ? full_tuple = df_raw.loc[j, 'index'], df_raw.loc[j, 'PM2.5']

? ? ? ? ? ? full.append(full_tuple)

? ? if show:

? ? ? ? draw_scatte_diagram(df_raw)

? ? ? ? df = pd.DataFrame(full, columns=['index', 'PM2.5'])

? ? ? ? df.to_csv('pm25_predicted_smooth.csv', index=False)

? ? return df_raw

# 拉格朗日插值詳細

def lagrange_detail(series, pos, window=5):

? ? """

? ? :param series: 列向量

? ? :param pos: 被插值的位置

? ? :param window: 為取前后的數(shù)據(jù)個數(shù)

? ? :return:

? ? """

? ? y = series[list(range(pos - window, pos)) + list(range(pos + 1, pos + 1 + window))]? # 取數(shù)

? ? y = y[y.notnull()]? # 剔除空值

? ? return lagrange(y.index, list(y))(pos)? # 插值并返回插值結(jié)果

# 拉格朗日插值

def lagrange_method():

? ? df_raw = load_data()

? ? df = df_raw['PM2.5'].copy()

? ? full = []

? ? for j in range(len(df)):

? ? ? ? if (df.isnull())[j]:? # 如果為空即插值。

? ? ? ? ? ? df[j] = lagrange_detail(df, j)

? ? ? ? ? ? df_raw.loc[j, 'PM2.5'] = df[j]

? ? ? ? ? ? # print(j, df.loc[j, 'index'], df[j])

? ? ? ? ? ? full_tuple = df_raw.loc[j, 'index'], df_raw.loc[j, 'PM2.5']

? ? ? ? ? ? full.append(full_tuple)

? ? draw_scatte_diagram(df_raw)

? ? df = pd.DataFrame(full, columns=['index', 'PM2.5'])

? ? df.to_csv('pm25_predicted_lagrange.csv', index=False)

# 計算RMSE

def calculate_RMSE(target, prediction):

? ? error = []

? ? for i in range(len(target)):

? ? ? ? error.append(target[i] - prediction[i])

? ? return (sum([n * n for n in error]) / len(error)) ** 0.5

# 計算MAE

def calculate_MAE(target, prediction):

? ? error = []

? ? for i in range(len(target)):

? ? ? ? error.append(target[i] - prediction[i])

? ? return sum([abs(n) for n in error]) / len(error)

# 計算R-square

def calculate_R_Square(target, prediction):

? ? error = []

? ? a = calculate_MAE(target, prediction) * len(error)

? ? mean = np.mean(np.array(target))

? ? for i in range(len(target)):

? ? ? ? error.append(prediction[i] - mean)

? ? b = sum([n * n for n in error])

? ? return 1 - a / b

if __name__ == '__main__':

? ? # mean_method()

? ? # median_method()

? ? # mode_method()

? ? # ffill_method()

? ? # bfill_method()

? ? # mean_by_before_after_method()

? ? # linear_method()

? ? # lagrange_method()

? ? smooth_method()

2.fbprophet_fill.py

# -*- coding:utf-8 -*-

from pandas.io.sas.sas7bdat import _column

from time_series_fill import smooth_method

__author__ = 'gin.chen'

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

import datetime

from fbprophet import Prophet

if __name__ == '__main__':

? ? def load_data():

? ? ? ? # df = pd.read_csv('F:/muke/super_mali/data/raw/pm25.csv')

? ? ? ? # return df.head(100)

? ? ? ? df = smooth_method(0)

? ? ? ? return df.head(3129)

? ? df = load_data()

? ? first_value = datetime.datetime.strptime('2017-01-01 00:00:00', '%Y-%m-%d %H:%M:%S')

? ? for i in range(len(df)):

? ? ? ? df.iloc[i, 0] = (first_value + datetime.timedelta(hours=i)).strftime("%Y-%m-%d %H:%M:%S")

? ? # df = pd.DataFrame(, columns=['ds', 'y'])

? ? # df.to_csv('pm25_predicted_mean.csv', index=False)

? ? # print(df.iloc[1,0])

? ? df.rename(columns={'index': 'ds', 'PM2.5': 'y'}, inplace=True)

? ? m = Prophet()

? ? # df['y'] = np.log(df['y'])

? ? df = m.fit(df)

? ? future = m.make_future_dataframe(freq='H', periods=5428)

? ? future.tail()

? ? forecast = m.predict(future)

? ? forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()

? ? fig1 = m.plot(forecast)

? ? fig2 = m.plot_components(forecast)

? ? plt.show()

運行結(jié)果圖:


Mean


Median


Ffill_method?


Bfill_method?


Linear_method?


lagrange_method


smooth_method


Fbprophet實現(xiàn)?


日,周,月的趨勢?

未完待續(xù)。。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容