matplotlib:忽略缺失数据在点之间画线

2025-03-14 08:57:00
admin
原创
50
摘要:问题描述:我有一组数据,我想将其绘制成线图。对于每个系列,有些数据缺失(但每个系列都不同)。目前,matplotlib 不会绘制跳过缺失数据的线:例如import matplotlib.pyplot as plt xs = range(8) series1 = [1, 3, 3, None, None, 5...

问题描述:

我有一组数据,我想将其绘制成线图。对于每个系列,有些数据缺失(但每个系列都不同)。目前,matplotlib 不会绘制跳过缺失数据的线:例如

import matplotlib.pyplot as plt

xs = range(8)
series1 = [1, 3, 3, None, None, 5, 8, 9]
series2 = [2, None, 5, None, 4, None, 3, 2]

plt.plot(xs, series1, linestyle='-', marker='o')
plt.plot(xs, series2, linestyle='-', marker='o')

plt.show()

导致绘图中的线条有间隙。我如何告诉 matplotlib 在间隙处画线?(我宁愿不必插入数据)。


解决方案 1:

您可以通过以下方式屏蔽 NaN 值:

import numpy as np
import matplotlib.pyplot as plt

xs = np.arange(8)
series1 = np.array([1, 3, 3, None, None, 5, 8, 9]).astype(np.double)
s1mask = np.isfinite(series1)
series2 = np.array([2, None, 5, None, 4, None, 3, 2]).astype(np.double)
s2mask = np.isfinite(series2)

plt.plot(xs[s1mask], series1[s1mask], linestyle='-', marker='o')
plt.plot(xs[s2mask], series2[s2mask], linestyle='-', marker='o')

plt.show()

这导致

阴谋

解决方案 2:

引用@Rutger Kassies(链接):

Matplotlib 仅在连续(有效)数据点之间画一条线,并在 NaN 值处留下间隙。

如果你使用Pandas,则有一个解决方案:

#pd.Series 
s.dropna().plot() #masking (as @Thorsten Kranz suggestion)

#pd.DataFrame
df['a_col_ffill'] = df['a_col'].ffill()
df['b_col_ffill'] = df['b_col'].ffill()  # changed from a to b
df[['a_col_ffill','b_col_ffill']].plot()

解决方案 3:

使用 pandas 的解决方案:

import matplotlib.pyplot as plt
import pandas as pd

def splitSerToArr(ser):
    return [ser.index, ser.as_matrix()]


xs = range(8)
series1 = [1, 3, 3, None, None, 5, 8, 9]
series2 = [2, None, 5, None, 4, None, 3, 2]

s1 = pd.Series(series1, index=xs)
s2 = pd.Series(series2, index=xs)

plt.plot( *splitSerToArr(s1.dropna()), linestyle='-', marker='o')
plt.plot( *splitSerToArr(s2.dropna()), linestyle='-', marker='o')

plt.show()

在 Pandas 中绘图时,此splitSerToArr函数非常方便。这是输出:在此处输入图片描述

解决方案 4:

如果不使用插值,您需要从数据中删除 None。这也意味着您需要删除系列中与 None 相对应的 X 值。这里有一个(丑陋的)一行代码可以做到这一点:

  x1Clean,series1Clean = zip(* filter( lambda x: x[1] is not None , zip(xs,series1) ))

lambda 函数对 None 值返回 False,从列表中过滤 x,series 对,然后将数据重新压缩回其原始形式。

解决方案 5:

不管怎样,经过反复尝试,我想对 Thorsten 的解决方案做一点澄清。希望这能为尝试过此方法后寻找其他解决方案的用户节省时间。

在使用时我无法成功解决相同的问题

from pyplot import *

并试图密谋

plot(abscissa[mask],ordinate[mask])

似乎需要使用它import matplotlib.pyplot as plt来获得正确的 NaN 处理,尽管我不知道为什么。

解决方案 6:

pandas DataFrames 的另一种解决方案:

plot = df.plot(style='o-') # draw the lines so they appears in the legend
colors = [line.get_color() for line in plot.lines] # get the colors of the markers
df = df.interpolate(limit_area='inside') # interpolate
lines = plot.plot(df.index, df.values) # add more lines (with a new set of colors)
for color, line in zip(colors, lines):
  line.set_color(color) # overwrite the new lines colors with the same colors as the old lines

解决方案 7:

我遇到了同样的问题,但掩码消除了中间的点,并且线无论如何都被切断了(我们在图片中看到的粉红色线条是唯一连续的非 NaN 数据,这就是线条的原因)。以下是屏蔽数据的结果(仍然有间隙):

xs  = df['time'].to_numpy()
series1 = np.array(df['zz'].to_numpy()).astype(np.double)
s1mask = np.isfinite(series1)

fplt.plot(xs[s1mask], series1[s1mask], ax=ax_candle, color='#FF00FF', width = 1, legend='ZZ')

在此处输入图片描述

可能是因为我使用 finplot(绘制蜡烛图),所以我决定用线性公式 y2-y1=m(x2-x1) 来制作缺失的 Y 轴点,然后制定在缺失点之间生成 Y 值的函数。

def fillYLine(y):
    #Line Formula
    fi=0
    first = None
    next = None
    for i in range(0,len(y),1):
        ne = not(isnan(y[i]))
        next = y[i] if ne else next
    
        if not(next is None):
            if not(first is None):
                m = (first-next)/(i-fi) #m = y1 - y2 / x1 - x2
                cant_points = np.abs(i-fi)-1
                if (cant_points)>0:
                    points = createLine(next,first,i,fi,cant_points)#Create the line with the values of the difference to generate the points x that we need    
                    x = 1
                    for p in points:
                        y[fi+x] = p
                        x = x + 1
            first = next
            fi = i
        next = None
    return y

def createLine(y2,y1,x2,x1,cant_points):
    m = (y2-y1)/(x2-x1) #Pendiente
    points = []
    x = x1 + 1#first point to assign
    for i in range(0,cant_points,1):
        y = ((m*(x2-x))-y2)*-1
        points.append(y)
        x = x + 1#The values of the line are numeric we don´t use the time to assign them, but we will do it at the same order
    return points

然后我使用简单的调用函数来填补之间的空白y = fillYLine(y),我的 finplot 就像:

x = df['time'].to_numpy()
y = df['zz'].to_numpy()
y = fillYLine(y)
fplt.plot(x, y, ax=ax_candle, color='#FF00FF', width = 1, legend='ZZ')

在此处输入图片描述

您需要认为 Y 变量中的数据仅用于绘图,我需要操作之间的 NaN 值(或将它们从列表中删除),这就是我从 pandas 数据集创建 Y 变量的原因df['zz']

注意:我注意到在我的例子中数据被消除了,因为如果我不屏蔽 X (xs),值会在图表中向左滑动,在这种情况下它们会变成连续的非 NaN 值,并且会绘制连续的线,但会向左缩小:

fplt.plot(xs, series1[s1mask], ax=ax_candle, color='#FF00FF', width = 1, legend='ZZ') #No xs masking (xs[masking])

在此处输入图片描述

这让我想到,有些人之所以要使用掩模版,是因为他们只是绘制那条线,或者非掩模版数据和掩模版数据之间没有太大区别(间隙很少,不像我的数据有很多间隙)。

解决方案 8:

也许我没抓住重点,但我相信 Pandas 现在会自动执行此操作。下面的示例有点复杂,需要互联网访问,但早年中国的线路有很多空白,因此使用直线段。

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

# read data from Maddison project 
url = 'http://www.ggdc.net/maddison/maddison-project/data/mpd_2013-01.xlsx'
mpd = pd.read_excel(url, skiprows=2, index_col=0, na_values=[' ']) 
mpd.columns = map(str.rstrip, mpd.columns)

# select countries 
countries = ['England/GB/UK', 'USA', 'Japan', 'China', 'India', 'Argentina']
mpd = mpd[countries].dropna()
mpd = mpd.rename(columns={'England/GB/UK': 'UK'})
mpd = np.log(mpd)/np.log(2)  # convert to log2 

# plots
ax = mpd.plot(lw=2)
ax.set_title('GDP per person', fontsize=14, loc='left')
ax.set_ylabel('GDP Per Capita (1990 USD, log2 scale)')
ax.legend(loc='upper left', fontsize=10, handlelength=2, labelspacing=0.15)
fig = ax.get_figure()
fig.show() 
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用