Search code examples
python-3.xmatrixplotheatmapseaborn

Seaborn Complex Heatmap---drawing circles within tiles to denote complex annotation


I have two data-frames in python.

data_A
Name  X  Y
A     1  0
B     1  1
C     0  0

data_B
Name  X  Y
A     0  1
B     1  1
C     0  1

I would like to overlap these heatmaps, where if it is a 1 in data_frame A, then the tile is colored purple (or any color), but if it's a 1 in data_frame B, then a circle is drawn (preferably the first one).

So for example, the heatmap would show A[,X][1] colored purple, but those with 1 in both data frames would be purple with a dot. C[,Y][3] would have just a dot, while C[,X][3] would have nothing.

I can seem to mask, with seaborn, and plot two heatmaps with different colors, but the color differential isn't clear enough that a user can simply see that a tile has only one versus both. I think having a circle to denote a positive in one matrix would be better.

Does anyone have an idea of how to plot circles onto a heatmap using seaborn?


Solution

  • To show a heatmap you may use an imshow plot. To show some dots, you may use a scatter plot. Then just plot both in the same axes.

    import pandas as pd
    import matplotlib.pyplot as plt
    import numpy as np
    
    dfA = pd.DataFrame([[1,0],[1,1],[0,0]], columns=list("XY"), index=list("ABC"))
    dfB = pd.DataFrame([[0,1],[1,1],[0,1]], columns=list("XY"), index=list("ABC"))
    
    assert dfA.shape == dfB.shape
    
    x = np.arange(0,len(dfA.columns))
    y = np.arange(0,len(dfB.index))
    X,Y=np.meshgrid(x,y)
    
    fig, ax = plt.subplots(figsize=(2.6,3))
    ax.invert_yaxis()
    ax.imshow(dfA.values, aspect="auto", cmap="Purples")
    
    cond = dfB.values == 1
    ax.scatter(X[cond], Y[cond], c="crimson", s=100)
    
    ax.set_xticks(x)
    ax.set_yticks(y)
    ax.set_xticklabels(dfA.columns)
    ax.set_yticklabels(dfA.index)
    plt.show()
    

    enter image description here

    Alternatives to using a dot to show several datasets on the same heatmap could also