Тепловая карта в matplotlib с pcolor?
Я хотел бы сделать тепловую карту, как это (показано на FlowingData):

исходные данные здесь, но случайные данные и метки было бы нормально использовать, т. е.
import numpy
column_labels = list('ABCD')
row_labels = list('WXYZ')
data = numpy.random.rand(4,4)
создание тепловой карты достаточно легко в matplotlib:
from matplotlib import pyplot as plt
heatmap = plt.pcolor(data)
и я даже нашел colormap аргументы, которые выглядят примерно так: heatmap = plt.pcolor(data, cmap=matplotlib.cm.Blues)
но помимо этого, я не могу понять, как отображать метки для столбцов и строки и отображать данные в правильной ориентации (начало координат в верхнем левом углу вместо нижнего левого).
попытки манипулировать heatmap.axes (например,heatmap.axes.set_xticklabels = column_labels) все провалились. Чего мне здесь не хватает?
4 ответов:
это поздно, но вот моя реализация python тепловой карты flowingdata NBA.
обновлено:1/4/2014: спасибо всем
# -*- 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://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вывод выглядит так:
есть IPython ноутбук со всем этим кодом здесь. Я многому научился у "переполнения", поэтому, надеюсь, кто-то найдет это полезным.
основная проблема заключается в том, что вам сначала нужно установить местоположение ваших X и y тиков. Кроме того, это помогает использовать более объектно-ориентированный интерфейс для matplotlib. А именно, взаимодействовать с
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()надеюсь, что это поможет.
модуль python seaborn основан на matplotlib и создает очень хорошую тепловую карту.
Ниже приведена реализация с seaborn, предназначенная для ноутбука 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")вывод выглядит так:
Я использовал цветовую карту Matplotlib Blues, но лично считаю цвета по умолчанию довольно красивыми. Я использовал matplotlib для поворота меток оси x, так как я не мог найти синтаксис seaborn. Как отмечает grexor, необходимо было уточнить размеры (рис.set_size_inches) методом проб и ошибок, который я нашел немного разочаровывающим.
Как отметил Пол х, вы можете легко добавить значения к тепловым картам (annot=True), но в этом случае я не думал, что это улучшило фигуру. Несколько фрагментов кода были взяты из отличного ответа joelotz.
кто-то редактировал этот вопрос, чтобы удалить код, который я использовал, поэтому я был вынужден добавить это в качестве ответа. Спасибо всем, кто участвовал в ответе на этот вопрос! Я думаю, что большинство других ответов лучше, чем этот код, я просто оставляю это здесь для справочных целей.
С благодарностью Пол Ч и unutbu (кто ответил этот вопрос), у меня есть довольно симпатичный выход:
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()и вот вывод:

Я использовал цветовую карту Matplotlib Blues, но лично считаю цвета по умолчанию довольно красивыми. Я использовал matplotlib для поворота меток оси x, так как я не мог найти синтаксис seaborn. Как отмечает grexor, необходимо было уточнить размеры (рис.set_size_inches) методом проб и ошибок, который я нашел немного разочаровывающим.
Comments