Tạo bản đồ nhiệt từ gấu trúc DataFrame


112

Tôi có một khung dữ liệu được tạo từ gói Pandas của Python. Làm cách nào để tạo bản đồ nhiệt bằng DataFrame từ gói gấu trúc.

import numpy as np 
from pandas import *

Index= ['aaa','bbb','ccc','ddd','eee']
Cols = ['A', 'B', 'C','D']
df = DataFrame(abs(np.random.randn(5, 4)), index= Index, columns=Cols)

>>> df
          A         B         C         D
aaa  2.431645  1.248688  0.267648  0.613826
bbb  0.809296  1.671020  1.564420  0.347662
ccc  1.501939  1.126518  0.702019  1.596048
ddd  0.137160  0.147368  1.504663  0.202822
eee  0.134540  3.708104  0.309097  1.641090
>>> 

Bạn đã thử gì về việc tạo bản đồ nhiệt hoặc nghiên cứu? Mà không biết thêm, tôi khuyên bạn nên chuyển đổi dữ liệu của bạn và sử dụng phương pháp này
học

@joelostblom Đây không phải là một câu trả lời, là một bình luận, nhưng vấn đề là tôi không đủ uy tín để có thể đưa ra bình luận. Tôi hơi bối rối vì giá trị đầu ra của ma trận và mảng ban đầu hoàn toàn khác nhau. Tôi muốn in trong bản đồ nhiệt các giá trị thực, không phải một số khác. Ai đó có thể giải thích cho tôi tại sao điều này lại xảy ra. Ví dụ: * dữ liệu được lập chỉ mục ban đầu: aaa / A = 2,431645 * giá trị được in trong bản đồ nhiệt: aaa / A = 1,06192
Monitotier

@Monitotier Vui lòng đặt một câu hỏi mới và bao gồm một ví dụ mã hoàn chỉnh về những gì bạn đã thử. Đây là cách tốt nhất để nhờ ai đó giúp bạn tìm ra điều sai trái! Bạn có thể liên kết đến câu hỏi này nếu bạn nghĩ nó có liên quan.
joelostblom

Câu trả lời:


82

Bạn muốn matplotlib.pcolor:

import numpy as np 
from pandas import DataFrame
import matplotlib.pyplot as plt

index = ['aaa', 'bbb', 'ccc', 'ddd', 'eee']
columns = ['A', 'B', 'C', 'D']
df = DataFrame(abs(np.random.randn(5, 4)), index=index, columns=columns)

plt.pcolor(df)
plt.yticks(np.arange(0.5, len(df.index), 1), df.index)
plt.xticks(np.arange(0.5, len(df.columns), 1), df.columns)
plt.show()

Điều này mang lại:

Mẫu đầu ra


5
Có một số cuộc thảo luận thú vị ở đây về pcolorvs imshow.
LondonRob

1
… Và cũng pcolormeshđược tối ưu hóa cho loại đồ họa này.
Eric O Lebigot

180

Đối với những người nhìn vào điều này ngày hôm nay, tôi muốn giới thiệu Seaborn heatmap()như được ghi lại ở đây .

Ví dụ trên sẽ được thực hiện như sau:

import numpy as np 
from pandas import DataFrame
import seaborn as sns
%matplotlib inline

Index= ['aaa', 'bbb', 'ccc', 'ddd', 'eee']
Cols = ['A', 'B', 'C', 'D']
df = DataFrame(abs(np.random.randn(5, 4)), index=Index, columns=Cols)

sns.heatmap(df, annot=True)

Đâu %matplotliblà một chức năng ma thuật IPython cho những người không quen.


Tại sao bạn không sử dụng gấu trúc?
tommy.carstensen

9
Seaborn và Pandas hoạt động tốt với nhau, vì vậy bạn vẫn sẽ sử dụng Pandas để đưa dữ liệu của mình vào đúng hình dạng. Seaborn chuyên về biểu đồ tĩnh và giúp việc tạo bản đồ nhiệt từ Pandas DataFrame đã chết trở nên đơn giản.
Brideau

