如何均匀地在散点图周围分布标注图像框?

huangapple go评论52阅读模式
英文:

How to evenly spread annotation imageboxes around a scatterplot?

问题

我想要在散点图中注释与每个数据点对应的图像。使用标准参数,图像最终会互相冲突,以及其他重要特性,如图例轴等。因此,我希望这些图像能够形成一个圆形或矩形,环绕主要散点图。

我的代码目前如下,我正在努力修改它,以便将图像组织在绘图的中心点周围。

import matplotlib.cbook as cbook
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
import seaborn as sns

# 生成围绕2D圆的n个点
def generate_circle_points(n, centre_x, center_y, radius=1):
    """生成围绕圆的n个点。
    参数:
        n (int): 要生成的点数。
        centre_x (float): 圆心的x坐标。
        center_y (float): 圆心的y坐标。
        radius (float): 圆的半径。
    返回:
        list: 点的列表。
    """
    points = []
    for i in range(n):
        angle = 2 * np.pi * i / n
        x = centre_x + radius * np.cos(angle)
        y = center_y + radius * np.sin(angle)
        points.append([x, y])
    return points

fig, ax = plt.subplots(1, 1, figsize=(7.5, 7.5))

data = pd.DataFrame(data={'x': np.random.uniform(0.5, 2.5, 20),
                          'y': np.random.uniform(10000, 50000, 20)})

with cbook.get_sample_data('grace_hopper.jpg') as image_file:
    image = plt.imread(image_file)

# 设置x轴和y轴的对数刻度
ax.set(xscale="log", yscale='log')
# 添加网格
ax.grid(True, which='major', ls="--", c='gray')

coordinates = generate_circle_points(n=len(data),
                                      centre_x=0, center_y=0, radius=10)

# 绘制散点图
scatter = sns.scatterplot(data=data, x='x', y='y', ax=ax)
for index, row in data.iterrows():
    imagebox = OffsetImage(image, zoom=0.05)
    imagebox.image.axes = ax
    xy = np.array([row['x'], row['y']])
    xybox = np.array(coordinates[index])
    ab = AnnotationBbox(imagebox, xy,
                        xycoords='data',
                        boxcoords="offset points",
                        xybox=xybox,
                        pad=0)
    ax.add_artist(ab)

目前的输出看起来像这样:点击这里查看图像描述

理想情况下,我希望输出看起来像这样:点击这里查看图像描述

非常感谢您提前的帮助。

英文:

I would like to annotate a scatterplot with images corresponding to each datapoint. With standard parameters the images end up clashing with each other and other important features such as legend axis, etc. Thus, I would like the images to form a circle or a rectangle around the main scatter plot.

My code looks like this for now and I am struggling to modify it to organise the images around the center point of the plot.

import matplotlib.cbook as cbook
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
import seaborn as sns
#Generate n points around a 2d circle
def generate_circle_points(n, centre_x, center_y, radius=1):
"""Generate n points around a circle.
Args:
n (int): Number of points to generate.
centre_x (float): x-coordinate of circle centre.
center_y (float): y-coordinate of circle centre.
radius (float): Radius of circle.
Returns:
list: List of points.
"""
points = []
for i in range(n):
angle = 2 * np.pi * i / n
x = centre_x + radius * np.cos(angle)
y = center_y + radius * np.sin(angle)
points.append([x, y])
return points
fig, ax = plt.subplots(1, 1, figsize=(7.5, 7.5))
data = pd.DataFrame(data={'x': np.random.uniform(0.5, 2.5, 20),
'y': np.random.uniform(10000, 50000, 20)})
with cbook.get_sample_data('grace_hopper.jpg') as image_file:
image = plt.imread(image_file)
# Set logarithmic scale for x and y axis
ax.set(xscale="log", yscale='log')
# Add grid
ax.grid(True, which='major', ls="--", c='gray')
coordianates = generate_circle_points(n=len(data),
centre_x=0, center_y=0, radius=10)
# Plot the scatter plot
scatter = sns.scatterplot(data=data, x='x', y='y', ax=ax)
for index, row in data.iterrows():
imagebox = OffsetImage(image, zoom=0.05)
imagebox.image.axes = ax
xy = np.array([row['x'], row['y']])
xybox = np.array(coordianates[index])
ab = AnnotationBbox(imagebox, xy,
xycoords='data',
boxcoords="offset points",
xybox=xybox,
pad=0)
ax.add_artist(ab)

for the moment the output looks like this:enter image description here

Ideally I would like the output to look to something like this:
enter image description here

Many thanks in advance for your help

答案1

得分: 1

以下是翻译好的部分:

You can control the location of the arrows, but sometimes it is easier to export figures as SVGs and edit them in Adobe Illustrator or Inkscape.

R has a dodge argument which is really nice, but even then is not always perfect. Solutions in Python exist but are laborious.

The major issue is that this needs to be done last as alternations to the plot would make it problematic. A few points need mentioning.

Your figures will have to have a fixed size (57mm / 121mm / 184mm for Science, 83mm / 171mm for RSC, 83mm / 178mm for ACS etc.), if you need to scale the figure in Illustrator keep note of the scaling factor, adding it as a textbox outside of the canvas —as the underlying plot will need to be replaced at least once due to Murphy's law. Exporting at the right size the SVG is ideal. Sounds silly, but it helps. Likewise, make sure the font size does not go under the minimum spec (7-9 points).

英文:

Not an answer but a long comment:

You can control the location of the arrows, but sometimes it is easier to export figures as SVGs and edit them in Adobe Illustrator or Inkscape.

R has a dodge argument which is really nice, but even then is not always perfect. Solutions in Python exist but are laborious.

The major issue is that this needs to be done last as alternations to the plot would make it problematic. A few points need mentioning.

Your figures will have to have a fixed size (57mm / 121mm / 184mm for Science, 83mm / 171mm for RSC, 83mm / 178mm for ACS etc.), if you need to scale the figure in Illustrator keep note of the scaling factor, adding it as a textbox outside of the canvas —as the underlying plot will need to be replaced at least once due to Murphy's law. Exporting at the right size the SVG is ideal. Sounds silly, but it helps. Likewise, make sure the font size does not go under the minimum spec (7-9 points).

huangapple
  • 本文由 发表于 2023年2月14日 07:11:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/75442035.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定