Heatmap en matplotlib con pcolor?

Me gustaría hacer un mapa de calor como este (que se muestra en FlowingData ): mapa de calor

Los datos de origen están aquí , pero los datos aleatorios y las tags podrían utilizarse, es decir,

import numpy column_labels = list('ABCD') row_labels = list('WXYZ') data = numpy.random.rand(4,4) 

Hacer el mapa de calor es bastante fácil en matplotlib:

 from matplotlib import pyplot as plt heatmap = plt.pcolor(data) 

E incluso encontré argumentos de mapa de heatmap = plt.pcolor(data, cmap=matplotlib.cm.Blues) que parecen correctos: heatmap = plt.pcolor(data, cmap=matplotlib.cm.Blues)

Pero más allá de eso, no puedo imaginar cómo mostrar tags para las columnas y filas y mostrar los datos en la orientación correcta (origen en la parte superior izquierda en lugar de en la parte inferior izquierda).

Los bashs de manipular heatmap.axes (por ejemplo, heatmap.axes.set_xticklabels = column_labels ) han fallado. ¿Que me estoy perdiendo aqui?

Esto es tarde, pero aquí está mi implementación en python del flujo de datos de la NBA.

actualizado el 1/4/2014 : gracias a todos

 # -*- coding: utf-8 -*- # 3.0 # ------------------------------------------------------------------------ # Filename : heatmap.py # Date : 2013-04-19 # Updated : 2014-01-04 # Author : @LotzJoe >> Joe Lotz # Description: My attempt at reproducing the FlowingData graphic in Python # Source : http://flowingdata.com/2010/01/21/how-to-make-a-heatmap-a-quick-and-easy-solution/ # # Other Links: # http://stackoverflow.com/questions/14391959/heatmap-in-matplotlib-with-pcolor # # ------------------------------------------------------------------------ import matplotlib.pyplot as plt import pandas as pd from urllib2 import urlopen import numpy as np %pylab inline page = urlopen("http://datasets.flowingdata.com/ppg2008.csv") nba = pd.read_csv(page, index_col=0) # Normalize data columns nba_norm = (nba - nba.mean()) / (nba.max() - nba.min()) # Sort data according to Points, lowest to highest # This was just a design choice made by Yau # inplace=False (default) ->thanks SO user d1337 nba_sort = nba_norm.sort('PTS', ascending=True) nba_sort['PTS'].head(10) # Plot it out fig, ax = plt.subplots() heatmap = ax.pcolor(nba_sort, cmap=plt.cm.Blues, alpha=0.8) # Format fig = plt.gcf() fig.set_size_inches(8, 11) # turn off the frame ax.set_frame_on(False) # put the major ticks at the middle of each cell ax.set_yticks(np.arange(nba_sort.shape[0]) + 0.5, minor=False) ax.set_xticks(np.arange(nba_sort.shape[1]) + 0.5, minor=False) # want a more natural, table-like display ax.invert_yaxis() ax.xaxis.tick_top() # Set the labels # label source:https://en.wikipedia.org/wiki/Basketball_statistics labels = [ 'Games', 'Minutes', 'Points', 'Field goals made', 'Field goal attempts', 'Field goal percentage', 'Free throws made', 'Free throws attempts', 'Free throws percentage', 'Three-pointers made', 'Three-point attempt', 'Three-point percentage', 'Offensive rebounds', 'Defensive rebounds', 'Total rebounds', 'Assists', 'Steals', 'Blocks', 'Turnover', 'Personal foul'] # note I could have used nba_sort.columns but made "labels" instead ax.set_xticklabels(labels, minor=False) ax.set_yticklabels(nba_sort.index, minor=False) # rotate the plt.xticks(rotation=90) ax.grid(False) # Turn off all the ticks ax = plt.gca() for t in ax.xaxis.get_major_ticks(): t.tick1On = False t.tick2On = False for t in ax.yaxis.get_major_ticks(): t.tick1On = False t.tick2On = False 

La salida se ve así: fluyedata-like nba heatmap

Hay un cuaderno de ipython con todo este código aquí . He aprendido mucho del desbordamiento, así que espero que alguien lo encuentre útil.

