有条件地在matplotlib中绘制连接线

时间:2013-04-17 10:51:57

标签: python matplotlib

我想在笛卡尔图上绘制风向测量值,其中X轴为时间,Y轴为方向。因为当从359移动到0度时方向包裹,所以绘制连接359到0的线是不合适的。

如果较短的跳跃没有包裹,是否可以条件地绘制连接线?这是一系列带有连接线的值:

10-15-30-90-150-290-350 40-50-20 310-250-150

我假设我会使用类似下面的公式来确定A和B之间是否应该有一条线:

max(A,B) - min(A,B) <= 180

2 个答案:

答案 0 :(得分:3)

在撰写问题时,我提出了一种工作方法:只需添加一个None值即表示数据不连续且线条已断开。

为了使它完美,我在我的范围之外添加了点数,这样线条就会让图形位于顶部并从底部出来。

这是通过添加相关数据点的简单生成器完成的:

def break_degree_wrap(values):
    values1, values2 = itertools.tee(values)

    # Yield the first value
    yield next(values2)

    for (prev_datetime, prev_val), (datetime, val) in itertools.izip(values1, values2):

        # If the data wraps over the top
        if val > prev_val and val - prev_val > 180:
            yield (datetime, val - 360)
            yield (datetime, None)
            yield (prev_datetime, prev_val + 360)

        # If the data wraps under the bottom
        elif val < prev_val and prev_val - val > 180:
            yield (datetime, val + 360)
            yield (datetime, None)
            yield (prev_datetime, prev_val - 360)

        # Add each original value
        yield (datetime, val)

这可以很容易地推广到接受有效范围,而不是硬编码(0,360)。

这是它的外观(原谅可怜的轴:-) Wind direction

答案 1 :(得分:3)

我总是使用np.diff()函数来获得更大于180度的点并插入一个蒙版元素。主要的缺点是你还必须为绘图保留一个“索引”。

所以:

a = np.array([10,15,30,90,150,290,350,40,50,20,310,250,150])
idx = np.arange(len(a))

b = np.diff(a)
mask = np.where(np.abs(b) >= 180)[0]+1

c = np.ma.masked_equal(np.insert(a, mask, -1), -1)
idx = np.ma.masked_equal(np.insert(idx, mask, -1), -1)

fig, ax = plt.subplots(figsize=(10,3))

ax.plot(idx, c)
ax.set_xticks(idx)
ax.set_ylim(0,360)

enter image description here

这不会插入范围之外的值,但我想可以添加。您可以插入2个元素,而不是1个蒙版元素,再次插入图形中的“out”和“in”。

另请注意,180度的阈值只是一个假设,除非您实际测量风,否则您实际上并不知道风是支持还是转向。