【问题标题】:Seaborn: Violinplot experiences difficulty with too many variables?Seaborn:Violinplot 遇到太多变量的困难?
【发布时间】:2019-10-14 11:21:56
【问题描述】:

我想使用 seaborn 用 violinplots 可视化我的整个 Pandas 数据框,并且我认为我已经进行了必要的更正,以便为我的数据框拥有的大量 270 个变量生成一个大图。

但是,无论我做什么,小提琴图只显示每个变量的内部迷你箱线图(作为另一个问题 here 描述),而不是它们的 kde:

fig, ax = plt.subplots(figsize=(50,5))
ax.set_ylim(-6, 6)

a = sns.violinplot(x='variable', y='value', data=pd.melt(train_norm), ax=ax)
a.set_xticklabels(a.get_xticklabels(), rotation=90);

plt.savefig('massive_violinplot.png', figsize=(50,5), dpi=220)

(为裁剪图道歉,整个事情太大了,无法发布)

而以下代码,使用相同的pd.Dataframe,但只显示前六个变量,正确显示:

fig, ax = plt.subplots(figsize=(10,5))
ax.set_ylim(-6, 6)

a = sns.violinplot(x='variable', y='value', data=pd.melt(train_norm.iloc[:,:6]), ax=ax)
a.set_xticklabels(a.get_xticklabels(), rotation=90);

plt.savefig('massive_violinplot.png', figsize=(10,5), dpi=220)

我怎样才能得到一个像上面那样的所有变量的图表,填充适当的小提琴图来显示他们的 kde 的?

【问题讨论】:

  • 如果您尝试在一个图形上放置太多图,a) 您会遇到您所描述的问题,并且 b) 它不再用作数据的可视化。一种选择是将要直接比较的特征分组,并将每个组呈现在不同的子图上。另一种方法是只显示一些能够说明数据有用信息的特征,而丢弃其余的。除此之外,唯一的其他选择是拥有一个非常大的地块,但这并不是一个好主意,原因有很多。
  • 我了解将任务分成单独的块的价值,但是在我拥有的小众数据处理上下文中,最好一次查看所有变量,并且必须有办法做到这一点.例如,正如在我的浏览器中看到的,imgur.com/71VD65x 处理如此大的图是完全可行的,而且 seaborn 似乎有足够的空间来生成真正的小提琴图。但是,当我继续扩展图表的 figsize 时,最终它开始崩溃,如此处所示,imgur.com/hQWOjKn
  • 您可以随时将其分解为图像看起来不错的块,然后使用成像工具手动将图像组合在一起。只要保持 y 轴相同的值,你应该可以很容易地做到这一点,而且不会超过 5 分钟。
  • 如您所见,(3000, 5) 图在正常的 seaborn 用例中并不可行。底线是 270 个图并不能很好地并排显示。您可以垂直堆叠多个子图(每个子图 6 个,45 个应该足够了)并在每个子图上显示一个子集,但实际上最好的选择可能是查看其他可视化库。散景,也许是为了互动?
  • 始终在 Stack Overflow 中分享您的 CSV 文件。提供的链接现在是指向垃圾邮件站点的重定向,因此对于想要从问题中学习的读者来说毫无用处。通常,如果所需文件太大而无法在问题中发布,则该问题是题外话。不过通常所有的例子都可以删减。

标签: python pandas matplotlib data-visualization seaborn


【解决方案1】:

这与变量的数量或绘图大小无关,而是与变量分布的巨大差异有关。我现在无法访问你的数据,所以我将用一个组成的数据集来说明它。您可以跟随您的数据集,选择离散度较大的三个变量和离散度较小的三个变量。作为分散测量,您可以使用方差甚至数据范围(如果您没有疯狂的长尾)或其他不同的东西,我不确定哪种方法会更好。

rs = np.random.RandomState(42)
data = rs.randn(100, 6)
data[:, :3] *= 20
df = pd.DataFrame(data)

看看如果我们用公共轴绘制密度以使它们可以直接比较会发生什么。

df.plot(kind='kde', subplots=True, layout=(3, 2), sharex=True, sharey=True)
plt.tight_layout()

这或多或少与您在 seaborn 小提琴情节中看到的相同,但当然是换位了。

sns.violinplot(x='variable', y='value', data=pd.melt(df))

这通常非常适合比较变量,因为您可以将宽度差异视为密度差异。不幸的是,用于分散更多变量的小提琴太窄了,你根本看不到宽度,你失去了任何形状的感觉。另一方面,离散度较小的变量显得太短(实际上在您的数据集中,其中一些只是水平线)。

对于第一个问题,您可以使用scale='width' 使小提琴使用所有可用的水平空间,但是您不再可以比较变量之间的密度。峰的宽度相同,但密度不同。

sns.violinplot(x='variable', y='value', data=pd.melt(df), scale='width')

顺便说一下,这是matplotlib的小提琴图默认做的。

plt.violinplot(df.T)

对于第二个问题,我认为您唯一的选择是以某种方式规范化或标准化变量。

sns.violinplot(x='variable', y='value', data=pd.melt((df - df.mean()) / df.std()))

现在您可以更清楚地分别了解每个变量(它们有多少模式、它们的偏斜程度、尾部有多长……),但您既无法比较变量的尺度也无法比较变量的离散度。

这个故事的寓意是你不能一次看到所有东西,你必须根据你在数据中寻找的内容进行选择。

【讨论】:

  • 有见地的帮助,非常感谢,Goyo。在这种情况下,我开始尝试使用width 参数,将其设置得非常高,如下面的代码sns.violinplot(x='variable', y='value', data=pd.melt(train_norm), linewidth=0.8, width=40, ax=ax),我得到了以下结果,似乎与我正在寻找的一样:imgur.com/WiRtxyv。通过将width 设置得如此之高,我是否会以某种方式扰乱kde 的真实尺寸,就像您对上面的scale='width' 所做的那样?
  • 这是一个奇怪的问题。没有“真实尺寸”,因为您在 X 轴上没有真实的比例。所有的小提琴都有相同的面积,因此可以进行比较。我会争辩说,所有变量的情节对于所有那些重叠的小提琴来说都是一个丑陋的混乱(你在链接中只展示了好的部分),但如果你发现它有用,就使用它。
  • 这是真的,我只使用它的漂亮部分作为示例图像^^。我想知道它们是否都具有相同的区域,如果它们具有可比性,那么感谢您的回答。我会牢记您的建议,并尝试找到一种方法来比现有的变量更标准化(数据用于 kaggle Housing 竞赛),并对其他可能性保持开放的态度。
猜你喜欢
  • 2011-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-25
  • 2013-10-18
  • 1970-01-01
  • 2013-07-30
  • 1970-01-01
相关资源
最近更新 更多