0

我想用 OpenTURNS 创建高斯样本的对数似然的等高线图。每个等高线映射到一个函数值,该函数值由绘图的图例指示。问题是图例在某种程度上隐藏了轮廓:如何设置绘图以使图例不隐藏内容?

这是一个例子。我创建了一个Normal与 20 至 79 岁之间的男性身高相对应的分布(参见“美国人口普查局的统计摘要。”表 209. 2012)。然后我从这个分布中生成一个样本。我定义了对数似然函数,它采用输入向量 (mu, sigma) 并返回一个包含对数似然输出的一维向量。我可以使用draw这个函数的方法来创建等高线图。

import openturns as ot
import openturns.viewer as otv

mu = 1.763
sigma = 0.0680
N = ot.Normal(mu, sigma)
sample_size = 100
sample = N.getSample(sample_size)

def loglikelihood_gauss(X):
    """Compute the log-likelihood of a Gaussian sample."""
    mu, sigma = X
    N = ot.Normal(mu, sigma)
    log_pdf = N.computeLogPDF(sample)
    sample_size = sample.getSize()
    log_likelihood = log_pdf.computeMean() * sample_size
    return log_likelihood

# Contour plot
logLikelihoodFunction = ot.PythonFunction(2, 1, loglikelihood_gauss)
ot.ResourceMap_SetAsUnsignedInteger("Contour-DefaultLevelsNumber", 5)
graph = logLikelihoodFunction.draw([1.65, 0.04], [1.85, 0.15], [50]*2)
graph.setXTitle(r"$\mu$")
graph.setYTitle(r"$\sigma$")
graph.setTitle("Log-Likelihood.")
view = otv.View(graph)

这会产生:

高斯样本的对数似然

如何设置绘图以使图例不隐藏轮廓?

4

3 回答 3

1

第一个技巧是使用matplotlib 函数的bbox_to_anchor选项。legend这是可能的,因为所有 OpenTURNS 图形都来自 Python 层的 Matplotlib。第二个技巧是View根据方法从对象中获取图形getFigure。没有进一步的代码,这会产生第二个图例,它位于正确的位置,但重复了图例。第三个技巧是通过将内容设置为空字符串来隐藏旧图例。

logLikelihoodFunction = ot.PythonFunction(2, 1, loglikelihood_gauss)
ot.ResourceMap_SetAsUnsignedInteger("Contour-DefaultLevelsNumber", 5)
graph = logLikelihoodFunction.draw([1.65, 0.04], [1.85, 0.15], [50]*2)
graph.setXTitle(r"$\mu$")
graph.setYTitle(r"$\sigma$")
graph.setTitle("Log-Likelihood.")
legends = graph.getLegends()
graph.setLegendPosition("")
view = otv.View(graph)
figure = view.getFigure()
figure.legend(legends, bbox_to_anchor=(1.1, 0.9))

带图例的对数似然等值线图

保存图形时,图例可能会被裁剪。可能需要使用以下bbox_inches选项:

figure.savefig("filename.png", bbox_inches="tight")
于 2020-12-06T11:58:14.597 回答
0

不幸的是,如果您混合不同类型的可绘制对象,则效果不佳:

import openturns as ot
import openturns.viewer as otv

f = ot.SymbolicFunction(["x", "y"], ["x^4+y^4-8*(x^2+y^2)"])
graph = f.draw([-4.0]*2, [4.0]*2)
graph.setLegendPosition("bottomleft")
graph.add(ot.Curve([[-4.0]*2, [4.0]*2], "red", "dashed", 1.0, "line"))
graph.add(ot.Cloud([[0.0]*2], "black", "fcircle", "point"))
legends = graph.getLegends()
view = otv.View(graph)
figure = view.getFigure()
figure.legend(legends, bbox_to_anchor=(1.0, 1.0))

在结果图中,您会看到新的图例已将点的标签和线的标签与前两个等值的标签颠倒了。获取图例标签的正确方法是:

_, legends = view._ax[0].get_legend_handles_labels()
于 2021-05-28T14:35:57.333 回答
0

非常不错的功能!我经常对图例太大的图表感到尴尬。您可以使用以下方法改进您的脚本:

graph.setLegendPosition('')

代替:

graph.setLegends([""] * 5)

它避免您计算图表中可绘制的数量。

于 2020-12-07T07:08:23.157 回答