python - examples - ¿Mapa de calor en matplotlib con pcolor?
heatmap python (4)
Me gustaría hacer un mapa de calor como este (que se muestra en FlowingData ):
La fuente de datos está here , pero los datos al azar y las etiquetas estarían bien para usar, 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é un argumento de colormap heatmap = plt.pcolor(data, cmap=matplotlib.cm.Blues)
que se ve bien: heatmap = plt.pcolor(data, cmap=matplotlib.cm.Blues)
Pero más allá de eso, no puedo entender cómo mostrar etiquetas para las columnas y filas y mostrar los datos en la orientación correcta (origen en la parte superior izquierda en lugar de abajo a la izquierda).
Los intentos de manipular heatmap.axes
(por ejemplo, heatmap.axes.set_xticklabels = column_labels
) han fallado. ¿Que me estoy perdiendo aqui?
Alguien editó esta pregunta para eliminar el código que usé, así que me vi obligado a agregarlo como respuesta. ¡Gracias a todos los que participaron en responder esta pregunta! Creo que la mayoría de las otras respuestas son mejores que este código, solo lo dejo aquí como referencia.
Gracias a y a unutbu (que respondió esta pregunta ), tengo un resultado bastante agradable:
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:
El módulo python seaborn se basa en matplotlib y produce un mapa de calor muy agradable.
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í: Utilicé el mapa de color Matplotlib Blues, pero personalmente encuentro que los colores predeterminados son bastante hermosos. Utilicé matplotlib para rotar las etiquetas del eje x, ya que no pude encontrar la sintaxis de los cuerpos marinos. Como señaló grexor, fue necesario especificar las dimensiones (fig.set_size_inches) por prueba y error, lo que encontré 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 creo que haya mejorado la figura. Varios fragmentos de código fueron tomados de la excelente respuesta de Joelotz.
El problema principal es que primero necesita establecer la ubicación de sus tics xe y. Además, ayuda a utilizar la interfaz más orientada a objetos para matplotlib. A saber, interactuar directamente con los objetos de los axes
.
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.
Esto es tarde, pero aquí está mi implementación de Python del mapa de calor de la NBA de flujo de datos.
actualizado: 1/4/2014 : gracias a todos
# -*- coding: utf-8 -*-
# <nbformat>3.0</nbformat>
# ------------------------------------------------------------------------
# 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://.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í:
Hay un cuaderno ipython con todo este código here . Aprendí mucho del desbordamiento, así que espero que alguien lo encuentre útil.