Python 如何使 Matplotlib 散点图作为一个组透明?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30108372/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to make Matplotlib scatterplots transparent as a group?
提问by Jason
I'm making some scatterplots using Matplotlib (python 3.4.0, matplotlib 1.4.3, running on Linux Mint 17). It's easy enough to set alpha transparency for each point individually; is there any way to set them as a group, so that two overlapping points from the same group don't change the color?
我正在使用 Matplotlib(python 3.4.0,matplotlib 1.4.3,在 Linux Mint 17 上运行)制作一些散点图。为每个点单独设置 alpha 透明度很容易;有什么方法可以将它们设置为一组,以便同一组中的两个重叠点不会改变颜色?
Example code:
示例代码:
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")
Results in this output:
此输出中的结果:
but I want something more like this one:
但我想要更像这样的东西:
I can workaround by saving as SVG and manually grouping then in Inkscape, then setting transparency, but I'd really prefer something I can code. Any suggestions?
我可以通过另存为 SVG 并在 Inkscape 中手动分组,然后设置透明度来解决,但我真的更喜欢我可以编码的东西。有什么建议?
采纳答案by Flabetvibes
Yes, interesting question. You can get this scatterplot with Shapely. Here is the code :
是的,有趣的问题。你可以用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")
and the result is :
结果是:
回答by Ed Smith
Interesting question, I think any use of transparency will result in the stacking effect you want to avoid. You could manually set a transparency type colour to get closer to the results you want,
有趣的问题,我认为任何使用透明度都会导致您想要避免的堆叠效果。您可以手动设置透明度类型颜色以更接近您想要的结果,
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()
The overlap between the different colours are not included in this way but you get,
不同颜色之间的重叠不以这种方式包括在内,但你会得到,
回答by Arcanist Lupus
This is a terrible, terrible hack, but it works.
这是一个可怕的、可怕的黑客,但它有效。
You see while Matplotlib plots data points as separate objects that can overlap, it plots the line between them as a single object - even if that line is broken into several pieces by NaNs in the data.
您会看到,虽然 Matplotlib 将数据点绘制为可以重叠的单独对象,但它将它们之间的线绘制为单个对象 - 即使该线被数据中的 NaN 分成几段。
With that in mind, you can do this:
考虑到这一点,您可以这样做:
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()
And each color will overlap with the other color but not with itself.
并且每种颜色都会与另一种颜色重叠,但不会与自身重叠。
One caveat is that you have to be careful with the spacing between the two points you use to make each circle. If they're two far apart then the separation will be visible on your plot, but if they're too close together, matplotlib doesn't plot the line at all. That means that the separation needs to be chosen based on the range of your data, and if you plan to make an interactive plot then there's a risk of all the data points suddenly vanishing if you zoom out too much, and stretching if you zoom in too much.
一个警告是,您必须小心用于制作每个圆的两点之间的间距。如果它们两个相距很远,则在您的绘图上可以看到分离,但如果它们靠得太近,则 matplotlib 根本不会绘制线条。这意味着需要根据数据范围选择分离度,如果您打算制作交互式绘图,那么如果缩小太多,则所有数据点都有可能突然消失,如果放大则可能会拉伸太多了。
As you can see, I found 1e-5 to be a good separation for data with a range of [0,1].
如您所见,我发现 1e-5 可以很好地分离范围为 [0,1] 的数据。