Membuat peta panas dari pandas DataFrame

112

Saya memiliki kerangka data yang dihasilkan dari paket Pandas Python. Bagaimana saya bisa menghasilkan peta panas menggunakan DataFrame dari paket pandas.

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
>>> 
Ingin tahu
sumber
Apa yang sudah Anda coba dalam hal membuat peta panas atau penelitian? Tanpa mengetahui lebih banyak, saya sarankan untuk mengonversi data Anda dan menggunakan metode ini
pelajar
@joelostblom Ini bukan jawaban, ini komentar, tapi masalahnya adalah saya tidak punya cukup reputasi untuk bisa memberi komentar. Saya sedikit bingung karena nilai keluaran dari matriks dan larik aslinya sama sekali berbeda. Saya ingin mencetak di peta panas nilai yang sebenarnya, tidak berbeda. Adakah yang bisa menjelaskan mengapa ini terjadi. Sebagai contoh: * data terindeks asli: aaa / A = 2.431645 * nilai yang dicetak di peta panas: aaa / A = 1.06192
Pengawas Keuangan
@Monitotier Silakan ajukan pertanyaan baru dan sertakan contoh kode lengkap dari apa yang telah Anda coba. Ini adalah cara terbaik untuk membuat seseorang membantu Anda mencari tahu apa yang salah! Anda dapat menautkan ke pertanyaan ini jika menurut Anda itu relevan.
joelostblom

Jawaban:

82

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

Ini memberi:

Sampel keluaran

chthonicdaemon
sumber
5
Ada beberapa diskusi yang menarik di sini tentang pcolorvs imshow.
LondonRob
1
… Dan juga pcolormesh, yang dioptimalkan untuk jenis grafik ini.
Eric O Lebigot
180

Bagi orang yang melihat ini hari ini, saya akan merekomendasikan Seaborn heatmap()seperti yang didokumentasikan di sini .

Contoh di atas akan dilakukan sebagai berikut:

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)

Di mana %matplotlibfungsi ajaib IPython untuk mereka yang tidak terbiasa.

Brideau
sumber
Mengapa Anda tidak menggunakan panda?
tommy.carstensen
9
Seaborn dan Pandas bekerja sama dengan baik, jadi Anda masih akan menggunakan Pandas untuk mendapatkan data Anda ke bentuk yang tepat. Seaborn berspesialisasi dalam bagan statis, dan membuat peta panas dari Pandas DataFrame sangat sederhana.
Brideau
Sepertinya link ini sudah mati; bisakah kamu memperbaruinya !? Selanjutnya, bagaimana saya menjalankan kode di atas import matplotlib.pyplot as plt?
Cleb
Hai @Cleb, saya harus memperbaruinya ke halaman arsip karena sepertinya tidak ada di mana pun. Lihatlah dokumen mereka untuk menggunakannya dengan pyplot: stanford.edu/~mwaskom/software/seaborn-dev/tutorial/…
Brideau
Gunakan import matplotlib.pyplot as pltalih-alih %matplotlib inlinedan selesaikan dengan plt.show()untuk benar-benar melihat plotnya.
tsveti_iko
83

Jika Anda tidak memerlukan plot per kata, dan Anda hanya tertarik untuk menambahkan warna untuk mewakili nilai dalam format tabel, Anda dapat menggunakan style.background_gradient()metode bingkai data pandas. Metode ini mewarnai tabel HTML yang ditampilkan saat melihat bingkai data panda di misalnya, Notebook JupyterLab dan hasilnya mirip dengan menggunakan "pemformatan bersyarat" di perangkat lunak spreadsheet:

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

masukkan deskripsi gambar di sini

Untuk penggunaan terperinci, silakan lihat jawaban yang lebih terperinci yang saya berikan pada topik yang sama sebelumnya dan bagian gaya dari dokumentasi panda .

joelostblom
sumber
4
Sial, jawaban ini sebenarnya yang saya cari. IMO, harus lebih tinggi (+1).
ponadto
7
Jawaban ini bukanlah solusi yang valid untuk pertanyaan yang diposting. Pewarnaan gradien latar belakang panda memperhitungkan setiap baris atau setiap kolom secara terpisah sementara pewarnaan pcolor atau pcolormesh matplotlib memperhitungkan seluruh matriks. Ambil contoh kode berikut pd.DataFrame([[1, 1], [0, 3]]).style.background_gradient(cmap='summer') menghasilkan tabel dengan dua tabel, masing-masing dengan warna berbeda.
Toni Penya-Alba
4
@ ToniPenya-Alba Pertanyaannya adalah tentang bagaimana membuat peta panas dari pandas dataframe, bukan bagaimana meniru perilaku pcolor atau pcolormesh. Jika Anda tertarik dengan yang terakhir untuk tujuan Anda sendiri, Anda dapat menggunakan axis=None(sejak pandas 0.24.0).
joelostblom
2
@joelostblom Saya tidak bermaksud komentar saya seperti dalam "mereproduksi satu alat atau perilaku lain" tetapi seperti dalam "biasanya seseorang menginginkan semua elemen dalam matriks mengikuti skala yang sama daripada memiliki skala yang berbeda untuk setiap baris / kolom". Seperti yang Anda tunjukkan, axis=Nonecapai itu dan, menurut saya, itu harus menjadi bagian dari jawaban Anda (khususnya karena tampaknya tidak didokumentasikan 0 )
Toni Penya-Alba
2
@ ToniPenya-Alba Saya sudah membuat axis=Nonebagian dari jawaban rinci yang saya tautkan di atas, bersama dengan beberapa opsi lain karena saya setuju dengan Anda bahwa beberapa opsi ini memungkinkan perilaku yang secara umum diinginkan. Saya juga melihat kurangnya dokumentasi kemarin dan membuka PR .
joelostblom
17

sns.heatmapApi yang berguna ada di sini . Periksa parameternya, ada sejumlah bagus. Contoh:

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)

masukkan deskripsi gambar di sini

Brad Solomon
sumber
4

Jika Anda menginginkan peta panas interaktif dari Pandas DataFrame dan Anda menjalankan buku catatan Jupyter, Anda dapat mencoba Widget Clustergrammer-Widget interaktif, lihat buku catatan interaktif di NBViewer di sini , dokumentasi di sini

masukkan deskripsi gambar di sini

Dan untuk kumpulan data yang lebih besar Anda dapat mencoba widget Clustergrammer2 WebGL dalam pengembangan (contoh notebook di sini )

Nick Fernandez
sumber
1
wow ini sangat rapi! senang melihat beberapa paket bagus datang ke python - lelah harus menggunakan magics R
Sos
2

Harap dicatat bahwa penulis seabornhanya ingin seaborn.heatmap bekerja dengan kerangka data kategorikal. Ini tidak umum.

Jika indeks dan kolom Anda adalah nilai numerik dan / atau tanggal waktu, kode ini akan membantu Anda dengan baik.

Fungsi pemetaan panas Matplotlib pcolormeshmembutuhkan bins, bukan indeks , jadi ada beberapa kode keren untuk membuat bins dari indeks dataframe Anda (bahkan jika indeks Anda tidak berjarak sama!).

Sisanya sederhana np.meshgriddan plt.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)

Sebut saja menggunakan heatmap(df), dan lihat menggunakan plt.show().

masukkan deskripsi gambar di sini

OrangeSherbet
sumber