我要在条形图中添加如下标记图像:
我尝试了AnnotationBbox,但是显示为正方形轮廓。谁能说出与上图完全一样的方法?
编辑:
下面是我的代码
df$Year <- ifelse(df$Month >= 1 & df$Month <= 12*1, '1',
ifelse(df$Month >= 1+12 & df$Month <= 12*2, '2',
ifelse(df$Month >= 1+12*2 & df$Month <= 12*3, '3',
...
ifelse(df$Month >= 1+12*9 & df$Month <= 12*10, '10', NA))))))))))
编辑2:
ax.barh(y = y, width = values, color = r, height = 0.8)
height = 0.8
for i, (value, url) in enumerate(zip(values, image_urls)):
response = requests.get(url)
img = Image.open(BytesIO(response.content))
width, height = img.size
left = 10
top = 10
right = width-10
bottom = height-10
im1 = img.crop((left, top, right, bottom))
print(im1.size)
im1
ax.imshow(im1, extent = [value - 6, value, i - height / 2, i + height / 2], aspect = 'auto', zorder = 2)
答案 0 :(得分:1)
您需要使用T
格式且背景透明的图像。 (如果图像没有所需的背景,则Gimp或ImageMagick之类的软件可能会有所帮助。)
有了这样的图像,plt.imshow()
可以将其放置在绘图中。通过.png
给出位置。为防止extent=[x0, x1, y0, y1]
强制使用相等的长宽比,请添加imshow
。 aspect='auto'
有助于使图像显示在条形图的顶部。之后,zorder=2
和plt.xlim
需要显式设置(同样是因为plt.ylim
弄乱了它们。)
下面的示例代码使用了matplotlib的“ ada.png”,因此可以独立测试该代码。现在,它正在countryflags.io之后从this post加载标志。
请注意,图像被放入data coordinates中的盒子中(在这种情况下为6宽和0.9高)。例如,当绘图大小调整时,此框将被拉伸。您可能要根据x比例和图形尺寸将6更改为另一个值。
imshow
PS:如Ernest在评论和this post中所述,使用import numpy as np
import matplotlib.pyplot as plt
# import matplotlib.cbook as cbook
import requests
from io import BytesIO
labels = ['CW', 'CV', 'GW', 'SX', 'DO']
colors = ['crimson', 'dodgerblue', 'teal', 'limegreen', 'gold']
values = 30 + np.random.randint(5, 20, len(labels)).cumsum()
height = 0.9
plt.barh(y=labels, width=values, height=height, color=colors, align='center')
for i, (label, value) in enumerate(zip(labels, values)):
# load the image corresponding to label into img
# with cbook.get_sample_data('ada.png') as image_file:
# img = plt.imread(image_file)
response = requests.get(f'https://www.countryflags.io/{label}/flat/64.png')
img = plt.imread(BytesIO(response.content))
plt.imshow(img, extent=[value - 8, value - 2, i - height / 2, i + height / 2], aspect='auto', zorder=2)
plt.xlim(0, max(values) * 1.05)
plt.ylim(-0.5, len(labels) - 0.5)
plt.tight_layout()
plt.show()
时图像的长宽比保持不变。 (此外,OffsetImage
和xlim
保持不变。)当条形更多时,图像不会缩小,因此您可能需要试验ylim
中的因子和x偏移量在OffsetImage(img, zoom=0.65)
中。
对于过短的条形,一个额外的选项可以将标志放置在条形之外。或在y轴的左侧。
适用于单杠的代码如下:
AnnotationBbox(..., xybox=(-25, 0))
答案 1 :(得分:1)
要完成@johanC答案,可以在GNU / linux和iso-flags-png
python包下使用iso3166
中的标志:
import matplotlib.pyplot as plt
from iso3166 import countries
import matplotlib.image as mpimg
def pos_image(x, y, pays, haut):
pays = countries.get(pays).alpha2.lower()
fichier = "/usr/share/iso-flags-png-320x240"
fichier += f"/{pays}.png"
im = mpimg.imread(fichier)
ratio = 4 / 3
w = ratio * haut
ax.imshow(im,
extent=(x - w, x, y, y + haut),
zorder=2)
plt.style.use('seaborn')
fig, ax = plt.subplots()
liste_pays = [('France', 10), ('USA', 9), ('Spain', 5), ('Italy', 5)]
X = [p[1] for p in liste_pays]
Y = [p[0] for p in liste_pays]
haut = .8
r = ax.barh(y=Y, width=X, height=haut, zorder=1)
y_bar = [rectangle.get_y() for rectangle in r]
for pays, y in zip(liste_pays, y_bar):
pos_image(pays[1], y, pays[0], haut)
plt.show()