Seaborn Facetgrid 中热图的变化

Posted

技术标签:

【中文标题】Seaborn Facetgrid 中热图的变化【英文标题】:Plots shifting in heatmaps in Seaborn Facetgrid 【发布时间】:2019-01-23 09:30:02 【问题描述】:

提前抱歉图片的数量,但它们有助于证明问题

我已经建立了一个数据框,其中包含膜厚度测量值,用于多个基材、多个层,作为坐标的函数:

|    | Sub | Result | Layer | Row | Col |
|----|-----|--------|-------|-----|-----|
|  0 |   1 |   2.95 | 3 - H |   0 |  72 |
|  1 |   1 |   2.97 | 3 - V |   0 |  72 |
|  2 |   1 |   0.96 | 1 - H |   0 |  72 |
|  3 |   1 |   3.03 | 3 - H | -42 |  48 |
|  4 |   1 |   3.04 | 3 - V | -42 |  48 |
|  5 |   1 |   1.06 | 1 - H | -42 |  48 |
|  6 |   1 |   3.06 | 3 - H |  42 |  48 |
|  7 |   1 |   3.09 | 3 - V |  42 |  48 |
|  8 |   1 |   1.38 | 1 - H |  42 |  48 |
|  9 |   1 |   3.05 | 3 - H | -21 |  24 |
| 10 |   1 |   3.08 | 3 - V | -21 |  24 |
| 11 |   1 |   1.07 | 1 - H | -21 |  24 |
| 12 |   1 |   3.06 | 3 - H |  21 |  24 |
| 13 |   1 |   3.09 | 3 - V |  21 |  24 |
| 14 |   1 |   1.05 | 1 - H |  21 |  24 |
| 15 |   1 |   3.01 | 3 - H | -63 |   0 |
| 16 |   1 |   3.02 | 3 - V | -63 |   0 |

这将持续超过 10 个潜艇(每批),每个潜艇 13 个站点,以及 3 层 - 这个df 是一个复合体。 我正在尝试将数据呈现为热图的 facetgrid(改编代码来自 How to make heatmap square in Seaborn FacetGrid - 谢谢!)

我可以很高兴地绘制df 的一个子集:

spam = df.loc[df.Sub== 6].loc[df.Layer == '3 - H']
spam_p= spam.pivot(index='Row', columns='Col', values='Result')

sns.heatmap(spam_p, cmap="plasma")

但是 - 有一些缺失的结果,其中层测量错误(返回“10000”)所以我用 NaN 替换了这些:

df.Result.replace(10000, np.nan)

为了绘制一个 facetgrid 以显示所有子/层,我编写了以下代码:

def draw_heatmap(*args, **kwargs):
    data = kwargs.pop('data')
    d = data.pivot(columns=args[0], index=args[1], 
    values=args[2])
    sns.heatmap(d, **kwargs)

fig = sns.FacetGrid(spam, row='Wafer', 
col='Feature', height=5, aspect=1)

fig.map_dataframe(draw_heatmap, 'Col', 'Row', 'Result', cbar=False, cmap="plasma", annot=True, annot_kws="size": 20)

产生:

