如何在海洋散点图图例中适应太大的点大小?

时间:2020-03-27 13:25:54

标签: python matplotlib seaborn

我创建了一系列带有Seaborn的气泡图,除了图例外,它看起来还不错: enter image description here

我使用以下命令创建了该图:

ax = sns.scatterplot(x='year', y='population', hue='Country', data=temp,
                     size="density", sizes=(1500, 5000), alpha=0.25, palette="muted")

如何从图例中删除“国家/地区”并仅保留密度?文档中没有此类选项。另外,如何估算气泡中的值并使它们更可见?

可运行的代码:

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
temp = pd.DataFrame({'year': [1980, 1980, 1980, 1980, 1980], 'population': [2.87,2.95,3.45,4.18,4.67], 'Country': ['ALB','ARM'
,'URY','PAN','CAF'], 'density': [1.0,1.03,1.2,1.46,1.63] })

ax=sns.scatterplot(x='year', y='population', hue='Country', data=temp,size="density", sizes=(500, 1500), alpha=0.25, palette="muted" )    
ax.set_xlim(1950,2030)
for line in temp.index:
    ax.text(temp.year[line], temp.population[line], temp.Country[line], horizontalalignment='center', size='medium', color='black', weight='semibold')
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
ax.set_ylabel("")
ax.set_xlabel("")
ax.set_title("Population density in 5 closely populated countries")

1 个答案:

答案 0 :(得分:2)

ax.get_legend_handles_labels()获取图例的当前句柄和标签。这些只是列表,可以通过切片来缩短。显示尺寸的手柄太大,无法放入图例中。只需获取尺寸,缩放比例并重新设置即可。 (请注意,handles[i].get_sizes()返回一个列表,通常只有一个条目。)

标签只是字符串。如果需要,可以重新创建它们,例如具有不同的格式。要更改显示的位数,可以先将标签转换为浮点,然后再转换回字符串f{float(label):.2f}'(使用f-strings进行格式化)。请注意,第一个标签是标题,应该以不同的方式处理。

(可选)可以扩展ylimits,因为默认的填充不考虑较大的散点。另外,文本可以垂直居中以更好地适合圆圈。

import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd

temp = pd.DataFrame({'year': [1980, 1980, 1980, 1980, 1980],
                     'population': [2.87, 2.95, 3.45, 4.18, 4.67],
                     'Country': ['ALB', 'ARM', 'URY', 'PAN', 'CAF'],
                     'density': [1.0, 1.03, 1.2, 1.46, 1.63]})

ax = sns.scatterplot(x='year', y='population', hue='Country', data=temp,
                     size="density", sizes=(500, 1500), alpha=0.25, palette="muted")
ax.set_xlim(1950, 2030)
ylim0, ylim1 = ax.get_ylim()
ydelta = (ylim1 - ylim0) * 0.05
ax.set_ylim(ylim0 - ydelta, ylim1 + ydelta)
for line in temp.index:
    ax.text(temp.year[line], temp.population[line], temp.Country[line], ha='center', va='center', size='medium',
            color='black', weight='semibold')
handles, labels = ax.get_legend_handles_labels()
entries_to_skip = len(temp) + 1
handles = handles[entries_to_skip:]
labels = labels[entries_to_skip:]
for h in handles[1:]:
    sizes = [s / 10 for s in h.get_sizes()]
    h.set_sizes(sizes)
labels = labels[:1] + [f'{float(lab):.2f}' for lab in labels[1:]]
plt.legend(handles, labels, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
ax.set_ylabel("")
ax.set_xlabel("")

plt.tight_layout()
plt.show()

resulting plot