【问题标题】:Seaborn heatmap - multiple variablesSeaborn 热图 - 多个变量
【发布时间】:2021-07-24 10:43:54
【问题描述】:

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

  • 如果绘制在 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)

【问题讨论】:

    标签: python pandas matplotlib seaborn


    【解决方案1】:

    我继续致力于此并探索使用 plt.implot() 的选项。

    • 更改的要求...死亡人数和新感染人数实际上是按国家/地区而不是按国家/地区和疫苗进行的
    • 使用 seabord 生成多个 热图 并使用 gridspec 控制间距。另外,不需要用于死亡和新病例的 colorbar。颜色显示一个国家/地区已接种疫苗但仍存在病例和死亡问题
    # 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)
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-13
      • 2019-01-23
      • 2018-09-05
      • 2020-08-04
      • 2021-02-26
      • 2019-10-30
      • 2021-05-07
      相关资源
      最近更新 更多