python 使用kdeplut的对数刻度

owfi6suc  于 2023-04-04  发布在  Python
关注(0)|答案(3)|浏览(135)

我想做一个很好的自由能曲面(热图)使用Seaborn的kdeplut。我非常接近,但无法找到改变颜色条比例的方法。颜色条比例很重要,因为它应该表示Map上不同坐标处的能量差异。我需要知道如何按-(0.5961573)*log(x)缩放颜色条的值,其中x是颜色条的值。我可能还需要从那里对颜色条进行归一化,以便最大值为0。
以下是我目前拥有的:

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.pyplot as plt
import seaborn as sns

rs=[]
dihes=[]
with open(sys.argv[1], 'r') as f:
    for line in f:
        time,r,dihe = line.split()
        rs.append(float(r))
        dihes.append(float(dihe))
    sns.set_style("white")
    sns.kdeplot(rs, dihes, n_levels=25, cbar=True, cmap="Purples_d")
    plt.show()

这让我:

数组rs和dihes是简单的一维数组。
任何关于如何缩放颜色条(z轴)的建议都将非常有帮助!

disho6za

disho6za1#

一种方法是手动创建图表,然后直接修改标签。这涉及到几行代码。您可能需要稍微调整格式,但这样应该可以让您走上正确的道路。
以下内容改编自this answerthis answer

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats

rs=[]
dihes=[]
with open(sys.argv[1], 'r') as f:
    for line in f:
        time,r,dihe = line.split()
        rs.append(float(r))
        dihes.append(float(dihe))

    x = rs
    y = dihes
    kde = stats.gaussian_kde([x, y])

    xx, yy = np.mgrid[min(x):max(x):(max(x)-min(x))/100, min(y):max(y):(max(y)-min(y))/100]
    density = kde(np.c_[xx.flat, yy.flat].T).reshape(xx.shape)

    sns.set_style("white")
    fig, ax = plt.subplots()
    cset = ax.contour(xx, yy, density, 25, cmap="Purples_r")
    cb = fig.colorbar(cset)
    cb.ax.set_yticklabels(map(lambda x: -0.5961573*np.log(float(x.get_text())), 
                              cb.ax.get_yticklabels()))
vpfxa7rd

vpfxa7rd2#

有点晚了,但我最终把这个上下文管理器放在一起,它把绘制的密度值切换到对数尺度:

import contextlib
import seaborn as sns

@contextlib.contextmanager
def plot_kde_as_log(base=np.exp(1), support_threshold=1e-4):
    """Context manager to render density estimates on a logarithmic scale.

    Usage:

        with plot_kde_as_log():
            sns.jointplot(x='x', y='y', data=df, kind='kde')
    """
    old_stats = sns.distributions._has_statsmodels
    old_univar = sns.distributions._scipy_univariate_kde
    old_bivar = sns.distributions._scipy_bivariate_kde

    sns.distributions._has_statsmodels = False
    def log_clip_fn(v):
        v = np.log(np.clip(v, support_threshold, np.inf))
        v -= np.log(support_threshold)
        v /= np.log(base)
        return v
    def new_univar(*args, **kwargs):
        x, y = old_univar(*args, **kwargs)
        y = log_clip_fn(y)
        return x, y
    def new_bivar(*args, **kwargs):
        x, y, z = old_bivar(*args, **kwargs)
        z = log_clip_fn(z)
        return x, y, z

    sns.distributions._scipy_univariate_kde = new_univar
    sns.distributions._scipy_bivariate_kde = new_bivar
    try:
        yield
    finally:
        sns.distributions._has_statsmodels = old_stats
        sns.distributions._scipy_univariate_kde = old_univar
        sns.distributions._scipy_bivariate_kde = old_bivar

这种方法的好处是,它保留了sns.jointplot()的所有样式和其他选项,而无需任何额外的工作。

fgw7neuy

fgw7neuy3#

我更新了Walt W's上下文管理器,使其可以与较新版本的seaborn一起使用

@contextlib.contextmanager
def plot_kde_as_log(base=np.exp(1), support_threshold=1e-4):
    """Context manager to render density estimates on a logarithmic scale.

    Usage:

        with plot_kde_as_log():
            sns.jointplot(x='x', y='y', data=df, kind='kde')
    """
    old_call = sns._statistics.KDE.__call__

    def log_clip_fn(v):
        v = np.log(np.clip(v, support_threshold, np.inf))
        v -= np.log(support_threshold)
        v /= np.log(base)
        return v
    def new_call(*args, **kwargs):
        density, support = old_call(*args, **kwargs)
        density = log_clip_fn(density)
        return density, support

    sns._statistics.KDE.__call__ = new_call
    try:
        yield
    finally:
        sns._statistics.KDE.__call__ = old_call

相关问题