時間序列數據在許多不同的行業中都非常重要。它在研究、金融行業、制藥、社交媒體、網絡服務等領域尤為重要。對時間序列數據的分析也變得越來越重要。在分析中有什么比一些好的可視化效果更好呢?沒有一些視覺效果,任何類型的數據分析都是不完整的。因為一個好的情節比20頁的報告更能讓你理解。因此,本文是關于時間序列數據可視化的。
我將從一些非常簡單的可視化開始,然后慢慢地轉向一些高級的可視化技術和工具
在開始之前,我需要再弄清楚一件事。
標題中的"完整指南"并不意味著,它有所有的可視化。在這么多不同的庫中有這么多的可視化方法,所以在一篇文章中包含所有這些方法是不實際的。
但是本文可以為您提供足夠的工具和技術來清楚地講述一個故事或理解和可視化時間序列數據。 我試圖解釋一些簡單的方法和一些先進的技術。
數據集
如果您正在閱讀本文以進行學習,則最好的方法是自己跟蹤并運行所有代碼。 請隨時從以下鏈接下載數據集:
https://github.com/rashida048/Datasets/blob/master/stock_data.csv
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df = pd.read_csv("stock_data.csv", parse_dates=True, index_col = "Date")
df.head()
我在readcsv函數中使用了" parsedates"參數將"日期"列轉換為DatetimeIndex格式。 在大多數情況下,日期是以字符串格式存儲的,而字符串格式不是用于時間序列數據分析的正確格式。 如果采用DatetimeIndex格式,則將其作為時間序列數據進行處理將非常有幫助。
我們先從基本開始。最基本的圖形應該是使用Pandas的線形圖。我將在這里繪制"Volume"數據。看看它是怎樣的:
df['Volume'].plot()
這是我們的"Volume"數據圖,看起來有些忙碌而有一些大的峰值。 將所有其他列也繪制在一個圖中以同時檢查所有它們的曲線將是一個好主意。
df.plot(subplots=True, figsize=(10,12))
'Open', 'Close', 'High' ,'Low' 數據的曲線形狀具有相同的形狀。 只有"Volume"具有不同的形狀。
我上面使用的折線圖非常適合顯示季節性。 重新采樣數月或數周并繪制條形圖是發現季節性的另一種非常簡單且廣泛使用的方法。 我在這里繪制2016年和2017年月份數據的條形圖。對于指數,我將使用[2016:]。 因為我們的數據集包含直到2017年的數據。所以,2016年末應該帶來2016年和2017年。
df_month = df.resample("M").mean()
fig, ax = plt.subplots(figsize=(10, 6))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
ax.bar(df_month['2016':].index, df_month.loc['2016':, "Volume"], width=25, align='center'
有24個小節。每個條代表一個月。2017年7月大幅飆升。
找到季節性的一種方法是使用一組箱線圖。這里我將為每個月制作箱線圖。我將使用Open', 'Close', 'High' ,'Low'數據來繪制這個圖。。
import seaborn as sns
#start, end = '2016-01', '2016-12'
fig, axes = plt.subplots(4, 1, figsize=(10, 16), sharex=True)
for name, ax in zip(['Open', 'Close', 'High', 'Low'], axes):
sns.boxplot(data = df, x='Month', y=name, ax=ax)
ax.set_ylabel("")
ax.set_title(name)
if ax != axes[-1]:
ax.set_xlabel('')
它清楚地顯示了每月的價值差異。
有更多的方式來顯示季節性。在本文的最后我用另一種方式進行討論。
重采樣和滾動
請記住上面的"Volume"數據的第一行圖。正如我們之前討論過的,這里數據量太大了。它可以通過重采樣來修復。繪制月平均數據將在很大程度上解決這個問題,而不是繪制每日數據。為此,我將使用已經為上面的條形圖和框圖準備的df_month數據集。
df_month['Volume'].plot(figsize=(8, 6))
更容易理解,更清楚!它能讓你更好地了解長期趨勢。
重采樣在時間序列數據中很常見。大多數時候重采樣是在較低的頻率進行。
因此,本文將只處理低頻的重采樣。雖然重新采樣的高頻率也有必要,特別是為了建模的目的。不是為了數據分析。
在我們目前正在研究的"Volume"數據中,我們可以觀察到一些大的峰值。這些類型的尖峰對數據分析或建模沒有幫助。通常平滑尖峰,重新采樣到較低的頻率和滾動是非常有用的。
現在,將日數據和周平均"Volume"畫在同一幅圖上。首先,使用重采樣方法制作每周平均數據集。
df_week = df.resample("W").mean()
這個"dfweek"和"dfmonth"在以后的可視化中也會很有用。
讓我們把每日和每周的數據畫在同一個圖上。
start, end = '2015-01', '2015-08'
fig, ax = plt.subplots()
ax.plot(df.loc[start:end, 'Volume'], marker='.', linestyle='-', linewidth = 0.5, label='Daily', color='black')
ax.plot(df_week.loc[start:end, 'Volume'], marker='o', markersize=8, linestyle='-', label='Weekly', color='coral')
label='Monthly', color='violet')
ax.set_ylabel("Open")
ax.legend()
周平均面積的峰值比日數據要小。
滾動是另一種非常有用的平滑曲線的方法。它取特定數據量的平均值。如果我想要一個7天的滾動,它會給我們7-d的平均數據。
讓我們在上面的圖中包含7-d滾動數據。
df_7d_rolling = df.rolling(7, center=True).mean()
start, end = '2016-06', '2017-05'fig, ax = plt.subplots()
ax.plot(df.loc[start:end, 'Volume'], marker='.', linestyle='-',
linewidth=0.5, label='Daily')
ax.plot(df_week.loc[start:end, 'Volume'], marker='o', markersize=5,
linestyle='-', label = 'Weekly mean volume')
ax.plot(df_7d_rolling.loc[start:end, 'Volume'], marker='.', linestyle='-', label='7d Rolling Average')
ax.set_ylabel('Stock Volume')
ax.legend()
在這個情節中發生了很多事情。但如果你仔細看,還是可以理解的。如果你注意到7-d的滾動平均比周平均平滑一些。
使用30-d或365-d滾動平均也很常見,以使曲線更平滑。
圖表展示變化
很多時候,查看數據如何隨時間變化比查看日常數據更有用。
有幾種不同的方法可以計算和可視化數據的變化。
shift
shift函數在指定的時間之前或之后移動數據。如果我不指定時間,它將轉移數據一天默認。這意味著你將獲得前一天的數據。在像這樣的財務數據中,把前一天的數據和今天的數據放在一起是很有幫助的。
因為這篇文章只專注于可視化,所以我將只繪制前一天的數據:
df['Change'] = df.Close.div(df.Close.shift())
df['Change'].plot(figsize=(20, 8), fontsize = 16)
在上面的代碼中,.div()幫助填充丟失的數據。div()的意思是"除"。df.div(6)將把df中的每個元素除以6。但這里我用的是' df.Close.shift() '因此,df的每個元素將被' df. close .shift() '的每個元素除。這樣做是為了避免' shift() '操作創建的空值。
您可以簡單地指定一個時間段并進行繪圖以使外觀更清晰。 這僅是2017年的情節。
df['2017']['Change'].plot(figsize=(10, 6))
盡管這種轉變在很多方面都很有用。但我發現百分比變化在很多情況下很有用。
變化百分比
我將使用開始計算的月度數據。這次我選擇了條形圖。它清楚地顯示了百分比的變化。有一個百分比更改函數可用來獲取percent_change數據。
df_month.loc[:, 'pct_change'] = df.Close.pct_change()*100
fig, ax = plt.subplots()
df_month['pct_change' ].plot(kind='bar', color='coral', ax=ax)
ax.xaxis.set_major_locator(mdates.WeekdayLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %d'))
plt.xticks(rotation=45)
ax.legend()
我在這里畫出了封閉數據的變化百分比。這里用的是月變化百分比。
差分
差分取指定距離值的差值。默認情況下,是1。如果像"df.High.diff(2)"那樣指定2,它將取'High'列的第一個和第三個元素、第二個和第四個元素的差值,依此類推。
在數據中去除趨勢是一種流行的方法。這種趨勢不利于預測或建模。
df.High.diff().plot(figsize=(10, 6))
擴展窗口
另一種轉變方式。它不斷增加累積。例如,如果向' High '列元素添加展開函數,則第一項元素保持不變。第二個元素成為第一個和第二個元素的累積,第三個元素成為第一個、第二個和第三個元素的累積,以此類推。你也可以在上面使用聚合函數,比如平均值、中位數、標準差等等。
這樣,它就能提供隨時間變化的均值、中位數、和或標準差。它對財務數據、業務銷售或利潤數據不是很有用嗎?
fig, ax = plt.subplots()
ax = df.High.plot(label='High')
ax = df.High.expanding().mean().plot(label='High expanding mean')
ax = df.High.expanding().std().plot(label='High expanding std')
ax.legend()
這里我加了均值和標準差。看看每天的數據和平均值。在2017年底,每日數據顯示一個巨大的高峰。但它并沒有顯示平均值的峰值。如果只看2017年的數據,不斷擴大的平均水平可能會有所不同。
熱點圖
熱點圖通常是一種隨處使用的常見數據可視化類型。在時間序列數據中,熱點圖也是非常有用的。
但是在深入研究熱點圖之前,我們需要開發一個日歷來表示我們數據集的年和月數據。讓我們看一個例子。
在這個演示中,我將導入一個日歷包并使用pivot表函數來生成值。
import calendar
all_month_year_df = pd.pivot_table(df, values="Open",
index=["month"],
columns=["year"],
fill_value=0,
margins=True)
named_index = [[calendar.month_abbr[i] if isinstance(i, int) else i for i in list(all_month_year_df.index)]] # name months
all_month_year_df = all_month_year_df.set_index(named_index)
all_month_year_df
日歷已經準備好了每月平均"Open"數據。現在,用它生成熱點圖。
ax = sns.heatmap(all_month_year_df, cmap='RdYlGn_r', robust=True, fmt='.2f',
annot=True, linewidths=.5, annot_kws={'size':11},
cbar_kws={'shrink':.8, 'label':'Open'})
ax.set_yticklabels(ax.get_yticklabels(), rotation=0, fontsize=10)
ax.set_xticklabels(ax.get_xticklabels(), rotation=0, fontsize=10)
plt.title('Average Opening', fontdict={'fontsize':18}, pad=14);
深紅色意味著非常高的數值,深綠色意味著非常低的數值。
分解圖
分解將在同一個圖中顯示觀察結果和這三個元素:
趨勢:時間序列一致的向上或向下的斜率。
季節性:時間序列的明確周期模式
噪聲:異常值或缺失值
使用stats模型庫,很容易做到:
from pylab import rcParams
import statsmodels.api as sm
rcParams['figure.figsize'] = 11, 9
decomposition = sm.tsa.seasonal_decompose(df_month['Volume'], model='Additive')
fig = decomposition.plot()
plt.show()
趨勢是移動平均線。為了讓對最后一行的殘差有一個高層次的概念,下面是一般公式:
原始觀測值=趨勢+季節性+殘差
盡管關于分解的文檔本身說它是一種非常簡單的表示,但它仍然很流行。
總結
如果你能運行上面所有的代碼,恭喜你!今天,您已經學習了足夠多的時間序列數據可視化。正如我在開始時提到的,有很多很酷的可視化技術可用。
作者:Rashida Nasrin Sucky
deephub翻譯組