使用 Pandas 数据帧中的值注释热图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21024066/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 21:32:07  来源:igfitidea点击:

Annotate heatmap with value from Pandas dataframe

pythontextmatplotlibpandasheatmap

提问by jonas

I would like to annotate a heatmap with the values that I pass from a dataframe into the function below. I have looked at matplotlib.text but have not been able to get the values from my dataframe in a desired way in my heatmap. I have pasted in my function for generating a heatmap below, after that my dataframe and the output from the heatmap call. I would like to plot each value from my dataframe in the center of each cell in the heatmap.

我想用我从数据帧传递到下面的函数的值来注释热图。我查看了 matplotlib.text,但无法在我的热图中以所需的方式从我的数据框中获取值。我在下面粘贴了用于生成热图的函数,然后是我的数据框和热图调用的输出。我想在热图中每个单元格的中心绘制我的数据框中的每个值。

Function for generating a heatmap:

生成热图的函数:

import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors

def heatmap_binary(df,
            edgecolors='w',
            #cmap=mpl.cm.RdYlGn,
            log=False):    
    width = len(df.columns)/7*10
    height = len(df.index)/7*10

    fig, ax = plt.subplots(figsize=(20,10))#(figsize=(width,height))

    cmap, norm = mcolors.from_levels_and_colors([0, 0.05, 1],['Teal', 'MidnightBlue'] ) # ['MidnightBlue', Teal]['Darkgreen', 'Darkred']

    heatmap = ax.pcolor(df ,
                        edgecolors=edgecolors,  # put white lines between squares in heatmap
                        cmap=cmap,
                        norm=norm)


    ax.autoscale(tight=True)  # get rid of whitespace in margins of heatmap
    ax.set_aspect('equal')  # ensure heatmap cells are square
    ax.xaxis.set_ticks_position('top')  # put column labels at the top
    ax.tick_params(bottom='off', top='off', left='off', right='off')  # turn off ticks

    plt.yticks(np.arange(len(df.index)) + 0.5, df.index, size=20)
    plt.xticks(np.arange(len(df.columns)) + 0.5, df.columns, rotation=90, size= 15)

    # ugliness from http://matplotlib.org/users/tight_layout_guide.html
    from mpl_toolkits.axes_grid1 import make_axes_locatable
    divider = make_axes_locatable(ax)
    cax = divider.append_axes("right", "3%", pad="1%")
    plt.colorbar(heatmap, cax=cax)


plt.show()

Herre is an example of My dataframe :

这是我的数据框的示例:

dataframe :

             0-5 km / h  5-40 km / h  40-80 km / h  80-120 km / h  \
NORDIC         0.113955     0.191888      0.017485      -0.277528   
MIDDLE  EU     0.117903     0.197084     -0.001447      -0.332677   
KOREA          0.314008     0.236503     -0.067174      -0.396518   
CHINA          0.314008     0.236503     -0.067174      -0.396518   

             120-160 km / h  160-190 km / h  190 km / h  
NORDIC            -0.054365        0.006107    0.002458  
MIDDLE  EU         0.002441        0.012097    0.004599  
KOREA             -0.087191        0.000331    0.000040  
CHINA             -0.087191        0.000331    0.000040  

Generating the heatmap:

生成热图:

heatmap_binary(dataframe)

enter image description here

在此处输入图片说明

Any ideas?

有任何想法吗?



Update to clarify my problem

更新以澄清我的问题

I tried the proposed solution from question which has the result I'm looking for: how to annotate heatmap with text in matplotlib?However, I still have a problem using the matplotlib.text function for positioning the values in the heatmap: Here is my cod for trying this solution:

我尝试了问题中提出的解决方案,该解决方案得到了我正在寻找的结果: 如何在 matplotlib 中使用文本注释热图?但是,使用 matplotlib.text 函数在热图中定位值仍然存在问题:这是我尝试此解决方案的代码:

import matplotlib.pyplot as plt
import numpy as np


data = dataframe.values
heatmap_binary(dataframe)

for y in range(data.shape[0]):
    for x in range(data.shape[1]):
        plt.text(data[y,x] +0.05 , data[y,x] + 0.05, '%.4f' % data[y, x], #data[y,x] +0.05 , data[y,x] + 0.05
                 horizontalalignment='center',
                 verticalalignment='center',
                 color='w')

#plt.colorbar(heatmap)

plt.show()

added plot: (different coloring but same problem) enter image description here

添加的情节:(不同的颜色,但同样的问题) 在此处输入图片说明

回答by 8one6

The values you were using for your coordinates in your forloop were screwed up. Also you were using plt.colorbarinstead of something cleaner like fig.colorbar. Try this (it gets the job done, with no effort made to otherwise cleanup the code):

您在for循环中用于坐标的值被搞砸了。您还使用plt.colorbar了诸如fig.colorbar. 试试这个(它完成了工作,无需努力以其他方式清理代码):

