【问题标题】:Boxplots with overlapping distribution/histogram具有重叠分布/直方图的箱线图
【发布时间】:2019-10-08 10:35:12
【问题描述】:

简而言之:我基本上是在尝试基于连续变量绘制箱线图,其中每个框代表该变量特定范围内的条目。最重要的是,我想叠加一个直方图来显示分布(每个区间有多少计数)。

再解释一下:我有一个包含各种列的数据框。我有兴趣按某个连续列 X 上的间隔对它们进行分组,并绘制 Y 列如何查找 X 列的每个间隔的箱线图。此外,我想叠加一个分布或 historgam 以显示每个上有多少元素箱线图,或多或少。

我已经尝试(但失败了)用适当的 bin 绘制直方图。然后根据每个 bin 的中间值对数据进行分类,以便我可以在相同的轴上绘制(直方图和箱线图)或使用相同的 x 轴(axes.twinx()),但直方图会变形。就像它没有将 x 轴的值识别为相同。

原始直方图:https://imgur.com/8iNnR2u

尝试添加箱线图后:https://imgur.com/0LRGTTp

这是我一直在尝试做的一个说明性示例:

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


# Generate random data
prices = np.random.uniform(low=-85.0,high=85.0, size=(50,))
value_x = np.random.uniform(low=0,high=3000.0, size=(50,))
df = pd.DataFrame({'price':prices,'value_x':value_x })
# Classify each entry according to the bin they belong to
df['interval_index'] = np.digitize(df['price'], np.arange(-85,85,5))
# Get middle value for each bin, for example, if bin is (40-45), middle value would be 42.5
df['interval_middle_value'] = df['interval_index']*5-87.5

# Failed attempt to generate the desired plot
fig, ax = plt.subplots()
sns.distplot(df['price'],bins=np.arange(-85,85,5), ax=ax, kde=False, norm_hist=False)
ax2=ax.twinx()
sns.boxplot(x='interval_middle_value',y='value_x',data=df, ax=ax2)

我希望得到如下图所示的结果:https://imgur.com/svEOlNQ

【问题讨论】:

  • 您的代码和图表不匹配 - 代码说您使用的是均匀分布,但图表对我来说看起来很正常?
  • 那是因为我在这里发布的代码只是一个使用随机数据生成的示例,所以它不是我使用的真实数据。这就是它们看起来不同的原因,但除了数据生成(基本上,在第二条评论之后)之外,我所做的事情与我发布的代码中显示的完全相同。
  • 您确实应该确保您的示例是一致的,这样我们才能确切地知道您的期望(特别是,如果您可以随机播种)。无论如何,您的问题是箱线图是一个分类图,因此您认为与直方图一致的 x 值不是。在不同的轴组和print(ax.get_xlim()) 上分别执行这两个操作,以了解我的意思
  • 好的,很抱歉,下次发问题时我会记住的。那么,考虑到这个分类与连续情节问题,有没有办法将两者一起绘制,以使它们看起来类似于我在帖子中提到的预期结果?

标签: python pandas matplotlib seaborn


【解决方案1】:

由于箱线图是分类的,您需要将箱的位置设置为箱间隔的中间。 因此,您可能正在寻找这样的东西:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# Generate random data
prices = np.random.uniform(low=-85.0,high=85.0, size=(500,))
value_x = np.random.uniform(low=0,high=3000.0, size=(500,))
df = pd.DataFrame({'price':prices,'value_x':value_x })
# Classify each entry according to the bin they belong to
bins = np.arange(-85,90,5)

width = np.diff(bins)[0]
df['interval_index'] = np.digitize(df['price'], bins)
# Get middle value for each bin, for example, if bin is (40-45), middle value would be 42.5
middle_value = bins[:-1] + width/2

# Failed attempt to generate the desired plot
fig, ax = plt.subplots()
ax.hist(df['price'].values, bins=bins)
ax2=ax.twinx()

stats = [df['value_x'][df['interval_index'] == i].values for i in range(1, len(bins))]
ax2.boxplot(stats, positions=middle_value, widths=width*0.6, manage_ticks=False)


plt.show()

【讨论】:

  • 谢谢!这确实解决了箱线图中分类x轴的问题。
  • 我很欣赏 boxplpts 在某些领域是贬义词,但我认为这会更好地表示为一系列线而不是 x 在每个置信区间,也许随着线粗细的变化以显示不同的区间。
猜你喜欢
  • 2018-10-24
  • 2021-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-21
  • 2016-02-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多