使用matplotlib填充行之间的空间

时间:2015-02-21 03:14:53

标签: python matplotlib

我正在编写一个python程序,它将.csv文件中的数据绘制为财务价值,而日期则采用月 - 日 - 年的格式。一行代表财务价值的上限估计,另一行代表较低的估计,第三行代表平均估计。我试图让图表用红色填充上下估计值之间的区域,并覆盖表示平均值的黑线。我可以将每个数据集绘制为一条线,但由于某种原因,它不会让我用红色填充上限和下限之间的空间。下图显示了几何图形,我正在尝试填充红线之间的空间。当我使用fill_between命令运行代码时,我收到消息" condition =〜(np.isfinite(a))。任何人都可以发现我的问题所在。我正在从.csv文件和整个代码中添加一个月的数据点,以便更好地理解机制或缺乏机制。

enter image description here

#!/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

2 个答案:

答案 0 :(得分:2)

错误是由传递给fill_between string类型的数据引起的。如果您在情节之前print 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将按预期工作,您的脚本将生成以下图表: Working output plot, using float values

答案 1 :(得分:1)

我想知道它是否与您的数据有关。 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是最新的并且你的后端设置得当,那么有些事情可能需要检查。