154 votes

Création d'une carte thermique à partir d'un DataFrame pandas

J'ai un cadre de données généré par le paquet Pandas de Python. Comment puis-je générer une carte thermique en utilisant le DataFrame du paquet 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
>>>

4voto

OrangeSherbet Points 453

Veuillez noter que les auteurs de seaborn uniquement veulent seaborn.heatmap pour travailler avec des cadres de données catégoriques. Ce n'est pas général.

Si votre index et vos colonnes sont des valeurs numériques et/ou des dates, ce code vous sera utile.

Fonction de cartographie thermique de Matplotlib pcolormesh nécessite bacs au lieu de indices Il existe donc un code sophistiqué pour construire des bins à partir des indices de votre cadre de données (même si votre indice n'est pas uniformément espacé !).

Le reste est simplement np.meshgrid y 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)

Appelez-le en utilisant heatmap(df) et le voir en utilisant plt.show() .

enter image description here

4voto

Hamza Points 3028

Il est surprenant que personne n'ait mentionné des alternatives plus performantes, interactives et faciles à utiliser.

A) Vous pouvez utiliser plotly :

  1. Deux lignes seulement et vous obtenez :

  2. l'interactivité,

  3. échelle lisse,

  4. couleurs basées sur l'ensemble du cadre de données au lieu des colonnes individuelles,

  5. noms de colonnes et indices de lignes sur les axes,

  6. en faisant un zoom,

  7. panning,

  8. la possibilité intégrée de l'enregistrer en un clic au format PNG,

  9. auto-scaling,

  10. comparaison au survol,

  11. des bulles montrant les valeurs afin que la carte thermique soit toujours belle et que vous puissiez voir les valeurs où vous voulez :

    import plotly.express as px fig = px.imshow(df.corr()) fig.show()

enter image description here

B) Vous pouvez également utiliser le Bokeh :

Toutes les mêmes fonctionnalités, mais avec un peu plus d'inconvénients. Mais ça vaut quand même le coup si vous ne voulez pas vous inscrire à plotly et que vous voulez quand même toutes ces choses :

from bokeh.plotting import figure, show, output_notebook
from bokeh.models import ColumnDataSource, LinearColorMapper
from bokeh.transform import transform
output_notebook()
colors = ['#d7191c', '#fdae61', '#ffffbf', '#a6d96a', '#1a9641']
TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom"
data = df.corr().stack().rename("value").reset_index()
p = figure(x_range=list(df.columns), y_range=list(df.index), tools=TOOLS, toolbar_location='below',
           tooltips=[('Row, Column', '@level_0 x @level_1'), ('value', '@value')], height = 500, width = 500)

p.rect(x="level_1", y="level_0", width=1, height=1,
       source=data,
       fill_color={'field': 'value', 'transform': LinearColorMapper(palette=colors, low=data.value.min(), high=data.value.max())},
       line_color=None)
color_bar = ColorBar(color_mapper=LinearColorMapper(palette=colors, low=data.value.min(), high=data.value.max()), major_label_text_font_size="7px",
                     ticker=BasicTicker(desired_num_ticks=len(colors)),
                     formatter=PrintfTickFormatter(format="%f"),
                     label_standoff=6, border_line_color=None, location=(0, 0))
p.add_layout(color_bar, 'right')

show(p)

enter image description here

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X