它已自动调整轴以不显示任何存在 NaN 的位置。 我尝试过屏蔽(参见https://github.com/mwaskom/seaborn/issues/375),但Inconsistent shape between the condition and the input (got (237, 15) and (7, 7)) 出现错误。

结果是,当不使用裁剪后的数据集时(即df 而不是spam,代码会生成以下 Facetgrid):

在极端(边缘)坐标位置具有缺失值的绘图使绘图在轴内移动 - 这里显然都在左上角。 Sub #5,第 3-H 层应如下所示:

即有NaNs的地方留空。

为什么 facetgrid 将整个绘图向上和/或向左移动?另一种方法是根据子/层数动态生成子图(啊!)。

非常感谢您的任何帮助。

2 层 sub 5 的完整数据集:

    Sub Result  Layer   Row     Col
0   5   2.987   3 - H   0       72
1   5   0.001   1 - H   0       72
2   5   1.184   3 - H   -42     48
3   5   1.023   1 - H   -42     48
4   5   3.045   3 - H   42      48 
5   5   0.282   1 - H   42      48
6   5   3.083   3 - H   -21     24 
7   5   0.34    1 - H   -21     24
8   5   3.07    3 - H   21      24
9   5   0.41    1 - H   21      24
10  5   NaN     3 - H   -63     0
11  5   NaN     1 - H   -63     0
12  5   3.086   3 - H   0       0
13  5   0.309   1 - H   0       0
14  5   0.179   3 - H   63      0
15  5   0.455   1 - H   63      0
16  5   3.067   3 - H   -21    -24
17  5   0.136   1 - H   -21    -24
18  5   1.907   3 - H   21     -24
19  5   1.018   1 - H   21     -24
20  5   NaN     3 - H   -42    -48
21  5   NaN     1 - H   -42    -48
22  5   NaN     3 - H   42     -48
23  5   NaN     1 - H   42     -48
24  5   NaN     3 - H   0      -72
25  5   NaN     1 - H   0      -72

【问题讨论】:

我该如何测试这个? “sub”和“wafer”一样吗?什么最小数据集可以重现该问题? 是的 - 抱歉,这里有多个命名约定,我已经把这个问题放在一起来问这个问题。子 == 晶圆。 我将进行编辑以帮助生成测试数据集... 我添加了一个完整的数据集;但是,您总是可以多次使用这些数据来模拟多个潜艇(显然)。如果你这样做 - 包含更多(假)值可能是一个好主意,以强制使用不同/新的位置,即。用值替换一些 NaN。 【参考方案1】:

您可以创建唯一列和行标签的列表,并使用它们重新索引数据透视表。

cols = df["Col"].unique()
rows = df["Row"].unique()

pivot = data.pivot(...).reindex_axis(cols, axis=1).reindex_axis(rows, axis=0)

如在this answer 中看到的那样。

一些完整的代码:

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

r = np.repeat([0,-2,2,-1,1,-3],2)
row = np.concatenate((r, [0]*2, -r[::-1]))
c = np.array([72]*2+[48]*4 + [24]*4 + [0]* 3)
col = np.concatenate((c,-c[::-1]))

df = pd.DataFrame("Result" : np.random.rand(26),
                   "Layer" : list("AB")*13,
                   "Row" : row, "Col" : col)

df1 = df.copy()
df1["Sub"] = [5]*len(df1)
df1.at[10:11,"Result"] = np.NaN
df1.at[20:,"Result"] = np.NaN

df2 = df.copy()
df2["Sub"] = [3]*len(df2)
df2.at[0:2,"Result"] = np.NaN

df = pd.concat([df1,df2])

cols = np.unique(df["Col"].values)
rows = np.unique(df["Row"].values)

def draw_heatmap(*args, **kwargs):
    data = kwargs.pop('data')
    d = data.pivot(columns=args[0], index=args[1], 
                   values=args[2])
    d = d.reindex_axis(cols, axis=1).reindex_axis(rows, axis=0)
    print d
    sns.heatmap(d,  **kwargs)

grid = sns.FacetGrid(df, row='Sub', col='Layer', height=3.5, aspect=1 )

grid.map_dataframe(draw_heatmap, 'Col', 'Row', 'Result', cbar=False, 
                  cmap="plasma", annot=True)

plt.show()

【讨论】:

非常感谢 - 让我头疼不已。如果我理解正确,您的解决方案解释了为什么这些图的漂移不同;它们每个都需要为 col/rows 重新索引。并特别感谢您提供完整的代码,这对于查看一些专业级的方法来解决我的问题非常有帮助!真的很感激。

以上是关于Seaborn Facetgrid 中热图的变化的主要内容,如果未能解决你的问题,请参考以下文章

使用数据框更改绘图 Seaborn Facetgrid 中同一行的线型

在 Seaborn/其他库中聚合的 FacetGrid 图

在 seaborn 中的特定位置画一条线/注释 Facetgrid

seaborn使用FacetGrid函数可视化山脊图(Ridgeline Plot with Seaborn)

在 seaborn 中使用 FacetGrid 为所有方面重复 x 轴标签

Seaborn displot 'FacetGrid' 对象不可调用