def heatmap_binary(df,
            edgecolors='w',
            #cmap=mpl.cm.RdYlGn,
            log=False):    
    width = len(df.columns)/7*10
    height = len(df.index)/7*10

    fig, ax = plt.subplots(figsize=(20,10))#(figsize=(width,height))

    cmap, norm = mcolors.from_levels_and_colors([0, 0.05, 1],['Teal', 'MidnightBlue'] ) # ['MidnightBlue', Teal]['Darkgreen', 'Darkred']

    heatmap = ax.pcolor(df ,
                        edgecolors=edgecolors,  # put white lines between squares in heatmap
                        cmap=cmap,
                        norm=norm)
    data = df.values
    for y in range(data.shape[0]):
        for x in range(data.shape[1]):
            plt.text(x + 0.5 , y + 0.5, '%.4f' % data[y, x], #data[y,x] +0.05 , data[y,x] + 0.05
                 horizontalalignment='center',
                 verticalalignment='center',
                 color='w')


    ax.autoscale(tight=True)  # get rid of whitespace in margins of heatmap
    ax.set_aspect('equal')  # ensure heatmap cells are square
    ax.xaxis.set_ticks_position('top')  # put column labels at the top
    ax.tick_params(bottom='off', top='off', left='off', right='off')  # turn off ticks

    ax.set_yticks(np.arange(len(df.index)) + 0.5)
    ax.set_yticklabels(df.index, size=20)
    ax.set_xticks(np.arange(len(df.columns)) + 0.5)
    ax.set_xticklabels(df.columns, rotation=90, size= 15)

    # ugliness from http://matplotlib.org/users/tight_layout_guide.html
    from mpl_toolkits.axes_grid1 import make_axes_locatable
    divider = make_axes_locatable(ax)
    cax = divider.append_axes("right", "3%", pad="1%")
    fig.colorbar(heatmap, cax=cax)

Then

然后

df1 = pd.DataFrame(np.random.choice([0, 0.75], size=(4,5)), columns=list('ABCDE'), index=list('WXYZ'))
heatmap_binary(df1)

gives:

给出:

The Answer

答案

回答by JayaZ

This functionality is provided by the seabornpackage. It can produce maps like

此功能由seaborn包提供。它可以生成像

Example annotated heatmap

带注释的热图示例

An example usage of seabornis

seaborn 的一个示例用法是

import seaborn as sns
sns.set()

# Load the example flights dataset and conver to long-form
flights_long = sns.load_dataset("flights")
flights = flights_long.pivot("month", "year", "passengers")

# Draw a heatmap with the numeric values in each cell
sns.heatmap(flights, annot=True, fmt="d", linewidths=.5)

回答by Joe Kington

This is because you're using plt.textafter you've added another axes.

这是因为您在plt.text添加另一个轴之后使用。

The state machine will plot on the currentaxes, and after you've added a new one with divider.append_axes, the colorbar's axes is the current one. (Just calling plt.colorbarwill not cause this, as it sets the current axes back to the original one afterwards if it creates the axes itself. If a specific axes object is passed in using the caxkwarg, it doesn't reset the "current" axes, as that's not what you'd normally want.)

状态机将绘制在当前轴上,并且在您添加了一个新轴之后divider.append_axes,颜色条的轴是当前轴。(只是调用plt.colorbar不会导致这种情况,因为如果它自己创建轴,它会将当前轴设置回原来的轴。如果使用caxkwarg传入特定的轴对象,它不会重置“当前”轴,因为那不是您通常想要的。)

Things like this are the main reason that you'll see so many people advising that you use the OO interface to matplotlib instead of the state machine interface. That way you know which axes object that you're plotting on.

像这样的事情是你会看到这么多人建议你使用面向 matplotlib 的 OO 接口而不是状态机接口的主要原因。这样你就知道你正在绘制哪个轴对象。

For example, in your case, you could have heatmap_binaryreturn the axobject that it creates, and the plot using ax.textinstead of plt.text(and similar for the other plotting methods).

例如,在您的情况下,您可以heatmap_binary返回ax它创建的对象,并使用ax.text代替plt.text(和其他绘图方法类似)的绘图。

回答by Fariliana Eri

You also can use plotly.figure_factoryto create heatmap from DataFrame, but you have convertit into list.

您还可以使用plotly.figure_factory创建热图的数据帧,但你必须转换成列表

    import plotly.figure_factory as ff

    z = [your_dataframe].values.tolist()
    x = [your_dataframe].columns.tolist()
    y = [your_dataframe].index.tolist()

    fig = ff.create_annotated_heatmap(z, x=x, y=y, annotation_text=z, colorscale='viridis')

    # for add annotation into Heatmap
    for i in range(len(fig.layout.annotations)):
        fig.layout.annotations[i].font.size = 12

    # show your Heatmap
    fig.show()