我正在使用Matplotlib制作一些散点图(python 3.4.0,matplotlib 1.4.3,在Linux Mint 17上运行)。很容易为每个点单独设置alpha透明度;有没有办法将它们设置为一个组,以便同一组中的两个重叠点不会改变颜色?
示例代码:
import matplotlib.pyplot as plt
import numpy as np
def points(n=100):
x = np.random.uniform(size=n)
y = np.random.uniform(size=n)
return x, y
x1, y1 = points()
x2, y2 = points()
fig = plt.figure(figsize=(4,4))
ax = fig.add_subplot(111, title="Test scatter")
ax.scatter(x1, y1, s=100, color="blue", alpha=0.5)
ax.scatter(x2, y2, s=100, color="red", alpha=0.5)
fig.savefig("test_scatter.png")
此输出结果:
但我想要更像这样的东西:
我可以通过保存为SVG并在Inkscape中手动分组,然后设置透明度来解决,但我真的更喜欢我可以编码的东西。有什么建议吗?
答案 0 :(得分:8)
有趣的问题,我认为任何透明度的使用都会导致你想要避免的堆叠效应。您可以手动设置透明度类型颜色以更接近您想要的结果,
import matplotlib.pyplot as plt
import numpy as np
def points(n=100):
x = np.random.uniform(size=n)
y = np.random.uniform(size=n)
return x, y
x1, y1 = points()
x2, y2 = points()
fig = plt.figure(figsize=(4,4))
ax = fig.add_subplot(111, title="Test scatter")
alpha = 0.5
ax.scatter(x1, y1, s=100, lw = 0, color=[1., alpha, alpha])
ax.scatter(x2, y2, s=100, lw = 0, color=[alpha, alpha, 1.])
plt.show()
不同颜色之间的重叠不是以这种方式包含的,但是你得到了,
答案 1 :(得分:8)
是的,有趣的问题。您可以使用Shapely获取此散点图。这是代码:
import matplotlib.pyplot as plt
import matplotlib.patches as ptc
import numpy as np
from shapely.geometry import Point
from shapely.ops import cascaded_union
n = 100
size = 0.02
alpha = 0.5
def points():
x = np.random.uniform(size=n)
y = np.random.uniform(size=n)
return x, y
x1, y1 = points()
x2, y2 = points()
polygons1 = [Point(x1[i], y1[i]).buffer(size) for i in range(n)]
polygons2 = [Point(x2[i], y2[i]).buffer(size) for i in range(n)]
polygons1 = cascaded_union(polygons1)
polygons2 = cascaded_union(polygons2)
fig = plt.figure(figsize=(4,4))
ax = fig.add_subplot(111, title="Test scatter")
for polygon1 in polygons1:
polygon1 = ptc.Polygon(np.array(polygon1.exterior), facecolor="red", lw=0, alpha=alpha)
ax.add_patch(polygon1)
for polygon2 in polygons2:
polygon2 = ptc.Polygon(np.array(polygon2.exterior), facecolor="blue", lw=0, alpha=alpha)
ax.add_patch(polygon2)
ax.axis([-0.2, 1.2, -0.2, 1.2])
fig.savefig("test_scatter.png")
结果是:
答案 2 :(得分:2)
这是一个可怕的,可怕的黑客,但它确实有效。
您可以看到,当Matplotlib将数据点绘制为可以重叠的单独对象时,它会将它们之间的线条绘制为单个对象 - 即使该行在数据中被NaN分成几个部分。
考虑到这一点,你可以这样做:
import numpy as np
from matplotlib import pyplot as plt
plt.rcParams['lines.solid_capstyle'] = 'round'
def expand(x, y, gap=1e-4):
add = np.tile([0, gap, np.nan], len(x))
x1 = np.repeat(x, 3) + add
y1 = np.repeat(y, 3) + add
return x1, y1
x1, y1 = points()
x2, y2 = points()
fig = plt.figure(figsize=(4,4))
ax = fig.add_subplot(111, title="Test scatter")
ax.plot(*expand(x1, y1), lw=20, color="blue", alpha=0.5)
ax.plot(*expand(x2, y2), lw=20, color="red", alpha=0.5)
fig.savefig("test_scatter.png")
plt.show()
每种颜色都会与其他颜色重叠,但不会与其自身重叠。
需要注意的是,您必须小心用于制作每个圆圈的两个点之间的间距。如果它们相隔很远,那么分离将在你的情节中可见,但如果它们太靠近,matplotlib根本不绘制线条。这意味着需要根据数据范围选择分离,如果您打算制作交互式绘图,那么如果缩小太多则所有数据点都会突然消失,如果放大则会拉伸。太多了。
正如你所看到的,我发现1e-5对于范围为[0,1]的数据来说是一个很好的分离。
答案 3 :(得分:0)
只需将一个edgecolors='none'
的参数传递给plt.scatter()