Seaborn热图多变量

2024-06-07 17:31:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我想创建一个热图,在一个单元格中显示三个变量的颜色

  • 如果在3个单独的轴上绘制,则有代码显示此情况
  • 已尝试将所有颜色覆盖在彼此之上,这将显示所有三个颜色贴图,但仅显示来自最终变量的数据

有没有办法在每个图中使用单元格的一部分,所以第一个变量使用左三分之一、第二个中间和第三个右三分之一

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.colors
import seaborn as sns

dfv = pd.DataFrame(data=[[968.942, 20.338, 68.17, 'Oxford/AstraZeneca, Sinopharm/Beijing'], [9.721, 0.116, 62.43, 'Moderna, Pfizer/BioNTech'], [12.219, 0.0, 62.25, 'Oxford/AstraZeneca'], [642.741, 0.0, 54.62, 'Oxford/AstraZeneca, Pfizer/BioNTech, Sinopharm/Beijing'], [0.0, 0.0, 53.72, 'Pfizer/BioNTech'], [0.0, 0.0, 51.59, 'Pfizer/BioNTech'], [193.42, 0.303, 51.38, 'Oxford/AstraZeneca, Pfizer/BioNTech, Sinopharm/Beijing, Sinopharm/Wuhan, Sputnik V'], [52.738, 0.0, 51.14, 'Moderna, Oxford/AstraZeneca, Pfizer/BioNTech'], [0.0, 0.0, 50.67, 'Pfizer/BioNTech'], [32.95, 0.236, 50.22, 'Moderna, Oxford/AstraZeneca, Pfizer/BioNTech'], [0.0, 0.0, 43.66, 'Moderna, Pfizer/BioNTech'], [152.486, 2.196, 43.0, 'Johnson&Johnson, Moderna, Pfizer/BioNTech'], [316.433, 5.545, 42.11, 'Pfizer/BioNTech, Sinovac'], [221.14, 18.84, 40.51, 'Moderna, Oxford/AstraZeneca, Pfizer/BioNTech, Sinopharm/Beijing, Sputnik V'], [644.778, 4.114, 40.28, 'Oxford/AstraZeneca, Pfizer/BioNTech, Sinopharm/Beijing, Sputnik V']],
            columns=['new_cases_smoothed_per_million', 'new_deaths_per_million','people_vaccinated_per_hundred', 'vaccines'],
            index=['SYC', 'ISR', 'BTN', 'MDV', 'CYM', 'BMU', 'ARE', 'MLT', 'ABW', 'GBR', 'CUW', 'USA', 'CHL', 'HUN', 'BHR'])

# keep order so can reindex
o = dfv.sort_values("people_vaccinated_per_hundred", ascending=False).index

# explode out vaccines being deployed in a country, add to index
dfv = (dfv.join(dfv["vaccines"].apply(lambda csv: [v.strip() for v in csv.split(",")]).explode(), rsuffix="_r")
       .set_index("vaccines_r", append=True)
      )

fig, ax = plt.subplots(4,1, figsize=(16, 8), sharex=True)

for i, m in enumerate(["new_cases_smoothed_per_million","new_deaths_per_million","people_vaccinated_per_hundred"]):
    cmap = matplotlib.colors.LinearSegmentedColormap.from_list("", [["whitesmoke","yellow"],
                                                                    ["mistyrose","tomato","red"],
                                                                    ["aqua","limegreen","green"]][i])
    dfhm = dfv.loc[:,m].unstack(1).reindex(o).T

    sns.heatmap(dfhm, cmap=cmap, ax=ax[i], linewidth=.5, linecolor="whitesmoke",
               cbar_kws={'label': ["Infections","Deaths","Vaccinated"][i]})
    ax[i].xaxis.label.set_visible(False)
    ax[i].yaxis.label.set_visible(False)
    
    # trying to plot all three variables on one heatmap, ideally where 1/3 of cell is used for each variable
    sns.heatmap(dfhm, ax=ax[3], cmap=cmap , linewidth=.5, linecolor="whitesmoke")
    ax[3].yaxis.label.set_visible(False)

enter image description here


Tags: importnewaxmodernacmapoxfordpermillion
1条回答
网友
1楼 · 发布于 2024-06-07 17:31:42

我继续对此进行研究,并探索了使用plt.implot()的选项

  • 更改的要求。。。死亡和新感染实际上是按国家,而不是按国家和疫苗
  • 使用seabord生成多个热图,并使用gridspec控制间距。加上彩色条,不需要用于死亡和新病例。颜色显示一个国家接种了疫苗,但仍然存在病例和死亡问题
# keep order so can reindex
o = df.sort_values("people_vaccinated_per_hundred", ascending=False).index

# explode out vaccines being deployed in a country, add to index
dfv = (df.join(df["vaccines"].apply(lambda csv: [v.strip() for v in csv.split(",")]).explode(), rsuffix="_r")
       .set_index("vaccines_r", append=True)
      )

# ration of heights... NB colorbar uses space...
vh = len(np.unique(dfv.index.get_level_values(1)))

fig, ax = plt.subplots(3,1, figsize=(16, 3), sharex=True, gridspec_kw={"hspace":0., 'height_ratios': [1/vh, 1/vh, (vh+3)/vh]})

for i, m in enumerate(["new_cases_smoothed_per_million","new_deaths_per_million","people_vaccinated_per_hundred"]):
    cmap = matplotlib.colors.LinearSegmentedColormap.from_list("", [["whitesmoke","yellow"],
                                                                    ["whitesmoke","red"],
                                                                    ["aqua","limegreen","green"]][i])
    if m=="people_vaccinated_per_hundred":
        dfhm = dfv
        cbar={"cbar":True, "cbar_kws":{"orientation":'horizontal', "aspect":90}}
    else:
        dfhm = df.assign(all=m.replace("_per_million", "").replace("new_","")).set_index("all", append=True)
        cbar={"cbar":False}

    dfhm = dfhm.loc[:,m].unstack(1).reindex(o).T

    sns.heatmap(dfhm, cmap=cmap, ax=ax[i], linewidth=.5, linecolor="whitesmoke", **cbar, xticklabels=True, yticklabels=True)
    ax[i].yaxis.label.set_visible(False)
    ax[i].tick_params(axis='y', labelrotation = 0)

enter image description here

相关问题 更多 >

    热门问题