Erstellen einer Heatmap aus Pandas DataFrame

112

Ich habe einen Datenrahmen aus Pythons Pandas-Paket generiert. Wie kann ich eine Heatmap mit DataFrame aus dem Pandas-Paket erstellen?

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
>>> 
Neugierig
quelle
Was haben Sie versucht, um eine Heatmap oder Forschung zu erstellen? Ohne mehr zu wissen, würde ich empfehlen, Ihre Daten zu konvertieren und diese Methode zu verwenden
Lernende
@joelostblom Dies ist keine Antwort, ist ein Kommentar, aber das Problem ist, dass ich nicht genug Ruf habe, um einen Kommentar abgeben zu können. Ich bin ein bisschen verblüfft, weil der Ausgabewert der Matrix und des ursprünglichen Arrays völlig unterschiedlich sind. Ich möchte die realen Werte in die Heatmap drucken, nicht einige andere. Kann mir jemand erklären, warum das passiert? Zum Beispiel: * indizierte Originaldaten: aaa / A = 2.431645 * gedruckte Werte in der Heatmap: aaa / A = 1.06192
Monitotier
@Monitotier Bitte stellen Sie eine neue Frage und fügen Sie ein vollständiges Codebeispiel für das bei, was Sie versucht haben. Dies ist der beste Weg, um jemanden zu finden, der Ihnen hilft, herauszufinden, was falsch ist! Sie können auf diese Frage verlinken, wenn Sie sie für relevant halten.
Joelostblom

Antworten:

82

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

Das gibt:

Beispiel ausgeben

chthonicdaemon
quelle
5
Es gibt einige interessante Diskussion hier über pcolorvs. imshow.
LondonRob
1
… Und auch pcolormesh, das für diese Art von Grafik optimiert ist.
Eric O Lebigot
179

Für Leute, die sich das heute ansehen, würde ich das Seaborn empfehlen, heatmap()wie hier dokumentiert .

Das obige Beispiel würde wie folgt durchgeführt:

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)

Wo %matplotlibist eine IPython-Zauberfunktion für Unbekannte?

Brideau
quelle
Warum würdest du keine Pandas benutzen?
Tommy.carstensen
9
Seaborn und Pandas arbeiten gut zusammen, sodass Sie Pandas weiterhin verwenden würden, um Ihre Daten in die richtige Form zu bringen. Seaborn ist jedoch auf statische Diagramme spezialisiert und macht das Erstellen einer Heatmap aus einem Pandas DataFrame zum Kinderspiel.
Brideau
Dieser Link scheint tot zu sein. Könntest du es aktualisieren? Wie würde ich den obigen Code ausführen import matplotlib.pyplot as plt?
Cleb
Hey @Cleb, ich musste es auf die archivierte Seite aktualisieren, weil es nirgendwo so aussieht. Schauen Sie sich ihre Dokumente an, um sie mit pyplot zu verwenden: stanford.edu/~mwaskom/software/seaborn-dev/tutorial/…
Brideau
Verwenden Sie import matplotlib.pyplot as pltanstelle von %matplotlib inlineund beenden Sie mit, plt.show()um die Handlung tatsächlich zu sehen.
Tsveti_iko
83

Wenn Sie kein Plot per say benötigen und einfach nur Farbe hinzufügen möchten, um die Werte in einem Tabellenformat darzustellen, können Sie die style.background_gradient()Methode des Pandas-Datenrahmens verwenden. Diese Methode färbt die HTML-Tabelle ein, die beim Anzeigen von Pandas-Datenrahmen im JupyterLab-Notizbuch angezeigt wird. Das Ergebnis ähnelt der Verwendung der "bedingten Formatierung" in der Tabellenkalkulationssoftware:

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

Geben Sie hier die Bildbeschreibung ein

Ausführliche Informationen zur Verwendung finden Sie in der ausführlicheren Antwort, die ich zuvor zum gleichen Thema gegeben habe, und im Abschnitt zum Styling der Pandas-Dokumentation .

