与 seaborn 的 kdeplot 上的带宽混淆
Confusion with bandwidth on seaborn's kdeplot
下面的 lineslist 表示一组线(对于某些化学光谱,比方说),以 MHz 为单位。我知道用于探测这些线的激光线宽为 5 MHz。因此,天真地,这些带宽为 5 的线的核密度估计应该给我在使用上述激光的实验中产生的连续分布。
以下代码:
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
lineslist=np.array([-153.3048645 , -75.71982528, -12.1897835 , -73.94903264,
-178.14293936, -123.51339541, -118.11826988, -50.19812838,
-43.69282206, -34.21268228])
sns.kdeplot(lineslist, shade=True, color="r",bw=5)
plt.show()
产量
这看起来像带宽远大于 5 MHz 的高斯分布。
我猜出于某种原因,kdeplot 的带宽单位与绘图本身的单位不同。最高线和最低线之间的间隔约为 170.0 MHz。假设我需要通过这个因素重新调整带宽:
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
lineslist=np.array([-153.3048645 , -75.71982528, -12.1897835 , -73.94903264,
-178.14293936, -123.51339541, -118.11826988, -50.19812838,
-43.69282206, -34.21268228])
sns.kdeplot(lineslist, shade=True, color="r",bw=5/(np.max(lineslist)-np.min(lineslist)))
plt.show()
我得到:
线路似乎具有预期的 5 MHz 带宽。
虽然这个解决方案很花哨,但我已经把它从我的屁股里拿出来了,我很好奇是否有人更熟悉 seaborn 的 kdeplot 内部结构可以评论为什么会这样。
谢谢,
塞缪尔
需要注意的一件事是,Seaborn 实际上并不处理带宽本身 - 它或多或少按原样将设置传递给 SciPy 或 Statsmodels 包,具体取决于您使用的是什么已安装。 (它更喜欢 Statsmodels,但会退回到 SciPy。)
这个参数在各种子包中的文档有点混乱,但据我所知,这里的关键问题是 SciPy 的设置是带宽 factor,而不是带宽本身。也就是说,这个因素(有效地)乘以您正在绘制的数据的标准偏差,为您提供内核中使用的实际带宽。
所以对于 SciPy,如果你有一个固定的数字作为你的带宽,你需要除以你的数据标准偏差。如果您试图一致地绘制多个数据集,则需要针对每个数据集的标准偏差进行调整。此调整有效地执行了按范围缩放所做的操作——但同样,使用的数字不是数据的范围,而是数据的标准差。
为了让事情变得更加混乱,Statsmodels 期望在给定标量值时获得真实带宽,而不是乘以样本标准偏差的因子。因此,根据您使用的后端,Seaborn 的行为会有所不同。没有直接的方法告诉 Seaborn 使用哪个后端 - 最好的测试方法可能是尝试 import statsmodels
,然后看看是否成功(直接获取带宽)或失败(获取带宽 factor).
顺便说一句,这些结果是针对 Seaborn 版本 0.7.0 进行测试的——我预计(希望?)未来的版本可能会改变这种行为。
lineslist 表示一组线(对于某些化学光谱,比方说),以 MHz 为单位。我知道用于探测这些线的激光线宽为 5 MHz。因此,天真地,这些带宽为 5 的线的核密度估计应该给我在使用上述激光的实验中产生的连续分布。
以下代码:
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
lineslist=np.array([-153.3048645 , -75.71982528, -12.1897835 , -73.94903264,
-178.14293936, -123.51339541, -118.11826988, -50.19812838,
-43.69282206, -34.21268228])
sns.kdeplot(lineslist, shade=True, color="r",bw=5)
plt.show()
产量
这看起来像带宽远大于 5 MHz 的高斯分布。
我猜出于某种原因,kdeplot 的带宽单位与绘图本身的单位不同。最高线和最低线之间的间隔约为 170.0 MHz。假设我需要通过这个因素重新调整带宽:
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
lineslist=np.array([-153.3048645 , -75.71982528, -12.1897835 , -73.94903264,
-178.14293936, -123.51339541, -118.11826988, -50.19812838,
-43.69282206, -34.21268228])
sns.kdeplot(lineslist, shade=True, color="r",bw=5/(np.max(lineslist)-np.min(lineslist)))
plt.show()
我得到:
线路似乎具有预期的 5 MHz 带宽。
虽然这个解决方案很花哨,但我已经把它从我的屁股里拿出来了,我很好奇是否有人更熟悉 seaborn 的 kdeplot 内部结构可以评论为什么会这样。
谢谢,
塞缪尔
需要注意的一件事是,Seaborn 实际上并不处理带宽本身 - 它或多或少按原样将设置传递给 SciPy 或 Statsmodels 包,具体取决于您使用的是什么已安装。 (它更喜欢 Statsmodels,但会退回到 SciPy。)
这个参数在各种子包中的文档有点混乱,但据我所知,这里的关键问题是 SciPy 的设置是带宽 factor,而不是带宽本身。也就是说,这个因素(有效地)乘以您正在绘制的数据的标准偏差,为您提供内核中使用的实际带宽。
所以对于 SciPy,如果你有一个固定的数字作为你的带宽,你需要除以你的数据标准偏差。如果您试图一致地绘制多个数据集,则需要针对每个数据集的标准偏差进行调整。此调整有效地执行了按范围缩放所做的操作——但同样,使用的数字不是数据的范围,而是数据的标准差。
为了让事情变得更加混乱,Statsmodels 期望在给定标量值时获得真实带宽,而不是乘以样本标准偏差的因子。因此,根据您使用的后端,Seaborn 的行为会有所不同。没有直接的方法告诉 Seaborn 使用哪个后端 - 最好的测试方法可能是尝试 import statsmodels
,然后看看是否成功(直接获取带宽)或失败(获取带宽 factor).
顺便说一句,这些结果是针对 Seaborn 版本 0.7.0 进行测试的——我预计(希望?)未来的版本可能会改变这种行为。