项目里需要画一个散点图(泡泡图),但是有一个问题,图例的大小跟实际图中泡泡的尺寸是相对成比例的,而我期望图例大小是一样的.
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
from matplotlib.pyplot import MultipleLocator
import random
import json
import math
import sys
import colorsys
import numpy
myfont = fm.FontProperties(fname=r'/usr/share/fonts/custom/simhei.ttf') # 设置字体
saveGraphPath = sys.argv[1] ## 图片的保存路径
fig, ax = plt.subplots(figsize=(13, 7))
xmin = 10000
xmax = -10000
ymin = 10000
ymax = -10000
# 这段代码生成随机数据,x,y,value(泡泡的size)
xlist = []
ylist = []
valuelist = []
maxValue = -1 # 记录value最大值
for i in range(0, 26):
thisX = random.randint(-10, 30)
xlist.append(thisX)
thisY = random.randint(-100, 200)
ylist.append(thisY)
thisValue = random.randint(100, 100000)
valuelist.append(thisValue)
if thisValue > maxValue:
maxValue = thisValue
# 颜色列表
rgb = [[0.2, 0.2, 1], [0.2, 0.5, 0.8], [1, 0.8, 0.2], [0.8, 1, 0.2], [0.2, 1, 0.8], [0.2, 0.8, 1], [0.8, 0.2, 1],
[1, 0.7, 0.85], [1, 0, 0], [1, 0, 0.6],
[0.5, 0.5, 1], [0.3, 0.3, 0.3], [0, 1, 0], [1, 0.5, 0], [1, 0, 0.5], [0.5, 0, 1], [0, 0.5, 1], [0.5, 1, 0],
[0, 1, 0.5], [1, 0.5, 0.5],
[0.5, 0.2, 0.8], [0.3, 0.4, 1], [0.6, 0.9, 0.1], [0.1, 0.451, 0.333], [0.77, 0.63, 0.231], [0.5, 0.8, 1]]
for i in range(0, 26):
scale2 = 8000 / math.sqrt(maxValue / valuelist[i]) #泡泡的尺寸,为了value值适应xy轴的大小,作了数据处理
scale = 4 / math.sqrt(maxValue / valuelist[i]) #用于设定margin
x = xlist[i]
if x - scale < xmin:
xmin = x - scale
if x + scale > xmax:
xmax = x + scale
y = ylist[i]
if y - scale < ymin:
ymin = y - scale
if y + scale > ymax:
ymax = y + scale
name = xlist[i] + ylist[i] + valuelist[i]
color = rgb[i % 26]
plt.scatter(x, y, c=color, s=scale2, label=name, alpha=0.7, edgecolors='none')
# scatter = plt.scatter(x, y, c=color, s=0.1, label=name, alpha=0.7, edgecolors='none')
nameList.append(name)
# scatterLIst.append(scatter)
#设定margin让图片更协调
xmin = xmin
xmax = xmax
ymin = ymin / 2 + ymin
ymax = ymax / 5 + ymax
plt.xlim(xmin, xmax)
plt.ylim(ymin, ymax)
# 设点y轴的间隔
y_major_locator = MultipleLocator(25)
ax.yaxis.set_major_locator(y_major_locator)
# 图片画两条基准线
plt.axvline(x=10.0001, color='k', linestyle='--')
plt.axhline(y=10, color='k', linestyle='--')
legend1 = ax.legend(loc='center left', bbox_to_anchor=(1, 0.6), ncol=1, prop=myfont, fontsize=15, markerscale=0.2,
labelspacing=0.7)
#四个象限增加文字
plt.text(xmin + 1, ymax - 16, "XX类别", fontproperties=myfont, fontsize=18)
plt.text(xmax - 3, ymax - 16, "XX类别", fontproperties=myfont, fontsize=18)
plt.text(xmax - 3, ymin + 10, "XX类别", fontproperties=myfont, fontsize=18)
plt.text(xmin + 1, ymin + 10, "XX类别", fontproperties=myfont, fontsize=18)
# xy轴的意思
plt.xlabel("XXX率%", fontproperties=myfont, fontsize=15)
plt.ylabel("XXX率%", fontproperties=myfont, fontsize=15)
ax.grid(True)
plt.tight_layout()
plt.savefig(saveGraphPath, bbox_inches='tight')
plt.show()
去看了ax.legend文档,没有设定相同尺寸的参数,然后在stack overflow找啊找,还是没找的解决方法.
后来灵机一动,画另一组具有相同x,y,color,name,value值的散点图,scale数值一样(需要足够小),用它来表示图例
修改部分用多行注释进行了标识
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
from matplotlib.pyplot import MultipleLocator
import random
import json
import math
import sys
import colorsys
import numpy
myfont = fm.FontProperties(fname=r'/usr/share/fonts/custom/simhei.ttf') # 设置字体
saveGraphPath = sys.argv[1] ## 图片的保存路径
fig, ax = plt.subplots(figsize=(13, 7))
xmin = 10000
xmax = -10000
ymin = 10000
ymax = -10000
# 这段代码生成随机数据,x,y,value(泡泡的size)
xlist = []
ylist = []
valuelist = []
maxValue = -1 # 记录value最大值
for i in range(0, 26):
thisX = random.randint(-10, 30)
xlist.append(thisX)
thisY = random.randint(-100, 200)
ylist.append(thisY)
thisValue = random.randint(100, 100000)
valuelist.append(thisValue)
if thisValue > maxValue:
maxValue = thisValue
"""
记录另一组散点用来生成图例
"""
nameList = []
scatterLIst = []
colorList = []
# 颜色列表
rgb = [[0.2, 0.2, 1], [0.2, 0.5, 0.8], [1, 0.8, 0.2], [0.8, 1, 0.2], [0.2, 1, 0.8], [0.2, 0.8, 1], [0.8, 0.2, 1],
[1, 0.7, 0.85], [1, 0, 0], [1, 0, 0.6],
[0.5, 0.5, 1], [0.3, 0.3, 0.3], [0, 1, 0], [1, 0.5, 0], [1, 0, 0.5], [0.5, 0, 1], [0, 0.5, 1], [0.5, 1, 0],
[0, 1, 0.5], [1, 0.5, 0.5],
[0.5, 0.2, 0.8], [0.3, 0.4, 1], [0.6, 0.9, 0.1], [0.1, 0.451, 0.333], [0.77, 0.63, 0.231], [0.5, 0.8, 1]]
for i in range(0, 26):
scale2 = 8000 / math.sqrt(maxValue / valuelist[i])
scale = 4 / math.sqrt(maxValue / valuelist[i])
x = xlist[i]
if x - scale < xmin:
xmin = x - scale
if x + scale > xmax:
xmax = x + scale
y = ylist[i]
if y - scale < ymin:
ymin = y - scale
if y + scale > ymax:
ymax = y + scale
name = xlist[i] + ylist[i] + valuelist[i]
color = rgb[i % 26]
plt.scatter(x, y, c=color, s=scale2, label=name, alpha=0.7, edgecolors='none')
"""
画另一组散点,这里我scale设定都设为0.1
并记录在nameList,scatterList中
"""
scatter = plt.scatter(x, y, c=color, s=0.1, label=name, alpha=0.7, edgecolors='none')
nameList.append(name)
scatterLIst.append(scatter)
#设定margin让图片更协调
xmin = xmin
xmax = xmax
ymin = ymin / 2 + ymin
ymax = ymax / 5 + ymax
plt.xlim(xmin, xmax)
plt.ylim(ymin, ymax)
# 设点y轴的间隔
y_major_locator = MultipleLocator(25)
ax.yaxis.set_major_locator(y_major_locator)
# 图片画两条基准线
plt.axvline(x=10.0001, color='k', linestyle='--')
plt.axhline(y=10, color='k', linestyle='--')
#legend1 = ax.legend(loc='center left', bbox_to_anchor=(1, 0.6), ncol=1, prop=myfont, fontsize=15, markerscale=0.2,
# labelspacing=0.7)
"""
markerscale 设定为37
人工设定handles和labels
"""
legend1 = ax.legend(handles =scatterLIst,labels = nameList, loc='center left', bbox_to_anchor=(1, 0.5), ncol=1,prop=myfont,fontsize = 15,markerscale = 37,labelspacing = 0.7)
#四个象限增加文字
plt.text(xmin + 1, ymax - 16, "XX类别", fontproperties=myfont, fontsize=18)
plt.text(xmax - 3, ymax - 16, "XX类别", fontproperties=myfont, fontsize=18)
plt.text(xmax - 3, ymin + 10, "XX类别", fontproperties=myfont, fontsize=18)
plt.text(xmin + 1, ymin + 10, "XX类别", fontproperties=myfont, fontsize=18)
# xy轴的意思
plt.xlabel("XXX率%", fontproperties=myfont, fontsize=15)
plt.ylabel("XXX率%", fontproperties=myfont, fontsize=15)
ax.grid(True)
plt.tight_layout()
plt.savefig(saveGraphPath, bbox_inches='tight')
plt.show()