【问题标题】:Why does matplotlib extrapolate/plot missing values?为什么 matplotlib 推断/绘制缺失值?
【发布时间】:2016-11-05 19:46:42
【问题描述】:

我有一种情况,有时整个系列的数据都不可用。我正在实时绘制来自传感器的值,这些值可以通过用户交互打开和关闭,因此我不能确定这些值总是在一个系列中。用户可以启动传感器,然后将其关闭然后再次打开,但在这种情况下,matplotlib 从最后一个端点和新起点绘制一条线。

我绘制的数据如下:

[[  5.          22.57011604]
 [  6.          22.57408142]
 [  7.          22.56350136]
 [  8.          22.56394005]
 [  9.          22.56790352]
 [ 10.          22.56451225]
 [ 11.          22.56481743]
 [ 12.          22.55789757]
  #Missing x vals. Still plots straight line..
 [ 29.          22.55654716]
 [ 29.          22.56066513]
 [ 30.          22.56110382]
 [ 31.          22.55050468]
 [ 32.          22.56550789]
 [ 33.          22.56213379]
 [ 34.          22.5588932 ]
 [ 35.          22.54829407]
 [ 35.          22.56697655]
 [ 36.          22.56005478]
 [ 37.          22.5568161 ]
 [ 38.          22.54621696]
 [ 39.          22.55033493]
 [ 40.          22.55079269]
 [ 41.          22.55475616]
 [ 41.          22.54783821]
 [ 42.          22.55195618]]

我的绘图函数看起来很简单,如下所示:

def plot(self, data)
    for name, xy_dict in data.iteritems():
        x_vals = xy_dict['x_values']
        y_vals = xy_dict['y_values']
        line_to_plot = xy_dict['line_number']
        self.lines[line_to_plot].set_xdata(x_vals)
        self.lines[line_to_plot].set_ydata(y_vals)

有人知道为什么会这样吗?并且在绘图时我是否必须处理非序列 x 和 y 值?似乎 matplotlib 应该自己处理这个问题。否则我必须将列表拆分为更小的列表并绘制这些?

【问题讨论】:

    标签: python matplotlib plot


    【解决方案1】:

    Matplotlib 将用线连接所有连续的数据点。

    如果您想避免这种情况,您可以在缺失的 x 值处拆分数据,并分别绘制两个拆分后的列表。

    【讨论】:

    • 我还能像以前一样设置 x 和 y 数据还是需要在新行上绘制它们? (那不是很好,因为它们会改变颜色等)。如果数据点在同一 matplotlib 行上,我会更喜欢
    【解决方案2】:

    一种选择是在缺少数据的地方添加虚拟项目(在您的情况下,显然当x 变化超过 1 时),并将它们设置为屏蔽元素。这样 matplotlib 会跳过线段。例如:

    import numpy as np
    import matplotlib.pylab as pl
    
    # Your data, with some additional elements deleted...
    data = np.array(
    [[  5., 22.57011604],
     [  6., 22.57408142],
     [  9., 22.56790352],
     [ 10., 22.56451225],
     [ 11., 22.56481743],
     [ 12., 22.55789757],
     [ 29., 22.55654716],
     [ 33., 22.56213379],
     [ 34., 22.5588932 ],
     [ 35., 22.54829407],
     [ 40., 22.55079269],
     [ 41., 22.55475616],
     [ 41., 22.54783821],
     [ 42., 22.55195618]])
    
    x = data[:,0]
    y = data[:,1]
    
    # Difference from element to element in x
    dx = x[1:]-x[:-1]
    
    # Wherever dx > 1, insert a dummy item equal to -1
    x2 = np.insert(x, np.where(dx>1)[0]+1, -1)
    y2 = np.insert(y, np.where(dx>1)[0]+1, -1)
    
    # As discussed in the comments, another option is to use e.g.:
    #x2 = np.insert(x, np.where(dx>1)[0]+1, np.nan)
    #y2 = np.insert(y, np.where(dx>1)[0]+1, np.nan)
    # and skip the masking step below.
    
    # Mask elements which are -1
    x2 = np.ma.masked_where(x2 == -1, x2)
    y2 = np.ma.masked_where(y2 == -1, y2)
    
    pl.figure()
    pl.subplot(121)
    pl.plot(x,y)
    pl.subplot(122)
    pl.plot(x2,y2)
    

    【讨论】:

    • 真不错!谢谢你的提示。我目前正在考虑使用 np.nan 来中断一条线,这显然有效。我会先尝试,然后再尝试。
    • 屏蔽似乎相对较慢,例如在具有随机数的数组上,np.ma.masked_where(x<0, x) 的速度大约是 x[x<0]=np.nan 的 5 倍,对于较大的 x
    • 我无法重现,但鉴于此:stackoverflow.com/questions/12708807/numpy-integer-nan 答案,您的x2 数组似乎被解释为整数数组。你可以试试x2.astype(np.float64)
    • 是的,我的解决方案需要 numpy 数组,因此如果您从 Python 列表开始,则需要先进行转换(您可以在其中传递 dtype 关键字,例如 @987654333 @)
    • 啊,真不错。试过了,它应该像它一样工作。非常感谢您的回答!
    【解决方案3】:

    另一种选择是将Nonenumpy.nan 作为y 的值。

    例如,这显示了断开的线路:

    import matplotlib.pyplot as plt
    plt.plot([1,2,3,4,5],[5,6,None,7,8])
    

    【讨论】:

    • 也发现了这一点。我目前正在尝试合并@Bart 的答案以使用 np.nan,但遇到了一些错误。问候!
    猜你喜欢
    • 2011-05-16
    • 1970-01-01
    • 2018-06-01
    • 2018-01-11
    • 2014-06-09
    • 1970-01-01
    • 2018-05-01
    • 2020-11-09
    • 1970-01-01
    相关资源
    最近更新 更多