【问题标题】:Python Matplotlib - Smooth plot line for x-axis with date valuesPython Matplotlib - 具有日期值的 x 轴平滑绘图线
【发布时间】:2017-03-26 09:24:20
【问题描述】:

我正在尝试平滑图形线,但由于 x 轴值是日期,因此我很难做到这一点。假设我们有一个如下的数据框

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)

然后我们绘制数据

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

我们得到

现在为了平滑这条线,已经有一些有用的 staekoverflow 问题,例如:

但是对于我的示例,我似乎无法获得一些代码来执行此操作,有什么建议吗?

【问题讨论】:

    标签: python date pandas matplotlib smooth


    【解决方案1】:

    您可以使用pandas 附带的插值功能。因为您的数据框已经为每个索引都有一个值,所以您可以使用更稀疏的索引填充它,并用 NaN 值填充每个以前不存在的索引。然后,在许多插值methods available 中选择一个后,插值​​并绘制您的数据:

    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()
    

    【讨论】:

      【解决方案2】:

      有一种解决方法,我们将创建两个图 - 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()
      
      

      结果图

      重叠绘图以查看平滑。

      【讨论】:

        猜你喜欢
        • 2020-06-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-26
        相关资源
        最近更新 更多