python scatter plot area size proportional axis length

拟墨画扇 提交于 2019-12-02 11:30:14

问题


I'm getting quite desperate about this, I couldn't find anything on the www so far.

Here's the situation:

  • I am working with Python.
  • I have 3 arrays: the x-coordinates, the y-coordinates and the radius.
  • I want to create a scatter plot with the given x- and y-coordinates.

So far, everything works how I want it to. Here is what's bothering me:

  • The circle size of each point in the scatter plot should be defined by the radius array.
  • The the values of the coordinates and the radius are in same units. More explicitly: Let's assume I have a point at (1, 1) with radius 0.5 assigned. Then I want to get a circle in the plot centered at (1, 1) and with the border going throught the points (1.5, 1), (1, 1.5), (0.5, 1) and (1, 0.5)

What I am struggling with is to find out the ratio of plot points to the length in an axis. I need to work with points because as far as I can see, the circle size of the scatter plot is given in point values. So if let's say my axis goes from 0 to 10, I need to know how many points there are in between in the plot.

Can anybody help me? Or is there another way of doing this? Thanks in advance.


回答1:


I'm jumping in from your other stackoverflow question. I think the approach you presented as an answer to the present question won't work exactly as you want for the following reasons:

  • First, the size of the markers is in points, not in pixels. In typography, the point is the smallest unit of measure and correspond in matplotlib to a fixed length of 1/72 inch. In contrast, the size of a pixel will vary following the figure dpi and size.
  • Second, the size of the markers in plt.scatter are related to the diameter of the circles, not the radius.

So the size in points of each marker should be calculated as:

size_in_points = (2 * radius_in_pixels / fig_dpi * 72 points/inch)**2

Moreover, as shown in the MWE below, it is possible to calculate the size of the marker radius in pixels directly with matplotlib transformations, without having to generate an empty figure beforehand:

import numpy as np
import matplotlib.pyplot as plt

plt.close('all')

# Generate some data :
N = 25
x = np.random.rand(N) + 0.5
y = np.random.rand(N) + 0.5
r = np.random.rand(N)/10

# Plot the data :
fig = plt.figure(facecolor='white', figsize=(7, 7))
ax = fig.add_subplot(111, aspect='equal')
ax.grid(True)
scat = ax.scatter(x, y, s=0, alpha=0.5, clip_on=False)
ax.axis([0, 2, 0, 2])

# Draw figure :
fig.canvas.draw()

# Calculate radius in pixels :
rr_pix = (ax.transData.transform(np.vstack([r, r]).T) -
          ax.transData.transform(np.vstack([np.zeros(N), np.zeros(N)]).T))
rpix, _ = rr_pix.T

# Calculate and update size in points:
size_pt = (2*rpix/fig.dpi*72)**2
scat.set_sizes(size_pt)

# Save and show figure:
fig.savefig('scatter_size_axes.png')
plt.show()

A point at (1, 1) with radius 0.5 assigned will result in a circle in the plot centered at (1, 1) and with the border going throught the points (1.5, 1), (1, 1.5), (0.5, 1) and (1, 0.5):



来源:https://stackoverflow.com/questions/36458458/python-scatter-plot-area-size-proportional-axis-length

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!