Bản đồ nhiệt trong matplotlib với màu?


100

Tôi muốn tạo một bản đồ nhiệt như thế này (hiển thị trên FlowingData ): bản đồ nhiệt

Dữ liệu nguồn ở đây , nhưng dữ liệu và nhãn ngẫu nhiên sẽ được sử dụng, tức là

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

Tạo bản đồ nhiệt đủ dễ dàng trong matplotlib:

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

Và tôi thậm chí còn tìm thấy một đối số bản đồ màu có vẻ đúng:heatmap = plt.pcolor(data, cmap=matplotlib.cm.Blues)

Nhưng ngoài ra, tôi không thể tìm ra cách hiển thị nhãn cho các cột và hàng và hiển thị dữ liệu theo hướng thích hợp (điểm gốc ở trên cùng bên trái thay vì dưới cùng bên trái).

Các nỗ lực để thao tác heatmap.axes(ví dụ heatmap.axes.set_xticklabels = column_labels) đều không thành công. Tôi còn thiếu gì ở đây?


Có rất nhiều sự trùng lặp với câu hỏi về bản đồ nhiệt này - có thể là một số thông tin tốt cho bạn ở đó.
John Lyon

Các kỹ thuật nhãn từ này có thể giúp bài stackoverflow.com/questions/6352740/matplotlib-label-each-bin
tacaswell

Câu trả lời:


123

Điều này đã muộn, nhưng đây là cách triển khai python của tôi về bản đồ nhiệt NBA flowdata.

cập nhật: 1/4/2014 : cảm ơn mọi người

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

Đầu ra trông như thế này: Bản đồ nhiệt nba giống như flowdata

Có một sổ ghi chép ipython với tất cả mã này ở đây . Tôi đã học được rất nhiều điều từ 'tràn nên hy vọng ai đó sẽ thấy điều này hữu ích.


1
Mã trên không chạy trong máy tính xách tay iPythnon. Tôi đã thực hiện một số sửa đổi nhỏ, thay đổi nba_sort = nba_norm.sort ('PTS', ascending = True, inplace = True) thành nba_sort = nba_norm.copy () nba_sort.sort ('PTS', ascending = True, inplace = True) vì sự sắp xếp hoạt động theo hiệu ứng phụ không phải bởi hàm trả về! Cảm ơn vì ví dụ conceret tuyệt vời!
Yu Shen

1
Hmmm ... bạn có vẻ đúng. Không chắc đó là tất cả về những gì. Tôi sẽ sửa mã. Cảm ơn!
BubbleGuppies

Cách dễ nhất để tạo một đồ họa như thế này nhưng hiển thị giá trị của thống kê trong bảng. Tức là tôi muốn tạo một cái pcolornhư thế này nhưng nó cũng có các giá trị số được hiển thị. HOẶC: Tôi muốn tạo một matplotlib tabletô màu các ô của nó. Tôi đã thấy các giải pháp cho vấn đề khác, và chúng xấu về mặt thẩm mỹ. Điều này trông tuyệt vời, giá như tôi biết cách chồng các con số.
8one 6

Vâng. Tôi đã vấp phải điều đó khi trả lời câu hỏi của người khác: stackoverflow.com/a/21167108/2501018
8one6

@joelotz Bạn có sẵn sàng đóng góp phiên bản (đã sửa đổi) của phiên bản này cho tài liệu matplotlib không? Nếu vậy, chỉ cần mở một bài PR hoặc ping cho tôi qua email (xem hồ sơ của tôi).
tacaswell

12

Mô-đun python seaborn dựa trên matplotlib và tạo ra một bản đồ nhiệt rất đẹp.

Dưới đây là một triển khai với seaborn, được thiết kế cho máy tính xách tay 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")

Kết quả đầu ra như sau: bản đồ nhiệt seaborn nba Tôi đã sử dụng bản đồ màu matplotlib Blues, nhưng cá nhân tôi thấy màu sắc mặc định khá đẹp. Tôi đã sử dụng matplotlib để xoay các nhãn trục x, vì tôi không thể tìm thấy cú pháp seaborn. Như đã lưu ý bởi grexor, cần phải chỉ định kích thước (fig.set_size_inches) bằng cách thử và sai, điều này tôi thấy hơi bực bội.

Theo lưu ý của Paul H, bạn có thể dễ dàng thêm các giá trị vào bản đồ nhiệt (annot = True), nhưng trong trường hợp này, tôi không nghĩ rằng nó đã cải thiện con số. Một số đoạn mã được lấy từ câu trả lời xuất sắc của joelotz.


11

Vấn đề chính là trước tiên bạn cần thiết lập vị trí của các tick x và y. Ngoài ra, nó giúp sử dụng giao diện hướng đối tượng hơn cho matplotlib. Cụ thể là tương tác axestrực tiếp với đối tượng.

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

Hy vọng rằng sẽ giúp.


Cảm ơn, @Paul H, hoạt động rất hay. Tôi đang sử dụng heatmap.axestài sản, vì một số lý do không làm được gì cả.
Jason Sundram

Bạn có biết cách di chuyển các nhãn trục x để ở trên cùng không? Tôi đã thử điều hiển nhiên ax.xaxis.set_label_position('top')nhưng không có kết quả.
Jason Sundram

@JasonSundram Bạn nên mở một câu hỏi mới cho việc di chuyển vị trí nhãn, bởi vì, điều đó sẽ hoạt động và thật kỳ lạ là nó không.
tacaswell

1
@tcaswell, điểm tốt. Câu hỏi mới ở đây: stackoverflow.com/questions/14406214/…
Jason Sundram

1
@ Tgsmith61591 Tôi sẽ sử dụng chức năng Heatmap sanh ở biển của, thiết lập annot=Truekhi gọi ( stanford.edu/~mwaskom/software/seaborn/generated/... )
Paul H

3

Ai đó đã chỉnh sửa câu hỏi này để xóa mã tôi đã sử dụng, vì vậy tôi buộc phải thêm nó làm câu trả lời. Cảm ơn tất cả những người đã tham gia trả lời câu hỏi này! Tôi nghĩ rằng hầu hết các câu trả lời khác tốt hơn mã này, tôi chỉ để điều này ở đây cho mục đích tham khảo.

Cảm ơn Paul Hunutbu (người đã trả lời câu hỏi này ), tôi có một số đầu ra khá đẹp:

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

Và đây là đầu ra:

Matplotlib HeatMap

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.