【问题标题】:Matplotlib - Boxplot calculated on log10 values but shown in logarithmic scaleMatplotlib - 根据 log10 值计算的箱线图,但以对数刻度显示
【发布时间】:2016-01-05 09:51:03
【问题描述】:

我认为这是一个简单的问题,但我似乎仍然想不出一个简单的解决方案。我有一组分子丰度数据,其值范围为多个数量级。我想用boxplots (box-and-whiskers plots) 来表示这些丰度,并且由于值的范围很广,我希望在对数刻度上计算这些框。 我知道我可以只计算数据的 log10 并将其发送到 matplotlib 的boxplot,但这不会在以后的图中保留对数刻度。

所以我的问题基本上是这样的: 当我根据我的值的 log10 计算出箱线图时,我如何转换之后的绘图以对数刻度显示,而不是与 log10 值呈线性关系? 我可以更改刻度标签以部分解决此问题,但我不知道如何将对数刻度带回绘图。

或者有另一种更直接的方法来绘制这个。可能已经包含此选项的其他软件包?

非常感谢您的帮助。

【问题讨论】:

  • 为什么不将您的 log10 计算值转换回正常值 (10**y) 并将 y 比例设置为对数?
  • 也许我应该澄清一下,我创建了这样的情节:bp = ax.boxplot(np.log10(abunds))。此命令计算框值并创建绘图。我需要改变情节中的东西,而不是价值观,对吧?
  • 按照你的做法,你正在策划不同的事情。我还是不明白为什么你不能做bp = ax.boxplot(abunds); ax.set_yscale('log')。这将为您提供对数刻度,因此 y 刻度与您的值正确对应。
  • 因为日志值为负数(值为 10^(-4) 或更低),所以我收到ax.set_yscale('log') 的错误
  • Tobias 你的 log 值是负数,但你原来的 abunds 值不应该是负数。你确定你完全按照@Evert 的建议去做了吗?

标签: python matplotlib plot boxplot logarithm


【解决方案1】:

我建议不要在原始值上绘制箱线图并将 y 轴设置为对数,因为箱线图函数并非设计为跨数量级工作,并且您可能会得到太多异常值(取决于您的数据,当然)。

相反,您可以绘制数据的对数并手动调整 y 标签。

这是一个非常粗略的例子:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator, FormatStrFormatter

np.random.seed(42)

values = 10 ** np.random.uniform(-3, 3, size=100)

fig = plt.figure(figsize=(9, 3))


ax = plt.subplot(1, 3, 1)

ax.boxplot(np.log10(values))
ax.set_yticks(np.arange(-3, 4))
ax.set_yticklabels(10.0**np.arange(-3, 4))
ax.set_title('log')

ax = plt.subplot(1, 3, 2)

ax.boxplot(values)
ax.set_yscale('log')
ax.set_title('raw')

ax = plt.subplot(1, 3, 3)

ax.boxplot(values, whis=[5, 95])
ax.set_yscale('log')
ax.set_title('5%')

plt.show()

右图显示了原始值的箱线图。这会导致许多异常值,因为最大晶须长度计算为四分位间距(盒子高度)的倍数(默认值:1.5),不会跨越数量级。

或者,您可以指定在给定的百分位范围内绘制胡须: ax.boxplot(values, whis=[5, 95]) 在这种情况下,您会得到固定数量的异常值 (5%) 高于和低于。

【讨论】:

  • 谢谢你的好例子。有没有办法像在原始图中一样为日志图添加次要刻度?
  • 我不知道,抱歉。 matplotlib.ticker 可能有可能:matplotlib.org/examples/pylab_examples/major_minor_demo1.html
  • 我可以按照与主要刻度类似的逻辑设置次要刻度。例如,要在位置1, 2, ..., 9, 20, 30, ..., 90 设置次要刻度,计算它们的 log10 并设置为次要刻度:minor_xticks = np.log10(np.concatenate((np.arange(1, 10), np.arange(1, 10) * 10)).astype(np.float)) ax.set_xticks(minor_xticks, minor=True)
【解决方案2】:

你可以使用 plt.yscale:

plt.boxplot(data); plt.yscale('log')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-08
    • 1970-01-01
    • 1970-01-01
    • 2019-03-03
    • 2020-03-19
    • 2018-04-21
    • 1970-01-01
    相关资源
    最近更新 更多