Có vẻ như liên kết này đã chết; bạn có thể cập nhật nó không !? Hơn nữa, tôi sẽ chạy đoạn mã trên bằng cách import matplotlib.pyplot as pltnào?
Cleb

Xin chào @Cleb, tôi đã phải cập nhật nó vào trang lưu trữ vì nó không giống ở đâu cả. Hãy xem tài liệu của họ để sử dụng nó với pyplot: stanford.edu/~mwaskom/software/seaborn-dev/tutorial/…
Brideau

Sử dụng import matplotlib.pyplot as pltthay vì %matplotlib inlinevà kết thúc bằng plt.show()để thực sự xem cốt truyện.
tsveti_iko

83

Nếu bạn không cần một biểu đồ và chỉ đơn giản là muốn thêm màu sắc để thể hiện các giá trị trong một định dạng bảng, bạn có thể sử dụng style.background_gradient()phương pháp của khung dữ liệu gấu trúc. Phương pháp này tô màu bảng HTML được hiển thị khi xem các khung dữ liệu gấu trúc trong Máy tính xách tay JupyterLab và kết quả tương tự như sử dụng "định dạng có điều kiện" trong phần mềm bảng tính:

import numpy as np 
import pandas as pd


index= ['aaa', 'bbb', 'ccc', 'ddd', 'eee']
cols = ['A', 'B', 'C', 'D']
df = pd.DataFrame(abs(np.random.randn(5, 4)), index=index, columns=cols)
df.style.background_gradient(cmap='Blues')

nhập mô tả hình ảnh ở đây

Để biết cách sử dụng chi tiết, vui lòng xem câu trả lời phức tạp hơn mà tôi đã cung cấp về cùng chủ đề trước đây và phần tạo kiểu của tài liệu về gấu trúc .


4
Chết tiệt, câu trả lời này thực sự là một trong những tôi đang tìm kiếm. IMO, phải cao hơn (+1).
ponadto

7
Câu trả lời này không phải là một giải pháp hợp lệ cho câu hỏi đã đăng. Màu chuyển nền của gấu trúc tính đến từng hàng hoặc từng cột riêng biệt trong khi màu pcolor hoặc pcolormesh của matplotlib tính đến toàn bộ ma trận. Ví dụ, đoạn mã sau pd.DataFrame([[1, 1], [0, 3]]).style.background_gradient(cmap='summer') dẫn đến một bảng có hai cái, mỗi cái có một màu khác nhau.
Toni Penya-Alba

4
@ ToniPenya-Alba Câu hỏi là về cách tạo bản đồ nhiệt từ khung dữ liệu gấu trúc, chứ không phải cách sao chép hành vi của pcolor hoặc pcolormesh. Nếu bạn quan tâm đến cái sau cho mục đích của riêng mình, bạn có thể sử dụng axis=None(vì pandas 0.24.0).
joelostblom

2
@joelostblom Tôi không có ý nhận xét của tôi như trong "tái tạo một công cụ hoặc một hành vi khác" nhưng như trong "thường người ta muốn tất cả các phần tử trong ma trận theo cùng một tỷ lệ thay vì có các tỷ lệ khác nhau cho mỗi hàng / cột". Như bạn chỉ ra, axis=Noneđạt được điều đó và, theo ý kiến của tôi, nó phải là một phần của câu trả lời của bạn (đặc biệt vì nó dường như không được ghi 0 )
Toni Penya-Alba

2
@ ToniPenya-Alba Tôi đã thực hiện axis=Nonemột phần của câu trả lời chi tiết mà tôi liên kết đến ở trên, cùng với một số tùy chọn khác vì tôi đồng ý với bạn rằng một số tùy chọn này cho phép hành vi thường mong muốn. Tôi cũng nhận thấy thiếu tài liệu ngày hôm qua và đã mở một buổi PR .
joelostblom

17

