Peta panas di matplotlib dengan pcolor?

100

Saya ingin membuat peta panas seperti ini (ditampilkan pada FlowingData ): peta panas

Data sumber ada di sini , tetapi data dan label acak akan baik-baik saja digunakan, yaitu

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

Membuat peta panas cukup mudah di matplotlib:

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

Dan saya bahkan menemukan file argumen peta warna yang terlihat benar:heatmap = plt.pcolor(data, cmap=matplotlib.cm.Blues)

Namun di luar itu, saya tidak tahu cara menampilkan label untuk kolom dan baris dan menampilkan data dalam orientasi yang tepat (asal di kiri atas, bukan di kiri bawah).

Upaya untuk memanipulasi heatmap.axes(misalnya heatmap.axes.set_xticklabels = column_labels) semuanya gagal. Apa yang kulewatkan di sini?

Jason Sundram
sumber
Ada banyak hal yang tumpang tindih dengan pertanyaan peta panas ini - mungkin ada beberapa info bagus untuk Anda di sana.
John Lyon
Teknik label dari posting ini mungkin membantu stackoverflow.com/questions/6352740/matplotlib-label-each-bin
tacaswell

Jawaban:

123

Ini terlambat, tetapi ini adalah implementasi python saya dari peta panas NBA data mengalir.

diperbarui: 1/4/2014 : terima kasih semuanya

# -*- 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

Outputnya terlihat seperti ini: peta panas nba seperti data mengalir

Ada notebook ipython dengan semua kode ini di sini . Saya telah belajar banyak dari 'overflow jadi semoga seseorang akan menganggap ini berguna.

BubbleGuppies
sumber
1
Kode di atas tidak berjalan di notebook iPythnon. Saya telah membuat sedikit modifikasi, mengubah nba_sort = nba_norm.sort ('PTS', ascending = True, inplace = True) menjadi nba_sort = nba_norm.copy () nba_sort.sort ('PTS', ascending = True, inplace = True) sebagai jenis bekerja dengan efek samping bukan dengan fungsi kembali! Terima kasih atas contoh konser yang luar biasa!
Yu Shen
1
Hmmm ... Anda sepertinya benar. Tidak yakin tentang apa itu semua. Saya akan memperbaiki kodenya. Terima kasih!
BubbleGuppies
Apa cara termudah untuk membuat grafik seperti ini tetapi menampilkan nilai statistik di tabel. Yaitu saya ingin membuat pcolorseperti ini tetapi itu memiliki nilai numerik yang ditampilkan juga. ATAU: Saya ingin membuat matplotlib tableyang mewarnai selnya. Saya telah melihat solusi untuk masalah lain, dan mereka jelek secara estetika. Ini tampak hebat, jika saja saya tahu cara melapisi angka-angka itu.
8one6
Ya. Saya tersandung untuk menjawab pertanyaan orang lain: stackoverflow.com/a/21167108/2501018
8one6
@joelotz Maukah Anda menyumbangkan versi (modifikasi) ini ke dokumen matplotlib? Jika demikian, cukup buka PR atau ping saya melalui email (lihat profil saya).
tacaswell
12

Modul python seaborn didasarkan pada matplotlib, dan menghasilkan peta panas yang sangat bagus.

Di bawah ini adalah implementasi dengan seaborn, dirancang untuk notebook 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")

Outputnya terlihat seperti ini: peta panas nba seaborn Saya menggunakan peta warna blues matplotlib, tetapi secara pribadi menemukan warna default cukup indah. Saya menggunakan matplotlib untuk memutar label sumbu x, karena saya tidak dapat menemukan sintaks seaborn. Seperti dicatat oleh grexor, itu perlu untuk menentukan dimensi (fig.set_size_inches) dengan coba-coba, yang menurut saya agak membuat frustrasi.

Seperti dicatat oleh Paul H, Anda dapat dengan mudah menambahkan nilai ke peta panas (annot = True), tetapi dalam kasus ini saya tidak berpikir itu meningkatkan angka. Beberapa potongan kode diambil dari jawaban yang sangat bagus oleh joelotz.

Mark Teese
sumber
11

Masalah utamanya adalah Anda harus terlebih dahulu mengatur lokasi tanda x dan y Anda. Juga, ini membantu untuk menggunakan antarmuka yang lebih berorientasi objek ke matplotlib. Yakni, berinteraksi dengan axesobjek secara langsung.

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()

Semoga membantu.

Paul H.
sumber
Terima kasih, @Paul H, itu berfungsi dengan baik. Saya menggunakan heatmap.axesproperti, yang karena alasan tertentu tidak melakukan apa-apa.
Jason Sundram
Tahukah Anda cara memindahkan label sumbu x agar berada di atas? Saya mencoba yang jelas tetapi ax.xaxis.set_label_position('top')tidak berhasil.
Jason Sundram
@JasonSundram Anda harus membuka pertanyaan baru untuk memindahkan pemosisian label, karena, itu seharusnya berfungsi dan anehnya tidak.
tacaswell
1
@tcaswell, bagus. Pertanyaan Baru di sini: stackoverflow.com/questions/14406214/…
Jason Sundram
1
@ Tgsmith61591 Saya akan menggunakan fungsi peta panas seaborn, menyetel annot=Truesaat dipanggil ( stanford.edu/~mwaskom/software/seaborn/generated/… )
Paul H
3

Seseorang mengedit pertanyaan ini untuk menghapus kode yang saya gunakan, jadi saya terpaksa menambahkannya sebagai jawaban. Terima kasih untuk semua yang berpartisipasi dalam menjawab pertanyaan ini! Saya pikir sebagian besar jawaban lain lebih baik daripada kode ini, saya meninggalkan ini di sini untuk tujuan referensi.

Dengan terima kasih kepada Paul H , dan unutbu (yang menjawab pertanyaan ini ), saya memiliki beberapa keluaran yang terlihat cukup bagus:

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()

Dan inilah hasilnya:

Matplotlib HeatMap

Jason Sundram
sumber