【问题标题】:How to debug a scatter plot in Matplotlib?如何在 Matplotlib 中调试散点图?
【发布时间】:2020-02-10 16:24:46
【问题描述】:

我有以下df:

df = pd.DataFrame([
    ['A', 'X', '2020-10-01', 1],
    ['A', 'X', '2020-10-02', 2], 
    ['A', 'X', '2020-10-03', 3], 
    ['A', 'Y', '2020-10-01', 4],
    ['A', 'Y', '2020-10-02', 5], 
    ['A', 'Y', '2020-10-03', 6],
    ['B', 'Z', '2020-10-01', 7],
    ['B', 'Z', '2020-10-02', 8], 
    ['B', 'Z', '2020-10-03', 9], 
    ['B', 'Z', '2020-10-01', 10],
    ['B', 'Z', '2020-10-02', 11], 
    ['B', 'Z', '2020-10-03', 12],    
],
    columns=['Q', 'W', 'DT', 'V']
)

我想创建一个散点图:

fig, ax = plt.subplots(figsize=(12, 8), frameon=False)
fig.suptitle('Plotz', fontsize=16)
ax.set_title('DF Plot')
ax.scatter(x=df.DT, y=df.W, s=df.V)

这创建了以下图表:

我想弄清楚实际发生了什么,因为图表上有 9 个数据点,而数据中有 12 个数据点。注释图表不起作用,它将为顶行注释 2 个值。

for i, txt in enumerate(df.V):
    ax.annotate(txt, (df.DT[i], df.W[i]), fontsize=14)

当 x,y 对有多个值时(如本例中),有没有办法弄清楚引擎盖下到底发生了什么?

更新:也许我不清楚。在这种情况下 Matplotlib 的默认行为是什么?是最后的价值获胜吗?我怎样才能在图上显示实际值? (与显示两个值的注释代码不同,这显示了绘图上的实际值)。

在谷歌搜索后,我认为答案是:

Visualization of scatter plots with overlapping points in matplotlib

【问题讨论】:

  • Z 点重叠。
  • 那是因为你的 Z 值是重复的。所以在 6 个 Z 值中,你只能得到 3 个
  • 是的,会发生什么?更大的价值获胜,最后的价值获胜?均值是计算出来的?存在重叠值时的默认行为是什么?我可以控制行为吗?

标签: python matplotlib


【解决方案1】:

通常情况下,点是按照它们遇到的顺序绘制的,一个接一个。如果没有透明度,最后绘制的将可见,而较早的将仅显示一些边框以防它们更大。

因此,调试这种情况的一种方法是设置一个使点透明的 alpha 值。多个点相互重叠会显示更暗并有一些边框。

使用给定的测试数据,下面的代码会放大大小并设置 alpha。随着点大小变得非常大,需要调整轴限制。使用多种颜色会更加强调重叠。

ax.scatter(x=df.DT, y=df.W, s=df.V*150, alpha=0.4)
plt.xlim(-1,3)
plt.ylim(-1,3)

另一种方法是添加抖动:在每个点位置添加一些小的随机噪声。在数值数据的情况下,可以直接将抖动添加到数据中。如果是分类数据,可以调用scatter后修改位置:

import numpy as np
dots = ax.scatter(x=df.DT, y=df.W, s=df.V)
offsets =  dots.get_offsets()
jittered_offsets = offsets + np.random.uniform(-0.1, 0.1, offsets.shape)
dots.set_offsets(jittered_offsets)

使用原始颜色和大小,并且没有 alpha,这会清楚地将注意力吸引到重叠的点上:

如果两个轴都是分类的,另一种方法是仅根据位置进行计数并包围多次出现的位置:

import collections
dots = ax.scatter(x=df.DT, y=df.W, s=df.V)
offsets =  dots.get_offsets()
counts = collections.Counter([(x,y)  for x, y in offsets])
suspects = [p for p in counts if counts[p] >= 2]
ax.scatter([x for x, _ in suspects], [y for _, y in suspects], ec='crimson', lw=1, fc='none', s=50)

当然,不同的方法(alpha、颜色、抖动、环绕)可以根据实际数据的具体情况进行组合。

【讨论】:

  • 感谢您的精彩回答!我刚刚实现了jitter方式,效果很好。
猜你喜欢
  • 1970-01-01
  • 2017-10-14
  • 2020-07-22
  • 1970-01-01
  • 2010-12-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多