“ValueError: year is out of range” when attempting to use matplotlib pyplot

筅森魡賤 提交于 2020-05-30 03:38:05

问题


I am attempting to get a matplotlib plotting function to be able to produce a graph with the x-axis set as a time axis. However, when I attempt to plot some values against UNIX times, I encounter the error ValueError: year is out of range. What is going wrong and how can it be addressed?

import os
import time

import matplotlib.dates
import matplotlib.pyplot
import shijian

def main():

    data = [
        [1484611200.0, 844.4333],
        [1484524800.0, 783.3373],
        [1484438400.0, 774.194 ],
        [1484352000.0, 769.2299]
    ]

    save_graph_matplotlib(
        values       = data,
        line         = True,
        line_width   = 0.5,
        title_axis_x = "time",
        title_axis_y = "value",
        #time_axis_x = True
    )

def save_graph_matplotlib(
    values              = None,
    title               = None,
    title_axis_x        = None,
    title_axis_y        = None,
    filename            = None,
    directory           = ".",
    overwrite           = True,
    color               = "black",
    LaTeX               = False,
    markers             = True,
    marker_size         = 1,
    aspect              = None,
    line                = False,
    line_style          = "-",
    line_width          = 0.2,
    font_size           = 20,
    scientific_notation = False,
    time_axis_x         = False
    ):

    # 1D or 2D data
    if isinstance(values[0], list):
        x = [element[0] for element in values]
        y = [element[1] for element in values]
    else:
        x = range(0, len(values))
        y = values

    matplotlib.pyplot.ioff()
    if LaTeX is True:
        matplotlib.pyplot.rc("text", usetex = True)
        matplotlib.pyplot.rc("font", family = "serif")
    if filename is None:
        if title is None:
            filename = "graph.png"
        else:
            filename = shijian.propose_filename(
                filename  = title + ".png",
                overwrite = overwrite
            )
    else:
        filename = shijian.propose_filename(
            filename  = filename,
            overwrite = overwrite
        )

    figure = matplotlib.pyplot.figure()

    if title is not None:
        figure.suptitle(
            title,
            fontsize = font_size
        )
    if markers is True:
        matplotlib.pyplot.scatter(
            x,
            y,
            s          = marker_size,
            c          = color,
            edgecolors = "none",
        )
    if line is True:
        matplotlib.pyplot.plot(
            x,
            y,
            line_style,
            c          = color,
            linewidth  = line_width
        )

    # Turn on or off axes scientific notation.
    if scientific_notation is False:
        matplotlib.pyplot.gca().get_xaxis().\
            get_major_formatter().set_scientific(False)
        matplotlib.pyplot.gca().get_yaxis().\
            get_major_formatter().set_scientific(False)
    # Set axes titles.
    if title_axis_x is not None:
        matplotlib.pyplot.xlabel(title_axis_x, fontsize = font_size)
    if title_axis_y is not None:
        matplotlib.pyplot.ylabel(title_axis_y, fontsize = font_size)
    # Set axes font size.
    matplotlib.pyplot.xticks(fontsize = font_size)
    matplotlib.pyplot.yticks(fontsize = font_size)
    # Set or do not set axis x as time.
    if time_axis_x:
        time_formatter = matplotlib.dates.DateFormatter("%Y-%m-%d")
        matplotlib.pyplot.axes().xaxis_date()
        matplotlib.pyplot.axes().xaxis.set_major_formatter(time_formatter)
        matplotlib.pyplot.xticks(rotation = -90)
    # Set the aspect ratio.
    if aspect is None:
        matplotlib.pyplot.axes().set_aspect(
            1 / matplotlib.pyplot.axes().get_data_ratio()
        )
    else:
        matplotlib.pyplot.axes().set_aspect(aspect)

    if not os.path.exists(directory):
        os.makedirs(directory)

    matplotlib.pyplot.savefig(
        directory + "/" + filename,
        dpi = 700
    )
    matplotlib.pyplot.close()

if __name__ == "__main__":
    main()

回答1:


You need to convert your timestamp-like x data to a python datetime object, which can then be used in matplotlib and be understood by the matplotlib.dates.DateFormatter.

This can be done using the datetime.datetime.fromtimestamp() method.

import datetime
import matplotlib.dates
import matplotlib.pyplot as plt

data = [
        [1484611200.0, 844.4333],
        [1484524800.0, 783.3373],
        [1484438400.0, 774.194 ],
        [1484352000.0, 769.2299]
    ]

x = [datetime.datetime.fromtimestamp(element[0]) for element in data]
y = [element[1] for element in data]

plt.plot( x,  y,  ls="-",  c= "b",  linewidth  = 2 )
plt.xlabel("Dates")

time_formatter = matplotlib.dates.DateFormatter("%Y-%m-%d")
plt.axes().xaxis.set_major_formatter(time_formatter)
plt.axes().xaxis_date() # this is not actually necessary

plt.show()



回答2:


Whilst not directly addressing the text of the question, the error mentioned in the title can also occur when one attempts to plot data on an existing axis whose timeline units don't match those of the plot data (e.g. seconds vs datetime).



来源:https://stackoverflow.com/questions/41742955/valueerror-year-is-out-of-range-when-attempting-to-use-matplotlib-pyplot

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!