簡體   English   中英

Python Matplotlib - 帶有日期值的 x 軸平滑 plot 線

[英]Python Matplotlib - Smooth plot line for x-axis with date values

我試圖平滑圖形線,但由於 x 軸值是日期,我在執行此操作時遇到了很大的麻煩。 假設我們有一個 dataframe 如下

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
%matplotlib inline

startDate = '2015-05-15'
endDate = '2015-12-5'
index = pd.date_range(startDate, endDate)
data = np.random.normal(0, 1, size=len(index))
cols = ['value']

df = pd.DataFrame(data, index=index, columns=cols)

然后我們plot這個數據

fig, axs = plt.subplots(1,1, figsize=(18,5))
x = df.index
y = df.value
axs.plot(x, y)
fig.show()

我們得到

在此處輸入圖像描述

現在為了平滑這條線,有一些有用的 staekoverflow 問題已經准備就緒,例如:

但是我似乎無法獲得一些代碼來為我的示例執行此操作,有什么建議嗎?

您可以使用pandas附帶的插值功能。 因為您的數據框已經為每個索引提供了一個值,所以您可以使用更稀疏的索引填充它,並用NaN值填充每個以前不存在的索引。 然后,在選擇了許多可用的插值方法之一后,對數據進行插值和繪圖:

index_hourly = pd.date_range(startDate, endDate, freq='1H')
df_smooth = df.reindex(index=index_hourly).interpolate('cubic')
df_smooth = df_smooth.rename(columns={'value':'smooth'})

df_smooth.plot(ax=axs, alpha=0.7)
df.plot(ax=axs, alpha=0.7)
fig.show()

在此處輸入圖片說明

有一種解決方法,我們將創建兩個圖 - 1) 非平滑/使用日期標簽進行插值 2) 不使用日期標簽進行平滑。

使用參數linestyle=" "繪制1)並將要繪制在 x 軸上的日期轉換為字符串類型。

使用參數linestyle="-"繪制2)並分別使用np.linespacemake_interp_spline插入 x 軸和 y 軸。

以下是針對您的代碼使用所討論的解決方法。

# your initial code
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from scipy.interpolate import make_interp_spline
%matplotlib inline
startDate = "2015-05-15"
endDate = "2015-07-5" #reduced the end date so smoothness is clearly seen
index = pd.date_range(startDate, endDate)
data = np.random.normal(0, 1, size=len(index))
cols = ["value"]

df = pd.DataFrame(data, index=index, columns=cols)
fig, axs = plt.subplots(1, 1, figsize=(40, 12))
x = df.index
y = df.value

# workaround by creating linespace for length of your x axis
x_new = np.linspace(0, len(df.index), 300)
a_BSpline = make_interp_spline(
    [i for i in range(0, len(df.index))],
    df.value,
    k=5,
)
y_new = a_BSpline(x_new)

# plot this new plot with linestyle = "-"
axs.plot(
    x_new[:-5], # removing last 5 entries to remove noise, because interpolation outputs large values at the end.
    y_new[:-5],
    "-",
    label="interpolated"
)

# to get the date on x axis we will keep our previous plot but linestyle will be None so it won't be visible
x = list(x.astype(str))
axs.plot(x, y, linestyle=" ", alpha=0.75, label="initial")
xt = [x[i] for i in range(0,len(x),5)]
plt.xticks(xt,rotation="vertical")
plt.legend()
fig.show()

結果圖情節

Overalpped 圖以查看平滑。 情節

根據“平滑”的確切含義,最簡單的方法是使用savgol_filter或類似的東西。 與插值樣條不同,此方法意味着平滑線不會通過測量點,從而有效濾除高頻噪聲。

from scipy.signal import savgol_filter

...
windowSize = 21
polyOrder = 1
smoothed = savgol_filter(values, windowSize, polyOrder)
axes.plot(datetimes, smoothed, color=chart.color)

多項式階數越高,平滑后的線越接近原始數據。

這是一個例子。 原始數據和平滑數據的比較圖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM