小能豆

seaborn jointplot 边距不适用于对数轴

py

我正在尝试通过以下方式进行绘图:

g = sns.jointplot(x = etas, y = vs, marginal_kws=dict(bins=100), space = 0)
g.ax_joint.set_xscale('log')
g.ax_joint.set_yscale('log')
g.ax_joint.set_xlim(0.01)
g.ax_joint.set_ylim(0.01)
g.ax_joint.set_xlabel(r'$\eta$')
g.ax_joint.set_ylabel("V")

plt.savefig("simple_scatter_plot_Seanborn.png",figsize=(8,8), dpi=150)

由此我得到了以下图像:

1.jpg

这不是我想要的。为什么直方图最后被填满了?那里没有数据点,所以我不明白……


阅读 18

收藏
2024-12-09

共1个答案

小能豆

你遇到的问题是由于 sns.jointplot 默认绘制了两个边际直方图,它们分别是 xy 数据的分布。由于在你的代码中你将 x 和 y 的坐标轴设置为了对数坐标,这可能导致了一些意料之外的结果,尤其是当数据中存在零或负值时,这些值在对数坐标下无法正确显示,可能填满了边际直方图的区域。

问题分析:

  1. 对数坐标系:你使用 ax_joint.set_xscale('log')ax_joint.set_yscale('log') 将坐标轴设置为对数坐标系。对数坐标系不能处理零值和负值,如果数据中有零或负值,matplotlib 会抛出错误,或者更常见的,显示不正常。
  2. 边际直方图填充:你提到直方图被填满了。对于对数坐标,如果数据中有零或负值,这些值会导致对数转换失败,导致图形填充无数据的区域。
  3. 边际数据没有正确处理sns.jointplot 会计算并绘制 x 和 y 的边际分布(直方图),如果对数变换后有无效的数据(如零或负数),可能会导致直方图的计算出现问题,甚至填充整个区域。

解决方案:

  1. 检查数据:首先,你需要确保你的 etasvs 数据中没有零或负数。如果数据中有零或负数,使用对数坐标系将无法正确显示。

    你可以通过简单的代码检查数据是否包含零或负数:
    python import numpy as np print(np.any(etas <= 0)) # 检查 etas 是否有小于或等于 0 的值 print(np.any(vs <= 0)) # 检查 vs 是否有小于或等于 0 的值

    如果有负数或零,你可能需要对这些数据进行过滤或调整(例如,可以用一个非常小的正数替代零值)。

  2. 使用 log1p 转换:如果你的数据包含零,你可以使用 np.log1p(x)(即 log(1 + x)),这将避免零值导致的问题。log1p 函数会对零值进行有效处理。

    python etas = np.log1p(etas) # 对 etas 进行 log1p 转换 vs = np.log1p(vs) # 对 vs 进行 log1p 转换

  3. 调整直方图的 bin 数:你在 marginal_kws 中使用了 bins=100。根据数据的范围,直方图可能会绘制得过于密集,特别是当数据量较小时。你可以调整 bins 的数量,使得直方图更合适。

    python g = sns.jointplot(x=etas, y=vs, marginal_kws=dict(bins=50), space=0)

  4. 确保坐标轴的范围:在设置对数坐标时,你可以确保坐标轴的最小值大于零。例如,可以通过设置 set_xlimset_ylim 来控制最小值。

    python g.ax_joint.set_xlim(0.01, 1000) # 设置 x 轴范围 g.ax_joint.set_ylim(0.01, 1000) # 设置 y 轴范围

最终代码示例:

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

# 假设 etas 和 vs 是你的数据
etas = np.random.lognormal(size=1000)
vs = np.random.lognormal(size=1000)

# 对数据进行 log1p 转换,避免零值
etas = np.log1p(etas)
vs = np.log1p(vs)

# 创建 jointplot
g = sns.jointplot(x=etas, y=vs, marginal_kws=dict(bins=50), space=0)

# 设置对数坐标
g.ax_joint.set_xscale('log')
g.ax_joint.set_yscale('log')

# 设置坐标轴范围
g.ax_joint.set_xlim(0.01, 1000)
g.ax_joint.set_ylim(0.01, 1000)

# 设置坐标轴标签
g.ax_joint.set_xlabel(r'$\eta$')
g.ax_joint.set_ylabel("V")

# 保存图像
plt.savefig("simple_scatter_plot_Seanborn.png", figsize=(8,8), dpi=150)
plt.show()

这样,应该能够解决你遇到的问题,确保坐标轴和直方图正确显示并避免填满图像的情况。

2024-12-09