避免"散点/点/蜜蜂群"图中数据点重叠
在使用 matplotlib
绘制点图时,我想把重叠的数据点稍微偏移一下,这样它们就都能看得见了。比如说,如果我有:
CategoryA: 0,0,3,0,5
CategoryB: 5,10,5,5,10
我希望每个 CategoryA
的 "0" 数据点能够并排显示,而不是重叠在一起,同时还要和 CategoryB
区分开来。
在 R 语言的 ggplot2
中,有一个叫 "jitter"
的选项可以做到这一点。请问在 matplotlib 中有没有类似的选项,或者有没有其他方法可以达到类似的效果呢?
编辑:为了更清楚,我想说的是,R 语言中的 "beeswarm"
图 正是我想要的效果,而 pybeeswarm
是一个早期但很有用的 matplotlib/Python 版本。
编辑:补充一下,Seaborn 的 Swarmplot,在 0.7 版本中引入,是我想要的效果的一个很好的实现。
7 个回答
15
我使用了numpy.random这个库来把数据在X轴上“散开”或者说“像蜜蜂一样聚集”,但是每个类别的数据都是围绕一个固定的点分布的。然后,我对每个类别的数据基本上都用pyplot.scatter()这个函数来绘制散点图:
import matplotlib.pyplot as plt
import numpy as np
#random data for category A, B, with B "taller"
yA, yB = np.random.randn(100), 5.0+np.random.randn(1000)
xA, xB = np.random.normal(1, 0.1, len(yA)),
np.random.normal(3, 0.1, len(yB))
plt.scatter(xA, yA)
plt.scatter(xB, yB)
plt.show()
22
Seaborn这个库可以通过 sns.swarmplot()
来制作类似直方图的分类点图,同时也可以用 sns.stripplot()
来制作带有抖动效果的分类点图:
import seaborn as sns
sns.set(style='ticks', context='talk')
iris = sns.load_dataset('iris')
sns.swarmplot('species', 'sepal_length', data=iris)
sns.despine()
sns.stripplot('species', 'sepal_length', data=iris, jitter=0.2)
sns.despine()
63
在@user2467675的回答基础上,我来分享一下我是怎么做的:
def rand_jitter(arr):
stdev = .01 * (max(arr) - min(arr))
return arr + np.random.randn(len(arr)) * stdev
def jitter(x, y, s=20, c='b', marker='o', cmap=None, norm=None, vmin=None, vmax=None, alpha=None, linewidths=None, verts=None, hold=None, **kwargs):
return scatter(rand_jitter(x), rand_jitter(y), s=s, c=c, marker=marker, cmap=cmap, norm=norm, vmin=vmin, vmax=vmax, alpha=alpha, linewidths=linewidths, **kwargs)
stdev
这个变量是用来确保抖动效果足够明显,可以在不同的比例下看到,但它假设坐标轴的范围是从零到最大值。
接着,你可以用jitter
来代替scatter
。