Python FaceGrid上的Seaborn颜色栏,用于具有标准化颜色映射的histplot

Python FaceGrid上的Seaborn颜色栏,用于具有标准化颜色映射的histplot,python,matplotlib,seaborn,Python,Matplotlib,Seaborn,我似乎无法使用seabornFaceGrid显示二维histplot的颜色栏。有人能告诉我丢失的链接吗 了解到已经讨论过类似的解决方案,我无法适应我的用例: 具体来说,我希望扩展下面的代码,以便显示颜色栏 import pandas as pd import numpy as np import seaborn as sns df = pd.DataFrame(list(zip([random.randint(0,10) for i in range(1000)], pd.to_date

我似乎无法使用seaborn
FaceGrid
显示二维
histplot
的颜色栏。有人能告诉我丢失的链接吗

了解到已经讨论过类似的解决方案,我无法适应我的用例:

  • 具体来说,我希望扩展下面的代码,以便显示颜色栏

    import pandas as pd
    import numpy as np
    import seaborn as sns
    
    df = pd.DataFrame(list(zip([random.randint(0,10) for i in range(1000)], pd.to_datetime(
                                [d.strftime('%Y-%m-%d') for d in pd.date_range('1800-01-01', periods=250, freq='1d')]+\
                                [d.strftime('%Y-%m-%d') for d in pd.date_range('1800-01-01', periods=250, freq='1d')]+\
                                [d.strftime('%Y-%m-%d') for d in pd.date_range('1800-01-01', periods=250, freq='1d')]+\
                                [d.strftime('%Y-%m-%d') for d in pd.date_range('1800-01-01', periods=250, freq='1d')]),
                                [random.choice(string.ascii_letters[26:30]) for i in range(1000)])), 
                                columns=["range","date","case_type"])
    df["range"][df["case_type"]=="A"] = [random.randint(4562,873645) for i in range(1000)] 
    df["range"][df["case_type"]=="C"] = [random.random() for i in range(1000)] 
    fg = sns.FacetGrid(df, col="case_type", col_wrap=2, sharey=False)
    
    fg.map(sns.histplot, "date", "range", stat="count", data=df)
    fg.set_xticklabels(rotation=30)
    fg.fig.show()
    
    
    目标是在刻面网格的右侧有一个颜色条,跨越整个图表-这里有两行,但可能会显示更多。显示的2D直方图具有一些非常不同的数据类型,因此每个箱子和颜色的计数可能非常不同,因此知道“深蓝色”是100还是1000很重要

    编辑:为了清晰起见,从评论中可以看出问题分为两个步骤:

  • 如何规范所有图和图之间的颜色编码
  • 使用标准化颜色映射在绘图右侧显示颜色栏

  • 我不确定是否有一种与生俱来的方式来实现你想要的情节。但是我们可以预先计算
    bin number
    vmin
    /
    vmax
    的合理值,并将它们应用于所有
    histplot

    import pandas as pd
    import seaborn as sns
    import matplotlib.pyplot as plt
    import numpy as np
    
    #generate a test dataset with different case_type probabilities
    np.random.seed(123)
    p1, p2, p3 = 0.8, 0.1, 0.03
    df = pd.DataFrame(list(zip(np.random.randint(0, 20, 1000), 
                      pd.to_datetime(4 * [d.strftime('%Y-%m-%d') for d in pd.date_range('1800-01-01', periods=250, freq='1d')]),
                      np.random.choice(list("ABCD"),size=1000, p=[p1, p2, p3, 1-(p1+p2+p3)]))), 
                      columns=["range","date","case_type"])
    df.loc[df.case_type == "A", "range"] *=   3
    df.loc[df.case_type == "B", "range"] *=  23
    df.loc[df.case_type == "C", "range"] *= 123
    
    #determine the bin number for the x-axis
    _, bin_edges = np.histogram(df["date"].dt.strftime("%Y%m%d").astype(int), bins="auto")
    bin_nr = len(bin_edges)-1
    
    #predetermine min and max count for each category
    c_types = df["case_type"].unique()
    vmin_list, vmax_list = [], []
    for c_type in c_types:
        arr, _, _ = np.histogram2d(df.loc[df.case_type == c_type, "date"], df.loc[df.case_type == c_type, "range"], bins=bin_nr)
        vmin_list.append(arr.min())
        vmax_list.append(arr.max())
        
    #find lowest and highest counts for all subplots
    vmin_all = min(vmin_list)
    vmax_all = max(vmax_list)
    
    #now we are ready to plot
    fg = sns.FacetGrid(df, col="case_type", col_wrap=2, sharey=False)
    #create common colorbar axis
    cax = fg.fig.add_axes([.92, .12, .02, .8])
    #map colorbar to colorbar axis with common vmin/vmax values
    fg.map(sns.histplot,"date", "range", stat="count", bins=bin_nr, vmin=vmin_all, vmax=vmax_all, cbar=True, cbar_ax=cax, data=df)
    #prevent overlap
    fg.fig.subplots_adjust(right=.9)
    fg.set_xticklabels(rotation=30)
    
    plt.show()
    
    样本输出:

    您可能还注意到,我更改了示例数据帧,使
    案例类型
    以不同的频率出现,否则您看不到
    组图
    之间有多大差异。您还应该知道,
    histplots
    是按照它们在数据框中的显示顺序打印的,这可能不是您希望在图形中看到的顺序


    免责声明:这主要基于。

    您的示例代码可能无法代表您的真实数据。您可以修改范围值(这与问题的上下文无关),但在每个类别中具有可比较的(尽管是随机的)分布。如果修改每个类别出现的概率,您将注意到两件事-不同面板中直方图箱的数量不同,相同的颜色将在不同面板中表示不同的值,从而使组合的颜色栏过时。有很多方法可以解决这个问题,但是你必须完全改变你的程序结构。如果你将
    cbar=True
    添加到
    fg.map()
    ,你甚至可能会看到颜色代码与你的版本之间的差异。谢谢。是的,每个子图的
    cbar
    确实有效,但它占用了大量空间,因此我的目标是将条形图放在右边距上。解决颜色编码的问题是我问题动机的一部分。所以,你真正的问题不是如何创建颜色条,而是如何规范HistPlot,使一种颜色在所有面板中代表相同的值?是的,实际上两者都是,规范化histplots颜色编码并在右侧显示规范化的颜色栏。我会编辑的更清晰。哦哇!!这是一个非常酷的答案,因为它解决了我遇到的另一个问题,即如何为直方图提供预先计算的箱子。我实际上是在spark上分别计算垃圾箱,可以用这些数字做一些有用的事情。非常感谢!!很高兴问题(奖金问题)解决了。