用Matplotlib填充行之间的空白区域

3
我正在编写一份Python程序,该程序会将 .csv 文件中的数据以财务价值与日期(格式为月-日-年)的关系进行绘图。其中,一行表示财务价值的上限估计,另一行表示下限估计,第三行则表示平均估计。我想将上限和下限估计之间的区域用红色填充,并覆盖一条表示平均值的黑线。我可以将每个数据集绘制成一条线,但由于某种原因,它不允许我使用红色填充上限和下限边界之间的空间。下面的图表显示了几何形状的情况,我试图填充红线之间的空间。当我使用 fill_between 命令运行代码时,会收到“condition = ~(np.isfinite(a))”消息。有人能发现我的问题在哪里吗?我通过添加一个月的数据点来更好地理解机制或缺陷,整个代码如下所示:
#!/usr/bin/python
import csv
import sys
import datetime
from pylab import *
from matplotlib.ticker import MaxNLocator

date      = []
Median    = []
Upper     = []
Lower     = []

inp           = open('Checking.csv','rt')
try:
    reader = csv.reader(inp)
    for row in reader:
        Init_Date = row[0]
        if(Init_Date[0:3] == 'Jan'):   Month = 1
        elif(Init_Date[0:3] == 'Feb'): Month = 2
        elif(Init_Date[0:3] == 'Mar'): Month = 3
        elif(Init_Date[0:3] == 'Apr'): Month = 4
        elif(Init_Date[0:3] == 'May'): Month = 5
        elif(Init_Date[0:3] == 'Jun'): Month = 6
        elif(Init_Date[0:3] == 'Jul'): Month = 7
        elif(Init_Date[0:3] == 'Aug'): Month = 8
        elif(Init_Date[0:3] == 'Sep'): Month = 9
        elif(Init_Date[0:3] == 'Oct'): Month = 10
        elif(Init_Date[0:3] == 'Nov'): Month = 11
        else: Month = 12

        day  = Init_Date[4:6]
        year = Init_Date[-3:-1]

        Median.append(row[1])
        Upper.append(row[2])
        Lower.append(row[3])
        dates = str(Month) + '/' + str(day).strip() + '/' + str(year)
        date.append(datetime.datetime.strptime(dates,'%m/%d/%y'))
finally:
    inp.close()

fig, plt = plt.subplots()
matplotlib.rc('xtick',labelsize=18)
matplotlib.rc('ytick',labelsize=18)
x = date
y = Median
y1 = Upper
y2 = Lower
plt.set_xlabel(r'$Date$',fontsize = 18)
plt.set_ylabel(r'$Y-Value$',fontsize = 18)
plt.plot(x, y1, color = 'red')
plt.plot(x, y2, color = 'red')
plt.fill_between(x,y2,y1,interpolate=True,color='red')
plt.plot(x, y, color = 'black')
plt.xaxis.set_major_locator(MaxNLocator(nbins = 12))
fig.savefig("Test.png")

测试数据

Mar 2 2014  18339.1     18734.15    17944.05
Mar 3 2014  18280.33    18675.39    17885.26
Mar 4 2014  18220.61    18614.84    17826.39
Mar 5 2014  18160.77    18552.15    17769.39
Mar 6 2014  18100.92    18493.55    17708.28
Mar 7 2014  18042.18    18431.77    17652.59
Mar 8 2014  17983.51    18371.31    17595.71
Mar 9 2014  17577.67    17959.34    17196
Mar 10 2014 17517.87    17898.33    17137.42
Mar 11 2014 15956.97    16309.96    15603.98
Mar 12 2014 15403.36    15746.7     15060.03
Mar 13 2014 15344.04    15684.44    15003.65
Mar 14 2014 20731.34    21171.47    20291.2
Mar 15 2014 22986.67    23469.15    22504.18
Mar 16 2014 22926.7     23408.98    22444.42
Mar 17 2014 22867.46    23348.73    22386.19
Mar 18 2014 22541.08    23015.78    22066.39
Mar 19 2014 22481.86    22955.47    22008.25
Mar 20 2014 22420.94    22895.56    21946.32
Mar 21 2014 22361.48    22832.68    21890.28
Mar 22 2014 22301.09    22771.64    21830.53
Mar 23 2014 21972.47    22435.43    21509.52
Mar 24 2014 21913.41    22376.04    21450.77
Mar 25 2014 21251.91    21701.94    20801.88
Mar 26 2014 21192.85    21642.57    20743.12
Mar 27 2014 21133.16    21582       20684.31
Mar 28 2014 21074.7     21521.39    20628.01
Mar 29 2014 21014.04    21461.03    20567.05
Mar 30 2014 24122.28    24627.21    23617.35
Mar 31 2014 24063.07    24566.59    23559.55