El problema principal es que primero debe establecer la ubicación de sus marcas x e y. Además, ayuda a usar la interfaz más orientada a objetos para matplotlib. A saber, interactuar con el objeto de axes directamente.

 import matplotlib.pyplot as plt import numpy as np column_labels = list('ABCD') row_labels = list('WXYZ') data = np.random.rand(4,4) fig, ax = plt.subplots() heatmap = ax.pcolor(data) # put the major ticks at the middle of each cell, notice "reverse" use of dimension ax.set_yticks(np.arange(data.shape[0])+0.5, minor=False) ax.set_xticks(np.arange(data.shape[1])+0.5, minor=False) ax.set_xticklabels(row_labels, minor=False) ax.set_yticklabels(column_labels, minor=False) plt.show() 

Espero que ayude.

El módulo de python seaborn está basado en matplotlib y produce un mapa de calor muy bueno.

A continuación se muestra una implementación con Seaborn, diseñada para el portátil ipython / jupyter.

 import pandas as pd import matplotlib.pyplot as plt import seaborn as sns %matplotlib inline # import the data directly into a pandas dataframe nba = pd.read_csv("http://datasets.flowingdata.com/ppg2008.csv", index_col='Name ') # remove index title nba.index.name = "" # normalize data columns nba_norm = (nba - nba.mean()) / (nba.max() - nba.min()) # relabel columns labels = ['Games', 'Minutes', 'Points', 'Field goals made', 'Field goal attempts', 'Field goal percentage', 'Free throws made', 'Free throws attempts', 'Free throws percentage','Three-pointers made', 'Three-point attempt', 'Three-point percentage', 'Offensive rebounds', 'Defensive rebounds', 'Total rebounds', 'Assists', 'Steals', 'Blocks', 'Turnover', 'Personal foul'] nba_norm.columns = labels # set appropriate font and dpi sns.set(font_scale=1.2) sns.set_style({"savefig.dpi": 100}) # plot it out ax = sns.heatmap(nba_norm, cmap=plt.cm.Blues, linewidths=.1) # set the x-axis labels on the top ax.xaxis.tick_top() # rotate the x-axis labels plt.xticks(rotation=90) # get figure (usually obtained via "fig,ax=plt.subplots()" with matplotlib) fig = ax.get_figure() # specify dimensions and save fig.set_size_inches(15, 20) fig.savefig("nba.png") 

La salida se ve así: mapa de calor nba marino Usé el mapa de colores de matplotlib Blues, pero personalmente encuentro los colores predeterminados bastante hermosos. Utilicé matplotlib para rotar las tags del eje x, ya que no pude encontrar la syntax marítima. Como señaló grexor, fue necesario especificar las dimensiones (fig.set_size_inches) por prueba y error, lo cual me pareció un poco frustrante.

Como señaló Paul H, puede agregar fácilmente los valores a los mapas de calor (annot = True), pero en este caso no pensé que mejorara la cifra. Joelotz tomó varios fragmentos de código de la excelente respuesta.

Alguien editó esta pregunta para eliminar el código que usé, por lo que me vi obligado a agregarla como respuesta. ¡Gracias a todos los que participaron respondiendo esta pregunta! Creo que la mayoría de las otras respuestas son mejores que este código, simplemente lo dejo aquí para fines de referencia.

Gracias a Paul H y unutbu (quien respondió esta pregunta ), tengo una salida bastante bonita:

 import matplotlib.pyplot as plt import numpy as np column_labels = list('ABCD') row_labels = list('WXYZ') data = np.random.rand(4,4) fig, ax = plt.subplots() heatmap = ax.pcolor(data, cmap=plt.cm.Blues) # put the major ticks at the middle of each cell ax.set_xticks(np.arange(data.shape[0])+0.5, minor=False) ax.set_yticks(np.arange(data.shape[1])+0.5, minor=False) # want a more natural, table-like display ax.invert_yaxis() ax.xaxis.tick_top() ax.set_xticklabels(row_labels, minor=False) ax.set_yticklabels(column_labels, minor=False) plt.show() 

Y aquí está la salida:

Matplotlib HeatMap