2012-07-20 27 views
8

Estoy usando la función imshow() de matplotlib para mostrar un pandas.DataFrame.pandas, matplotlib, utilice el índice del marco de datos como etiquetas de control del eje

Me gustaría que las etiquetas y marcas de los ejes xey se extraigan de las listas DataFrame.index y DataFrame.columns, pero no puedo encontrar la manera de hacerlo.

Suponiendo que data es una pandas.DataFrame:

>>> print data 
<class 'pandas.core.frame.DataFrame'> 
Index: 201 entries, 1901 to 2101 
Data columns: 
jan 201 non-null values 
feb 201 non-null values 
mar 201 non-null values 
apr 201 non-null values 
may 201 non-null values 
jun 201 non-null values 
jul 201 non-null values 
aug 201 non-null values 
sep 201 non-null values 
oct 201 non-null values 
nov 201 non-null values 
dec 201 non-null values 

Cuando hago esto:

ax1 = fig.add_subplot(131, xticklabels=data.columns, yticklabels=data.index) 
ax1.set_title("A") 
ax1.tick_params(axis='both', direction='out') 
im1 = ax1.imshow(data, 
       interpolation='nearest', 
       aspect='auto', 
       cmap=cmap) 

termino con etiquetas señalizadoras bien espaciadas en el eje y de la imagen, pero las etiquetas se 1901-1906 en lugar de 1901 a 2101. Del mismo modo, las etiquetas tic del eje x son feb-jul en lugar de jan-dec.

Si uso

ax1 = fig.add_subplot(131) # without specifying tick labels 

Entonces termino con las etiquetas del eje de garrapatas simplemente ser los valores de índice ndarray subyacentes (es decir, 0-201 y 0-12). No es necesario modificar el espaciado o la cantidad de marcas y etiquetas, solo quiero que el texto de la etiqueta provenga del índice de DataFrame y las listas de columnas. ¿No estoy seguro de si me falta algo fácil o no?

Gracias de antemano.

Respuesta

5

como una solución general, he encontrado el siguiente método para ser una manera fácil de llevar un índice Pandas datetime64 en una etiqueta de eje matplotlib.

En primer lugar, cree una nueva serie convirtiendo el pandas datetime64 index a una clase Python datetime.datetime.

new_series = your_pandas_dataframe.index.to_pydatetime()

Ahora usted tiene toda la funcionalidad de matplotlib.dates. Antes de trazar, importe matplotlib.fechas como mdates y declarar las siguientes variables:

years = mdates.YearLocator() 
months = mdates.MonthLocator() 
days = mdates.DayLocator() 
hours = mdates.HourLocator(12) #if you want ticks every 12 hrs, you can pass 12 to this function 
minutes = mdates.MinuteLocator() 
daysFmt = mdates.DateFormatter('%m/%d') #or whatever format you want 

Ahora, hacer sus parcelas, utilizando los new_series como el eje x:

fig1 = plt.figure() 
ax = fig1.add_subplot(111) 
ax.plot(new_series,your_pandas_dataframe) 

Puede utilizar las funciones mdates mencionadas para modificar las etiquetas y ticks a su gusto, como por ejemplo:

ax.xaxis.set_major_locator(days) 
ax.xaxis.set_major_formatter(daysFmt) 
ax.xaxis.set_minor_locator(hours) 
6

Creo que el problema tiene que ver con la especificación de las etiquetas de ticks existentes. De forma predeterminada, hay menos tics que etiquetas, por lo que solo se usan las primeras pocas etiquetas. Lo siguiente debería funcionar primero configurando el número de tics.

ax1 = fig.add_subplot(131) 
ax1.set_title("A") 
ax1.tick_params(axis='both', direction='out') 
ax1.set_xticks(range(len(data.columns))) 
ax1.set_xticklabels(data.columns) 
ax1.set_yticks(range(len(data.index))) 
ax1.set_yticklabels(data.index) 
im1 = ax1.imshow(data, interpolation='nearest', aspect='auto', cmap=cmap) 

Esto produce una señal para todos los años en el eje y, lo que podría querer utilizar un subconjunto de los valores del índice.

+0

Esta es la solución más general, sin necesidad de hackers DateTime, etc. – FuzzyDuck

3

He encontrado que la forma más fácil de hacerlo es con ImageGrid. Aquí está el código para hacer esto y la trama + here is an IPython notebook que lo muestra en un formato más presentable:

mons = ['Jan', 
'Feb', 
'Mar', 
'Apr', 
'May', 
'Jun', 
'Jul', 
'Aug', 
'Sep', 
'Oct', 
'Nov', 
'Dec'] 

# just get the first 5 for illustration purposes 
df = DataFrame(randn(201, len(mons)), columns=mons, 
       index=arange(1901, 2102))[:5] 

from mpl_toolkits.axes_grid1 import ImageGrid 
fig = figure(figsize=(20, 100)) 
grid = ImageGrid(fig, 111, nrows_ncols=(1, 1), 
       direction='row', axes_pad=0.05, add_all=True, 
       label_mode='1', share_all=False, 
       cbar_location='right', cbar_mode='single', 
       cbar_size='10%', cbar_pad=0.05) 

ax = grid[0] 
ax.set_title('A', fontsize=40) 
ax.tick_params(axis='both', direction='out', labelsize=20) 
im = ax.imshow(df.values, interpolation='nearest', vmax=df.max().max(), 
       vmin=df.min().min()) 
ax.cax.colorbar(im) 
ax.cax.tick_params(labelsize=20) 
ax.set_xticks(arange(df.shape[1])) 
ax.set_xticklabels(mons) 
ax.set_yticks(arange(df.shape[0])) 
ax.set_yticklabels(df.index) 

enter image description here

Cuestiones relacionadas