sns.heatmapApi hữu ích là ở đây . Kiểm tra các thông số, có một số tốt trong số họ. Thí dụ:

import seaborn as sns
%matplotlib inline

idx= ['aaa','bbb','ccc','ddd','eee']
cols = list('ABCD')
df = DataFrame(abs(np.random.randn(5,4)), index=idx, columns=cols)

# _r reverses the normal order of the color map 'RdYlGn'
sns.heatmap(df, cmap='RdYlGn_r', linewidths=0.5, annot=True)

nhập mô tả hình ảnh ở đây


4

Nếu bạn muốn có một bản đồ nhiệt tương tác từ Pandas DataFrame và bạn đang chạy sổ ghi chép Jupyter, bạn có thể thử Widget Clustergrammer-Widget tương tác, xem sổ ghi chép tương tác trên NBViewer tại đây , tài liệu tại đây

nhập mô tả hình ảnh ở đây

Và đối với các tập dữ liệu lớn hơn, bạn có thể dùng thử tiện ích con Clustergrammer2 WebGL đang được phát triển (sổ tay mẫu tại đây )


1
wow cái này rất gọn gàng! Thật tuyệt khi thấy một số gói đẹp sắp đến với python - mệt mỏi vì phải sử dụng R magics
Sos

2

Xin lưu ý rằng các tác giả của seabornchỉ muốn seaborn.heatmap làm việc với các khung dữ liệu phân loại. Nó không chung chung.

Nếu chỉ mục và cột của bạn là giá trị số và / hoặc ngày giờ, mã này sẽ phục vụ bạn tốt.

Chức năng ánh xạ nhiệt Matplotlib pcolormeshyêu cầu các thùng thay vì các chỉ mục , vì vậy có một số mã ưa thích để tạo các thùng từ các chỉ số khung dữ liệu của bạn (ngay cả khi chỉ mục của bạn không cách đều nhau!).

Phần còn lại đơn giản là np.meshgridplt.pcolormesh.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

def conv_index_to_bins(index):
    """Calculate bins to contain the index values.
    The start and end bin boundaries are linearly extrapolated from 
    the two first and last values. The middle bin boundaries are 
    midpoints.

    Example 1: [0, 1] -> [-0.5, 0.5, 1.5]
    Example 2: [0, 1, 4] -> [-0.5, 0.5, 2.5, 5.5]
    Example 3: [4, 1, 0] -> [5.5, 2.5, 0.5, -0.5]"""
    assert index.is_monotonic_increasing or index.is_monotonic_decreasing

    # the beginning and end values are guessed from first and last two
    start = index[0] - (index[1]-index[0])/2
    end = index[-1] + (index[-1]-index[-2])/2

    # the middle values are the midpoints
    middle = pd.DataFrame({'m1': index[:-1], 'p1': index[1:]})
    middle = middle['m1'] + (middle['p1']-middle['m1'])/2

    if isinstance(index, pd.DatetimeIndex):
        idx = pd.DatetimeIndex(middle).union([start,end])
    elif isinstance(index, (pd.Float64Index,pd.RangeIndex,pd.Int64Index)):
        idx = pd.Float64Index(middle).union([start,end])
    else:
        print('Warning: guessing what to do with index type %s' % 
              type(index))
        idx = pd.Float64Index(middle).union([start,end])

    return idx.sort_values(ascending=index.is_monotonic_increasing)

def calc_df_mesh(df):
    """Calculate the two-dimensional bins to hold the index and 
    column values."""
    return np.meshgrid(conv_index_to_bins(df.index),
                       conv_index_to_bins(df.columns))

def heatmap(df):
    """Plot a heatmap of the dataframe values using the index and 
    columns"""
    X,Y = calc_df_mesh(df)
    c = plt.pcolormesh(X, Y, df.values.T)
    plt.colorbar(c)

Gọi nó bằng cách sử dụng heatmap(df), và xem nó bằng cách sử dụng plt.show().

nhập mô tả hình ảnh ở đây

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.