suptitle pyplot axessubplot add_subplot python matplotlib

python - pyplot - Trabajando con valores de NaN en matplotlib



set title subplot (2)

Tengo datos por hora que consisten en una serie de columnas. La primera columna es una fecha ( date_log ), y el resto de columnas contienen diferentes puntos de muestra. El problema es que los puntos de muestra se registran utilizando un tiempo diferente incluso por hora, por lo que cada columna tiene al menos un par de NaN . Si grafico usando el primer código, funciona bien, pero quiero tener espacios donde no haya datos del registrador durante un día más o menos y no quiero que los puntos se unan. Si uso el segundo código, puedo ver las brechas, pero debido a los puntos de NaN, los puntos de datos no se unen. En el siguiente ejemplo, solo estoy trazando las primeras tres columnas.

Cuando hay una gran brecha como los puntos azules (01 / 06-01 / 07/2015) quiero tener una brecha y luego los puntos se unen. El segundo ejemplo no une los puntos. Me gusta el primer gráfico, pero quiero crear huecos como el segundo método cuando no hay puntos de datos de muestra para el rango de fechas de 24 horas, etc., dejando los puntos de datos faltantes por más tiempo como un espacio vacío.

¿Hay algún trabajo alrededor? Gracias

1-método:

Log_1a_mask = np.isfinite(Log_1a) # Log_1a is column 2 data points Log_1b_mask = np.isfinite(Log_1b) # Log_1b is column 3 data points plt.plot_date(date_log[Log_1a_mask], Log_1a[Log_1a_mask], linestyle=''-'', marker='''',color=''r'',) plt.plot_date(date_log[Log_1b_mask], Log_1b[Log_1b_mask], linestyle=''-'', marker='''', color=''b'') plt.show()

2-método:

plt.plot_date(date_log, Log_1a, ‘-r*’, markersize=2, markeredgewidth=0, color=’r’) # Log_1a contains raw data with NaN plt.plot_date(date_log, Log_1b, ‘-r*’, markersize=2, markeredgewidth=0, color=’r’) # Log_1a contains raw data with NaN plt.show()

Salida de 1 método:

Salida de 2 métodos:


Si lo estoy entendiendo correctamente, tiene un conjunto de datos con muchos huecos pequeños ( NaN individuales) que desea llenar y huecos más grandes que no.

Uso de pandas para "rellenar hacia delante" las lagunas

Una opción es usar pandas fillna con una cantidad limitada de valores de relleno.

Como un rápido ejemplo de cómo funciona esto:

In [1]: import pandas as pd; import numpy as np In [2]: x = pd.Series([1, np.nan, 2, np.nan, np.nan, 3, np.nan, np.nan, np.nan, 4]) In [3]: x.fillna(method=''ffill'', limit=1) Out[3]: 0 1 1 1 2 2 3 2 4 NaN 5 3 6 3 7 NaN 8 NaN 9 4 dtype: float64 In [4]: x.fillna(method=''ffill'', limit=2) Out[4]: 0 1 1 1 2 2 3 2 4 2 5 3 6 3 7 3 8 NaN 9 4 dtype: float64

Como ejemplo de uso de esto para algo similar a su caso:

import pandas as pd import numpy as np import matplotlib.pyplot as plt np.random.seed(1977) x = np.random.normal(0, 1, 1000).cumsum() # Set every third value to NaN x[::3] = np.nan # Set a few bigger gaps... x[20:100], x[200:300], x[400:450] = np.nan, np.nan, np.nan # Use pandas with a limited forward fill # You may want to adjust the `limit` here. This will fill 2 nan gaps. filled = pd.Series(x).fillna(limit=2, method=''ffill'') # Let''s plot the results fig, axes = plt.subplots(nrows=2, sharex=True) axes[0].plot(x, color=''lightblue'') axes[1].plot(filled, color=''lightblue'') axes[0].set(ylabel=''Original Data'') axes[1].set(ylabel=''Filled Data'') plt.show()

Usando numpy para interpolar huecos

Alternativamente, podemos hacer esto usando solo numpy . Es posible (y más eficiente) hacer un "relleno hacia adelante" idéntico al método de pandas anterior, pero le mostraré otro método para brindarle más opciones que solo repetir valores.

En lugar de repetir el último valor a través de la "brecha", podemos realizar una interpolación lineal de los valores en la brecha. Esto es menos eficiente computacionalmente (y lo haré incluso menos eficiente al interpolar en todas partes), pero para la mayoría de los conjuntos de datos no notará una gran diferencia.

Como ejemplo, definamos una función interpolate_gaps :

def interpolate_gaps(values, limit=None): """ Fill gaps using linear interpolation, optionally only fill gaps up to a size of `limit`. """ values = np.asarray(values) i = np.arange(values.size) valid = np.isfinite(values) filled = np.interp(i, i[valid], values[valid]) if limit is not None: invalid = ~valid for n in range(1, limit+1): invalid[:-n] &= invalid[n:] filled[invalid] = np.nan return filled

Tenga en cuenta que obtendremos un valor interpolado, a diferencia de la versión anterior de los pandas :

In [11]: values = [1, np.nan, 2, np.nan, np.nan, 3, np.nan, np.nan, np.nan, 4] In [12]: interpolate_gaps(values, limit=1) Out[12]: array([ 1. , 1.5 , 2. , nan, 2.66666667, 3. , nan, nan, 3.75 , 4. ])

En el ejemplo de trazado, si reemplazamos la línea:

filled = pd.Series(x).fillna(limit=2, method=''ffill'')

Con:

filled = interpolate_gaps(x, limit=2)

Obtendremos una trama visualmente idéntica:

Como un ejemplo completo, independiente:

import numpy as np import matplotlib.pyplot as plt np.random.seed(1977) def interpolate_gaps(values, limit=None): """ Fill gaps using linear interpolation, optionally only fill gaps up to a size of `limit`. """ values = np.asarray(values) i = np.arange(values.size) valid = np.isfinite(values) filled = np.interp(i, i[valid], values[valid]) if limit is not None: invalid = ~valid for n in range(1, limit+1): invalid[:-n] &= invalid[n:] filled[invalid] = np.nan return filled x = np.random.normal(0, 1, 1000).cumsum() # Set every third value to NaN x[::3] = np.nan # Set a few bigger gaps... x[20:100], x[200:300], x[400:450] = np.nan, np.nan, np.nan # Interpolate small gaps using numpy filled = interpolate_gaps(x, limit=2) # Let''s plot the results fig, axes = plt.subplots(nrows=2, sharex=True) axes[0].plot(x, color=''lightblue'') axes[1].plot(filled, color=''lightblue'') axes[0].set(ylabel=''Original Data'') axes[1].set(ylabel=''Filled Data'') plt.show()

Nota: originalmente leí completamente la pregunta. Ver el historial de versiones para mi respuesta original.


Simplemente uso esta función:

import math for i in range(1,len(data)): if math.isnan(data[i]): data[i] = data[i-1]