使用 matplotlib 更改线条样式比例间距

Changing line style proportional spacing using matplotlib

对于分布不均的数据,几乎所有点的颜色都过于相似。例如。下图表示对应value < 12000的颜色太浅。

所以,我考虑使用 Pysal 将数据范围分成几个 class 并将颜色图平均分配给这些 classes。

这是我的尝试

我的粗略工作

from pysal.esda.mapclassify import Natural_Breaks as nb
import pysal.esda.mapclassify as mpc
from matplotlib.colors import Normalize

my_bins = [ 20,200,600,1600, 4000, 36000]    
breaks =mpc.User_Defined(value,my_bins)     

bin_labels = ["%0.0f" % b for b in breaks.bins]
bins = pd.DataFrame({'Class': breaks.yb},)  

然后,每个点都有一个基于其值的数据范围的class。

fig = plt.figure()
ax  =plt.subplot()
cmap = plt.get_cmap('coolwarm')
norm1 = Normalize(vmin=bins['Class'].min(), vmax=bins['Class'].max())
em_plot = plt.scatter(px[:],py[:], linewidth='0',c =   
np.array(bins['Class']),s =(value**0.4)*10, cmap = cmap,\
                  norm = norm1,alpha = 0.7)
cbaxes = fig.add_axes([0.6625, 0.175, 0.175, 0.04]) 
cbar = plt.colorbar(em_plot,cax=cbaxes,orientation='horizontal')
value_list = np.array([1,3,5,]) ### THE CLASS
value_label = ['200', '1600','36000'] ### THE VALUE CORRESPONDING TO CLASS
cbar.set_ticks(value_list)
cbar.set_ticklabels(value_label)
cbar.ax.tick_params(labelsize=8) 

我的目标

我想用离散的圆圈标记散点,而不是条形图例颜色:每个圆圈代表主要图形上特定值的大小和颜色。

此处显示我在 Internet 上找到的插图:

如上图所示,不同颜色的percentage图例就是我理想的目标!

如有任何建议,我们将不胜感激!

更新

感谢您的回答。我试过你的方法。但似乎并不完全符合我的目标。

这是我的图,以答案为参考。

从图例和颜色条中,我们可以发现由于映射策略不同,颜色不一样(colorbar -> classify result; legend -> REAL VALUE)

然后,我做一些这样的调整:

cmap = plt.get_cmap('coolwarm')
colors=cmap(np.arange(6)/6.0)

ls = [Line2D(range(1), range(1), linewidth=0,  
      color=colors[np.where(np.array(my_bins) == v)[0]], \      
      marker='o', ms=(v**0.2)*2) for v in my_bins]

plt.legend(ls,my_bins)  

但是出错了:

ValueError: to_rgba: Invalid rgba arg "[[ 0.2298057 0.29871797 0.75368315 1. ]]" length of rgba sequence should be either 3 or 4

更新 2

感谢戴维斯的回答,我想生成my_bins的元素的索引。因此,我尝试使用 np.where(my_bins == element).
来获取索引 但它失败了。然后,我尝试使用:

 ..., color = colors[i], ms=(v**0.2)*2) for i,v in enumerate(my_bins)

有效!

我认为 "easiest" 会为您的图例创建一个 proxy artist

以下是可行的,但需要根据您的需要进行调整,我不确定色图的归一化和点的大小是否正确。

from matplotlib.lines import Line2D
cmap = plt.get_cmap('coolwarm')
my_bins = [20,200,600,1600, 4000, 36000]
ls = [Line2D(range(1), range(1), linewidth=0, color=cmap(v), marker='o', ms=(v**0.2)) for v in my_bins]
plt.plot()
plt.legend(ls,my_bins)

更新 关于您更新的问题:您的问题与 color=colors[np.where(np.array(my_bins) == v)[0]] 有关。说实话,我不知道你想在这里做什么。您应该传递一个 (6, 4) 数组,但您传递了一个 (1, 4) 数组。

如果我理解你的代码,你也许应该试试这个:

cmap = plt.get_cmap('coolwarm')
colors=cmap(np.arange(6)/6.0)

ls = [Line2D(range(1), range(1), linewidth=0,  
      color=colors[i], \      
      marker='o', ms=(v**0.2)*2) for i,v in enumerate(my_bins)]

plt.legend(ls,my_bins)