Trazar fechas en el eje x

4 minutos de lectura

avatar de usuario de irl_irl
irl_irl

Estoy tratando de trazar información contra fechas. Tengo una lista de fechas en el formato “02/01/1991”.

Los convertí haciendo lo siguiente:

x = parser.parse(date).strftime('%Y%m%d'))

lo que da 19910102

Luego traté de usar num2date

import matplotlib.dates as dates
new_x = dates.num2date(x)

Graficado:

plt.plot_date(new_x, other_data, fmt="bo", tz=None, xdate=True)

Pero me sale un error. Dice “ValueError: el año está fuera de rango”. ¿Alguna solución?

  • help(num2date): “x es un valor flotante que da uno más el número de días desde el 01-01-0001”, por lo que x=19910102 no corresponde al 2 de enero de 1991

    – Kyss Tao

    9 de marzo de 2012 a las 1:51

  • ¿Qué es el analizador en esta pregunta?

    – Juan Nieve

    4 de enero de 2020 a las 3:05

avatar de usuario de mechanical_meat
carne_mecanica

Puedes hacer esto más simplemente usando plot() en vez de plot_date().

Primero, convierta sus cadenas en instancias de Python datetime.date:

import datetime as dt

dates = ['01/02/1991','01/03/1991','01/04/1991']
x = [dt.datetime.strptime(d,'%m/%d/%Y').date() for d in dates]
y = range(len(x)) # many thanks to Kyss Tao for setting me straight here

Luego trama:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates

plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%m/%d/%Y'))
plt.gca().xaxis.set_major_locator(mdates.DayLocator())
plt.plot(x,y)
plt.gcf().autofmt_xdate()

Resultado:

ingrese la descripción de la imagen aquí

  • @bernie Gracias, realmente me ayudó. Sin embargo, en mi problema tengo demasiados días, por lo que toda la trama se obstruye. ¿Cómo mostrar cada quinta fecha o cada décima fecha en el eje x con su método?

    – usuario1506145

    3 de julio de 2013 a las 8:26

  • @erik Sé que es un poco tarde, pero eliminé las dos líneas set_major y eso me lo aclaró. Perdió algo de funcionalidad, pero sigue siendo una mejora.

    – El Boro

    18 de marzo de 2016 a las 9:19

  • Desafortunadamente, no me muestra 3 fechas, sino otras 6 fechas (aunque en ese intervalo). Usando matplotlib-1.5.1

    – Groosha

    22 de mayo de 2016 a las 9:16

Avatar de usuario de Jacek Szałęga
Jacek Szałęga

Tengo una reputación demasiado baja para agregar un comentario a la respuesta de @bernie, con una respuesta a @user1506145. Me he encontrado con el mismo problema.

1

La respuesta es un parámetro de intervalo que arregla las cosas.

2

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np
import datetime as dt

np.random.seed(1)

N = 100
y = np.random.rand(N)

now = dt.datetime.now()
then = now + dt.timedelta(days=100)
days = mdates.drange(now,then,dt.timedelta(days=1))

plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=5))
plt.plot(days,y)
plt.gcf().autofmt_xdate()
plt.show()

  • Tenga en cuenta que si está tomando la primera fecha de una serie o índice y la última fecha, dado que se trata de un rango, la última fecha se cortará y se encontrará con errores en su código. Suponiendo que tienes un Date columna en su índice, entonces puede hacer: days = mdates.drange(d1.index.min(),d1.index.max() + dt.timedelta(days=1),dt.timedelta(days=1)). Esencialmente, agregué 1 día a la fecha del valor límite superior del rango.

    –David Erickson

    5 de diciembre de 2020 a las 4:16


  • ¿Qué cambios debo hacer en el código de Jacek Szałęga para no asignar fechas aleatorias en el eje x, sino poner en el eje x las fechas recopiladas/muestreadas del archivo de Excel?

    – solo aprendiendo

    10 de septiembre de 2021 a las 7:16


  • mejor usar mdates.AutoDateLocator() en vez de mdates.DayLocator(interval=5) aquí para calcular automáticamente cuántas etiquetas de fecha deben mostrarse en el eje x. Esto puede responder a la pregunta anterior de @just_learning.

    – Hongchao Zhang

    15 de septiembre a las 3:11


Como @KyssTao ha estado diciendo, help(dates.num2date) dice que el x tiene que ser un flotante que indique el número de días desde 0001-01-01 más uno. Por eso, 19910102 no es 2/ene/1991, porque si contaras 19910101 días desde 0001-01-01 obtendrías algo en el año 54513 o similar (dividido por 365.25, número de días en un año).

Usar datestr2num en cambio (ver help(dates.datestr2num)):

new_x = dates.datestr2num(date) # where date is '01/02/1991'

  • Sería bueno si pudieras agregar el import declaración también, para ayudar a los novatos de Python como yo.

    – kkuilla

    6 de marzo de 2020 a las 10:13

  • @kkuilla Si esto sigue siendo relevante, supongo que lo tiene como import matplotlib.dates as dates

    – Irá II

    25 de febrero de 2021 a las 20:11


  • @IraI.I. Te referías from matplotlib import dates?

    – Shayán

    26 de julio a las 6:01


Adaptando la respuesta de @Jacek Szałęga para el uso de una figura fig y objeto de ejes correspondiente ax:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np
import datetime as dt

np.random.seed(1)

N = 100
y = np.random.rand(N)

now = dt.datetime.now()
then = now + dt.timedelta(days=100)
days = mdates.drange(now,then,dt.timedelta(days=1))


fig = plt.figure()
ax = fig.add_subplot(111)
    
ax.plot(days,y)
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax.xaxis.set_major_locator(mdates.DayLocator(interval=5))
ax.tick_params(axis="x", labelrotation=45)

plt.show()

¿Ha sido útil esta solución?