joelostblom
quelle
4
Verdammt, diese Antwort ist tatsächlich die, nach der ich gesucht habe. IMO sollte höher sein (+1).
Ponadto
7
Diese Antwort ist keine gültige Lösung für die gestellte Frage. Die Hintergrundgradientenfärbung von Pandas berücksichtigt entweder jede Zeile oder jede Spalte einzeln, während die Farb- oder Farbfärbung von matplotlib die gesamte Matrix berücksichtigt. Nehmen wir zum Beispiel den folgenden Code, der pd.DataFrame([[1, 1], [0, 3]]).style.background_gradient(cmap='summer') zu einer Tabelle mit zwei Einsen führt, von denen jede eine andere Farbe hat.
Toni Penya-Alba
4
@ ToniPenya-Alba Die Frage ist, wie eine Heatmap aus einem Pandas-Datenrahmen generiert wird und nicht, wie das Verhalten von pcolor oder pcolormesh repliziert wird. Wenn Sie sich für letztere für letztere interessieren, können Sie diese verwenden axis=None(seit Pandas 0.24.0).
Joelostblom
2
@joelostblom Ich meinte meinen Kommentar nicht wie in "Das eine Werkzeug oder ein anderes Verhalten reproduzieren", sondern wie in "Normalerweise möchte man, dass alle Elemente in der Matrix der gleichen Skala folgen, anstatt für jede Zeile / Spalte unterschiedliche Skalen zu haben". Wie Sie betonen, wird dies axis=Noneerreicht und sollte meiner Meinung nach Teil Ihrer Antwort sein (zumal es nicht dokumentiert zu sein scheint 0 )
Toni Penya-Alba
2
@ ToniPenya-Alba Ich habe bereits einen axis=NoneTeil der detaillierten Antwort, auf die ich oben verweise , zusammen mit einigen anderen Optionen gemacht, da ich Ihnen zustimme, dass einige dieser Optionen häufig gewünschtes Verhalten ermöglichen. Ich habe gestern auch den Mangel an Dokumentation bemerkt und eine PR eröffnet .
Joelostblom
17

Nützliche sns.heatmapAPI ist hier . Überprüfen Sie die Parameter, es gibt eine gute Anzahl von ihnen. Beispiel:

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)

Geben Sie hier die Bildbeschreibung ein

Brad Solomon
quelle
4

Wenn Sie eine interaktive Heatmap von einem Pandas DataFrame möchten und ein Jupyter-Notizbuch ausführen, können Sie das interaktive Widget Clustergrammer-Widget ausprobieren. Das interaktive Notizbuch in NBViewer finden Sie hier , die Dokumentation hier

Geben Sie hier die Bildbeschreibung ein

Für größere Datenmengen können Sie das in der Entwicklung befindliche Clustergrammer2- WebGL-Widget (Beispielnotizbuch hier ) ausprobieren.

Nick Fernandez
quelle
1
wow das ist sehr ordentlich! Gut zu sehen, dass einige nette Pakete nach Python kommen - müde von der Verwendung von R magics
Sos
2

Bitte beachten Sie, dass die Autoren seabornnur wollen seaborn.heatmap mit kategorischen Datenrahmen an der Arbeit. Es ist nicht allgemein.

Wenn Ihr Index und Ihre Spalten numerische Werte und / oder Datums- / Uhrzeitwerte sind, ist dieser Code für Sie von Vorteil.

Für die Matplotlib-Heat-Mapping-Funktion pcolormeshsind Bins anstelle von Indizes erforderlich. Daher gibt es einen ausgefallenen Code zum Erstellen von Bins aus Ihren Dataframe-Indizes (auch wenn Ihr Index nicht gleichmäßig verteilt ist!).

Der Rest ist einfach np.meshgridund 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)

Nennen Sie es mit heatmap(df)und sehen Sie es mit plt.show().

Geben Sie hier die Bildbeschreibung ein

OrangeSherbet
quelle