Pandas Plots: color separado para fines de semana, bonitos tiempos de impresión en el eje x

He creado una ttwig que parece introduzca la descripción de la imagen aquí

Tengo algunos problemas:

  1. ¿Cómo puedo mostrar específicamente los fines de semana. Algunas formas en las que había pensado eran capturar los índices correspondientes a los fines de semana y luego dibujar barras transparentes entre los límites. También se podría dibujar un rectángulo para el mismo. Sería mejor si pudiera hacerse claramente en Pandas.
  2. El formato de fecha no es el más bonito.

A continuación se muestra el código utilizado para generar este gráfico.

ax4=df4.plot(kind='bar',stacked=True,title='Mains 1 Breakdown'); ax4.set_ylabel('Power (W)'); idx_weekend=df4.index[df4.index.dayofweek>=5] ax.bar(idx_weekend.to_datetime(),[1800 for x in range(10)]) 

La ax.bar es específicamente para resaltar los fines de semana, pero no produce ningún resultado visible. (Problema 1) Para el Problema 2 traté de usar el formateador principal y los localizadores, el código es el siguiente:

 ax4=df4.plot(kind='bar',stacked=True,title='Mains 1 Breakdown'); ax4.set_ylabel('Power (W)'); formatter=matplotlib.dates.DateFormatter('%d-%b'); locator=matplotlib.dates.DayLocator(interval=1); ax4.xaxis.set_major_formatter(formatter); ax4.xaxis.set_major_locator(locator); 

La salida producida es la siguiente: introduzca la descripción de la imagen aquí

Puede ser útil saber cómo se ve el Dataframe

 In [122]:df4 Out[122]:  DatetimeIndex: 36 entries, 2011-04-19 00:00:00 to 2011-05-24 00:00:00 Data columns: (0 to 6 AM) Dawn 19 non-null values (12 to 6 PM) Dusk 19 non-null values (6 to 12 Noon) Morning 19 non-null values (6PM to 12 Noon) Night 20 non-null values dtypes: float64(4) 

Probé mucho y por ahora estos hacks funcionan. Esperamos una solución más pythonica y consistente. Solución a problemas de etiquetado:

 def correct_labels(ax): labels = [item.get_text() for item in ax.get_xticklabels()] days=[label.split(" ")[0] for label in labels] months=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"] final_labels=[] for i in range(len(days)): a=days[i].split("-") final_labels.append(a[2]+"\n"+months[int(a[1])-1]) ax.set_xticklabels(final_labels) 

También al trazar hago el siguiente cambio.

 ax=df.plot(kind='bar',rot=0) 

Esto hace que las tags en 0 rotación.

Para encontrar los fines de semana y resaltarlos, escribí las siguientes dos funciones:

 def find_weekend_indices(datetime_array): indices=[] for i in range(len(datetime_array)): if datetime_array[i].weekday()>=5: indices.append(i) return indices def highlight_weekend(weekend_indices,ax): i=0 while i 

Ahora, la ttwig parece mucho más útil y cubre estos casos de uso. introduzca la descripción de la imagen aquí

Ahora que Pandas admite el poderoso espacio de nombres .dt en cada serie, es posible identificar el inicio y el final de cada fin de semana sin ningún tipo de bucles de Python explícitos. Simplemente filtre sus valores de tiempo con t.dt.dayofweek >= 5 para seleccionar solo las veces que caen en el fin de semana, y luego year * 100 + weekofyear por un valor year * 100 + weekofyear que sea diferente cada semana; aquí uso year * 100 + weekofyear porque el resultado se ve como 201603 que es bastante agradable de leer para la depuración.

La función resultante es:

 def highlight_weekends(ax, timeseries): dt = timeseries.dt ranges = timeseries[dt.dayofweek >= 5].groupby(dt.year * 100 + dt.weekofyear).agg(['min', 'max']) for i, tmin, tmax in ranges.itertuples(): ax.axvspan(tmin, tmax, facecolor='orange', edgecolor='none', alpha=0.1) 

Simplemente pásale el eje y la serie de tiempo que es tu eje x , ¡y resaltará los fines de semana para ti!