你能添加一些测试样例吗?另外,“Median”、“Upper”和“Lower”是什么意思? - ljetibo
2个回答

3

这个错误是由于传递给fill_between的数据类型为string引起的。如果在绘图之前打印yy1y2变量,您可以看到问题所在:

>>> print(y)
['18339.1', '18280.33', '18220.61', '18160.77', '18100.92', '18042.18', '17983.51', '17577.67', '17517.87', '15956.97', '15403.36', '15344.04', '20731.34', '22986.67', '22926.7', '22867.46', '22541.08', '22481.86', '22420.94', '22361.48', '22301.09', '21972.47', '21913.41', '21251.91', '21192.85', '21133.16', '21074.7', '21014.04', '24122.28', '24063.07']

>>> print(y1)
['18734.15', '18675.39', '18614.84', '18552.15', '18493.55', '18431.77', '18371.31', '17959.34', '17898.33', '16309.96', '15746.7', '15684.44', '21171.47', '23469.15', '23408.98', '23348.73', '23015.78', '22955.47', '22895.56', '22832.68', '22771.64', '22435.43', '22376.04', '21701.94', '21642.57', '21582', '21521.39', '21461.03', '24627.21', '24566.59']

>>> print(y2)
['17944.05', '17885.26', '17826.39', '17769.39', '17708.28', '17652.59', '17595.71', '17196', '17137.42', '15603.98', '15060.03', '15003.65', '20291.2', '22504.18', '22444.42', '22386.19', '22066.39', '22008.25', '21946.32', '21890.28', '21830.53', '21509.52', '21450.77', '20801.88', '20743.12', '20684.31', '20628.01', '20567.05', '23617.35', '23559.55']

解决方法是在绘图之前将它们转换为数字类型(例如float)。最简单的地方是在构建列表的时候进行转换:
Median.append( float(row[1]) )
Upper.append( float(row[2]) )
Lower.append( float(row[3]) )

现在,fill_between将按预期工作,您的脚本将生成以下绘图:使用浮点值的有效输出图

下班后我会尝试在我的个人电脑上运行这段代码。然而,我理解你所描述的问题,并且这是关于matplotlib的一个有价值的教训。 - Jon

2

我想知道这是否与您的数据有关。fill_between可能无法处理复杂的数据。您的代码对于我使用不同的数据有效(我稍微修整了一下):

x = [1,2,3,4]
y1 = [1,2,3,4]
y2 = [2,3,4,5]
y = [1.5,2.5,3.5,4.5]
plt.plot(x, y1, color = 'red')
plt.plot(x, y2, color = 'red')
plt.fill_between(x,y2,y1,interpolate=True,color='red')
plt.plot(x, y, color = 'black')
plt.show()

结果如预期。不错的技巧。我从未见过fill_between函数。不要放弃希望。我相信有人会有解决方法。

编辑:

在我的简单数据中尝试您所有的代码也可以工作。我不明白为什么它对您不起作用,但除了坏数据外,一些需要检查的事情可能是matplotlib是否最新以及您的后端是否设置正确。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接