fill_between不适用于Windows

时间:2017-08-07 05:57:35

标签: python matplotlib fill between

我是Python编程的新手。 所以,我试图通过一本名为“Python Crash Course'”的书来学习Python。 但是当我在matplotlib中使用fill_between方法时出现了问题。这是我的代码。

import csv
from datetime import datetime

from matplotlib import pyplot as plt


# Read min, max temperatures from the file
filename = 'sitka_weather_2014.csv'
with open(filename) as f:
    reader = csv.reader(f)
    header_row = next(reader)

    dates, highs, lows = [], [], []
    for row in reader:
        current_date = datetime.strptime(row[0], "%Y-%m-%d")
        dates.append(current_date)

        high = int(row[1])
        highs.append(row[1])

        low = int(row[3])
        lows.append(low)

# plotting the data
fig = plt.figure(dpi=128, figsize=(12, 6))
plt.plot(dates, highs, c='red', alpha=0.5)
plt.plot(dates, lows, c='blue', alpha=0.5)
plt.fill_between(dates, highs, lows, facecolor='blue', alpha=0.1)

# deciding graph format
plt.title("Daily high and low temperature - 2014", fontsize=24)
plt.xlabel('Numbers', fontsize=14)
fig.autofmt_xdate()
plt.ylabel("Temperature (F)", fontsize=16)
plt.tick_params(axis='both', which='major', labelsize=16)

plt.show()

上面的代码试图绘制温度数据。 当我试图运行代码时,pyCharm给了我这个Traceback。

Traceback (most recent call last):
  File "C:/pyCharm(sang)/highs_lows.py", line 28, in <module>
    plt.fill_between(dates, highs, lows, facecolor='blue', alpha=0.1)
  File "C:\Users\John Jung\AppData\Roaming\Python\Python36\site-packages\matplotlib\pyplot.py", line 3000, in fill_between
    **kwargs)
  File "C:\Users\John Jung\AppData\Roaming\Python\Python36\site-packages\matplotlib\__init__.py", line 1898, in inner
    return func(ax, *args, **kwargs)
  File "C:\Users\John Jung\AppData\Roaming\Python\Python36\site-packages\matplotlib\axes\_axes.py", line 4779, in fill_between
    y1 = ma.masked_invalid(self.convert_yunits(y1))
  File "C:\Users\John Jung\AppData\Roaming\Python\Python36\site-packages\numpy\ma\core.py", line 2388, in masked_invalid
    condition = ~(np.isfinite(a))
TypeError: ufunc 'isfinite' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

现在我在Windows10上使用PyCharm,所以它不起作用。 但我昨晚在我的Mac上运行了完全相同的代码,它确实有效 像魔术一样。为什么这不适用于Windows但Mac? 什么是fill_between的问题?

先谢谢你们!

更新: 这是sitka_weather_2014.csv

的示例代码
 AKST,Max TemperatureF,Mean TemperatureF,Min TemperatureF,Max Dew PointF,MeanDew PointF,Min DewpointF,Max Humidity, Mean Humidity, Min Humidity, Max Sea Level PressureIn, Mean Sea Level PressureIn, Min Sea Level PressureIn, Max VisibilityMiles, Mean VisibilityMiles, Min VisibilityMiles, Max Wind SpeedMPH, Mean Wind SpeedMPH, Max Gust SpeedMPH,PrecipitationIn, CloudCover, Events, WindDirDegrees
2014-1-1,46,42,37,40,38,36,97,86,76,29.95,29.77,29.57,10,8,2,25,14,36,0.69,8,Rain,138
2014-1-2,41,38,35,38,35,32,97,89,76,30.09,29.90,29.81,10,9,4,14,7,22,0.34,8,Rain,92
2014-1-3,39,36,34,38,36,33,100,97,93,30.43,30.32,30.10,10,9,2,8,3,,0.02,7,Rain,102
2014-1-4,43,38,34,35,33,31,97,82,62,30.43,30.32,30.20,10,10,10,20,6,25,0.00,6,Rain,107
2014-1-5,44,42,41,42,36,32,97,77,63,30.20,30.02,29.88,10,8,2,26,17,36,0.37,8,Rain,113

2 个答案:

答案 0 :(得分:0)

就像我在评论中“害怕”一样。 Numpy的isinfinite不支持对象。因此,您必须使用MJD(或任何您认为合适的纯数字日期格式)进行绘图,并使用刻度格式化程序使其看起来像普通日期。

你可以通过

来做到这一点
numdates = []
for date in dates:
     numdates.append(date.toordinal())

numdates = matplotlib.dates.date2num(dates)

然后你可以轻松做到

plt.plot(numdates, highs, c="red")  
plt.plot(numdates, lows, c="blue")    
plt.fill_between(numdates, high, lows, facecolor="blue", alpha=0.1)
plt.show()

当然现在您会注意到您的x轴不是易于阅读的格式。相反,它是一个代表自1970年以来的秒数的大数字或者那些线下的东西。

对于那种并不总是有效的解决方法是使用plot_date,如下所示:

plt.plot_date(dates, highs, c="red", ls="-")  
plt.plot_date(dates, lows, c="blue", ls="-")    
plt.fill_between(numdates, high, lows, facecolor="blue", alpha=0.1)
plt.show()

注意我明确声明了linestyle lsplot_date,因为plot_date实际上是点的散点图。另请注意dates如何使用plot_datenumdates使用fill_between,情节仍有效。这是因为plot_dates只是尝试在后台为您猜测DateFormatter,但实际数字与顶部示例相同。

不幸的是,plot_date的格式有时会有点偏差。在这种情况下,我建议你自己勇敢地DateFormatter,这并不是那么糟糕。如果您想隐藏为日期绘制的圆圈,只是让该线条可见,您可以在marker=","命令中添加plot_date。这只是为散点绘制一个像素,因此它被线隐藏,请参阅更多here。另请参阅plot_date func的其他选项。 here

至于为什么这种情况有时只会发生 - 9/10的机会与numpy和python版本有关。这将弹出numpy 1.12.1,matplotlib 2.0.2和Python 3.6。我怀疑它也会发生在旧版本的Python版本(即2.7)中,并且对于某些版本的numpy / matplotlib来说,它不会发生。所有这些当然都是猜测。就“为什么”而言 - 我认为这是关于numpy的一个很好的决定,但是应该重新设计matplotlib以将其隐藏起来。如果您愿意,可以尝试在git上ping它们以查看它们对此有何看法。如果你不想这么说 - 我很有兴趣看到原因。

答案 1 :(得分:0)

此处的错误消息并不能确定根本问题。问题出在从csv文件中提取数据的代码中。这是该代码的相关部分:

dates, highs, lows = [], [], []
for row in reader:
    current_date = datetime.strptime(row[0], "%Y-%m-%d")
    dates.append(current_date)

    high = int(row[1])
    highs.append(row[1])

    low = int(row[3])
    lows.append(low)

从csv文件中读取数据时,它最终会以字符串形式读入。对于我们将要使用的每个数据,我们需要将其转换为适当的数据类型以进行绘图。因此,日期将转换为datetime对象,并且每个温度都会转换为int。在您的代码中,您已将高温转换为int,但您还没有使用该int。这一行:

highs.append(row[1])

应更改为:

highs.append(high)

如果您进行此更改,我认为您将看到正确的可视化。我想知道isinfinite()是否拒绝字符串数据?

注意:我是Python Crash Course的作者,我试着留意这样的帖子。我真的很想知道这些项目将继续为人们服务,如果它们变得过时就更新它们。