matplotlib: dibujar líneas entre puntos ignorando datos faltantes

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() 

resultados en una plot con huecos 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).

Related of "matplotlib: dibujar líneas entre puntos ignorando datos faltantes"

Puede enmascarar los valores de 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

Trama

Qouting @Rutger Kassies ( enlace ):

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 utilizando 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 las Ninguna de los datos. Esto también significa que deberá eliminar los valores X correspondientes a Ninguno en la serie. Aquí hay un (feo) un 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 los valores Falso para Ninguno, filtrando x, pares de series de la lista, luego vuelve a comprimir los datos en su forma original.

Una solución con pandas:

 import matplotlib.pyplot as plt import pandas as pd def splitSerToArr(ser): return [ser.index, ser.as_matrix()] xs = range(8) series1 = [1, 3, 3, None, None, 5, 8, 9] series2 = [2, None, 5, None, 4, None, 3, 2] s1 = pd.Series(series1, index=xs) s2 = pd.Series(series2, index=xs) plt.plot( *splitSerToArr(s1.dropna()), linestyle='-', marker='o') plt.plot( *splitSerToArr(s2.dropna()), linestyle='-', marker='o') plt.show() 

La función splitSerToArr es muy útil al trazar en Pandas. Esta es la salida: introduzca la descripción de la imagen aquí

Para lo que valga la pena, después de algunas pruebas y errores, me gustaría agregar una aclaración a la solución de Thorsten. Esperemos que ahorre tiempo para los usuarios que buscaron en otro lugar después de haber probado este enfoque.

No pude obtener éxito con un problema idéntico al usar

 from pyplot import * 

y tratando de trazar con

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

Parecía que estaba obligado a usar import matplotlib.pyplot as plt para obtener el manejo adecuado de los NaN, aunque no puedo decir por qué.

Tal vez no entendí el punto, pero creo que Pandas ahora hace esto automáticamente . El siguiente ejemplo es un poco complicado y requiere acceso a Internet, pero la línea para China tiene muchos vacíos en los primeros años, por lo tanto, los segmentos en 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()