python matplotlib

python - matplotlib: líneas de dibujo entre puntos que ignoran datos faltantes



plt title python (5)

Tengo un conjunto de datos que quiero trazar como un gráfico de líneas. Para cada serie, faltan algunos datos (pero diferentes para cada serie). Actualmente, matplotlib no dibuja líneas que omitan datos faltantes: por ejemplo

import matplotlib.pyplot as plt xs = range(8) series1 = [1, 3, 3, None, None, 5, 8, 9] series2 = [2, None, 5, None, 4, None, 3, 2] plt.plot(xs, series1, linestyle=''-'', marker=''o'') plt.plot(xs, series2, linestyle=''-'', marker=''o'') plt.show()

da como resultado una trama con espacios en las líneas. ¿Cómo puedo decirle a matplotlib que dibuje líneas a través de los huecos? (Prefiero no tener que interpolar los datos).


Por lo que pueda valer, después de algunas pruebas y errores, me gustaría agregar una aclaración a la solución de Thorsten. Con suerte, se ahorra tiempo a los usuarios que buscaron en otro lado después de haber probado este enfoque.

No pude tener éxito con un problema idéntico mientras usaba

from pyplot import *

e intentando trazar con

plot(abscissa[mask],ordinate[mask])

Parecía que se requería usar import matplotlib.pyplot as plt para obtener el manejo adecuado de NaNs, aunque no puedo decir por qué.


Puede enmascarar los valores NaN de esta manera:

import numpy as np import matplotlib.pyplot as plt xs = np.arange(8) series1 = np.array([1, 3, 3, None, None, 5, 8, 9]).astype(np.double) s1mask = np.isfinite(series1) series2 = np.array([2, None, 5, None, 4, None, 3, 2]).astype(np.double) s2mask = np.isfinite(series2) plt.plot(xs[s1mask], series1[s1mask], linestyle=''-'', marker=''o'') plt.plot(xs[s2mask], series2[s2mask], linestyle=''-'', marker=''o'') plt.show()

Esto lleva a


Qouting @Rutger Kassies ( link ):

Matplotlib solo dibuja una línea entre puntos de datos consecutivos (válidos) y deja un espacio en los valores de NaN.

Una solución si estás usando Pandas,:

#pd.Series s.dropna().plot() #masking (as @Thorsten Kranz suggestion) #pd.DataFrame df[''a_col_ffill''] = df[''a_col''].ffill(method=''ffill'') df[''b_col_ffill''] = df[''b_col''].ffill(method=''ffill'') # changed from a to b df[[''a_col_ffill'',''b_col_ffill'']].plot()


Sin interpolación, deberá eliminar los Ninguno de los datos. Esto también significa que deberá eliminar los valores X correspondientes a ninguno en la serie. Aquí hay un (un feo) trazador de líneas para hacer eso:

x1Clean,series1Clean = zip(* filter( lambda x: x[1] is not None , zip(xs,series1) ))

La función lambda devuelve False for None values, filtrando los pares x, series de la lista, luego vuelve a volver a comprimir los datos en su forma original.


Tal vez no entendí el punto, pero creo que Pandas ahora lo hace de forma automática . El siguiente ejemplo es un poco complicado y requiere acceso a Internet, pero la línea para China tiene muchas lagunas en los primeros años, de ahí los segmentos de línea recta.

import pandas as pd import numpy as np import matplotlib.pyplot as plt # read data from Maddison project url = ''http://www.ggdc.net/maddison/maddison-project/data/mpd_2013-01.xlsx'' mpd = pd.read_excel(url, skiprows=2, index_col=0, na_values=['' '']) mpd.columns = map(str.rstrip, mpd.columns) # select countries countries = [''England/GB/UK'', ''USA'', ''Japan'', ''China'', ''India'', ''Argentina''] mpd = mpd[countries].dropna() mpd = mpd.rename(columns={''England/GB/UK'': ''UK''}) mpd = np.log(mpd)/np.log(2) # convert to log2 # plots ax = mpd.plot(lw=2) ax.set_title(''GDP per person'', fontsize=14, loc=''left'') ax.set_ylabel(''GDP Per Capita (1990 USD, log2 scale)'') ax.legend(loc=''upper left'', fontsize=10, handlelength=2, labelspacing=0.15) fig = ax.get_figure() fig.show()