Создание тепловой карты из pandas DataFrame

112

У меня есть фрейм данных, созданный из пакета Python Pandas. Как создать тепловую карту с помощью DataFrame из пакета 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
>>> 
Любопытный
источник
Что вы пробовали в плане создания тепловой карты или исследования? Не зная больше, я бы порекомендовал преобразовать ваши данные и использовать этот метод
ученик
@joelostblom Это не ответ, это комментарий, но проблема в том, что у меня недостаточно репутации, чтобы оставить комментарий. Я немного сбит с толку, потому что выходное значение матрицы и исходного массива совершенно разные. Я хотел бы напечатать на тепловой карте реальные значения, а не какие-то другие. Может кто-нибудь объяснить мне, почему это происходит. Например: * исходные индексированные данные: aaa / A = 2,431645 * напечатанные значения на тепловой карте: aaa / A = 1.06192
Monitotier
@Monitotier Задайте новый вопрос и включите полный пример кода того, что вы пробовали. Это лучший способ попросить кого-нибудь помочь вам разобраться в том, что не так! Вы можете дать ссылку на этот вопрос, если считаете, что он актуален.
joelostblom

Ответы:

82

Вы хотите 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()

Это дает:

Выходной образец

хтонический демон
источник
5
Там какое - то интересное обсуждение здесь о pcolorсравнении imshow.
LondonRob
1
… А также pcolormeshоптимизированный для такого рода графики.
Эрик О Лебигот
180

Тем, кто смотрит на это сегодня, я бы порекомендовал Seaborn, heatmap()как описано здесь .

Пример выше был бы выполнен следующим образом:

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)

Где %matplotlibволшебная функция IPython для незнакомых?

Brideau
источник
Почему бы вам не использовать панд?
tommy.carstensen
9
Seaborn и Pandas прекрасно работают вместе, так что вы все равно будете использовать Pandas для придания вашим данным правильной формы. Тем не менее, Seaborn специализируется на статических диаграммах и упрощает создание тепловой карты из Pandas DataFrame.
Бридо
Кажется, эта ссылка мертва; не могли бы вы его обновить !? Кроме того, как мне запустить приведенный выше код import matplotlib.pyplot as plt?
Cleb
Привет, @Cleb, мне пришлось обновить его до заархивированной страницы, потому что он нигде не выглядит. Взгляните на их документацию по использованию его с pyplot: stanford.edu/~mwaskom/software/seaborn-dev/tutorial/…
Brideau 01
Используйте import matplotlib.pyplot as pltвместо %matplotlib inlineи закончите plt.show(), чтобы увидеть сюжет.
tsveti_iko
84

Если вам не нужен график, например, и вы просто заинтересованы в добавлении цвета для представления значений в формате таблицы, вы можете использовать style.background_gradient()метод фрейма данных pandas. Этот метод окрашивает HTML-таблицу, которая отображается при просмотре фреймов данных pandas, например, в JupyterLab Notebook, и результат аналогичен использованию «условного форматирования» в программном обеспечении для работы с электронными таблицами:

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

введите описание изображения здесь

Для подробного использования, пожалуйста, просмотрите более подробный ответ, который я дал ранее по той же теме, и раздел стилей документации pandas .

Joelostblom
источник
4
Блин, это именно тот ответ, который я искал. ИМО, должно быть выше (+1).
ponadto
7
Этот ответ не является правильным решением поставленного вопроса. Градиентная окраска фона Pandas учитывает либо каждую строку, либо каждый столбец отдельно, в то время как окраска pcolor или pcolormesh matplotlib учитывает всю матрицу. Возьмем, к примеру, следующий код, который pd.DataFrame([[1, 1], [0, 3]]).style.background_gradient(cmap='summer') приводит к таблице с двумя таблицами, каждая из которых имеет свой цвет.
Тони Пенья-Альба
4
@ ToniPenya-Alba Вопрос в том, как сгенерировать тепловую карту из фрейма данных pandas, а не в том, как воспроизвести поведение pcolor или pcolormesh. Если последний вам интересен для своих целей, вы можете использовать axis=None(начиная с pandas 0.24.0).
joelostblom 05
2
@joelostblom Я не имел в виду свой комментарий как «воспроизвести тот или иной инструмент», а как «обычно нужно, чтобы все элементы в матрице следовали одному и тому же масштабу, а не имели разные масштабы для каждой строки / столбца». Как вы указываете, это axis=Noneдостигается, и, на мой взгляд, это должно быть частью вашего ответа (особенно потому, что это, похоже, не задокументировано 0 )
Тони Пенья-Альба
2
@ ToniPenya-Alba Я уже сделал axis=Noneчасть подробного ответа, на который я ссылаюсь выше, вместе с несколькими другими вариантами, потому что я согласен с вами, что некоторые из этих параметров обеспечивают обычно желаемое поведение. Еще вчера заметил отсутствие документации и открыл пиар .
joelostblom
17

Полезный sns.heatmapapi здесь . Ознакомьтесь с параметрами, их очень много. Пример:

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)

введите описание изображения здесь

Брэд Соломон
источник
4

Если вам нужна интерактивная тепловая карта из Pandas DataFrame и вы используете записную книжку Jupyter, вы можете попробовать интерактивный виджет Clustergrammer-Widget , см. Интерактивную записную книжку на NBViewer здесь , документация здесь

введите описание изображения здесь

А для больших наборов данных вы можете попробовать находящийся в разработке виджет Clustergrammer2 WebGL (пример блокнота здесь )

Ник Фернандес
источник
1
вау, это очень здорово! приятно видеть несколько хороших пакетов, прибывающих в python - устал от необходимости использовать R magics
Sos
2

Пожалуйста , обратите внимание , что авторы seabornтолько хотят seaborn.heatmap работать с категорическим dataframes. Это не общее.

Если ваш индекс и столбцы являются числовыми значениями и / или значениями даты и времени, этот код вам пригодится.

Для функции теплового отображения Matplotlib pcolormeshтребуются бункеры вместо индексов , поэтому есть некоторый причудливый код для создания бинов из индексов вашего фрейма данных (даже если ваш индекс неравномерно распределен!).

Остальное просто np.meshgridи 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)

Назовите это using heatmap(df)и посмотрите, как это делается plt.show().

введите описание изображения здесь

OrangeSherbet
источник