使用matplotlib更改线型比例间距

时间:2016-06-21 14:29:15

标签: python python-2.7 matplotlib visualization legend

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

enter image description here

因此,我考虑使用 Pysal 将数据范围分成几个类,并将色彩图均匀地分配给这些类。

这是我的尝试

  • Lat是每个点的纬度
  • Lon是每个点的经度
  • Value是与每个点对应的属性,我想用不同的标记颜色和大小绘制它

我的粗略工作

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},)  

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

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) 

enter image description here

我的目标

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

我在互联网上找到的插图如下所示:

enter image description here

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

任何建议都会受到赞赏!

更新

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

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

enter image description here

从图例和颜色栏,我们发现由于不同的映射策略(颜色栏 - &gt;分类结果;图例 - &gt;真实值),颜色不一样

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

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:无效的rgba arg&#34; [[0.2298057 0.29871797 0.75368315 1.]]&#34;   rgba序列的长度应为3或4

更新2

感谢Davis的回答,我想生成my_bins元素的索引。所以,我试图通过使用np.where(my_bins == element)来获得指数 但它失败了。然后,我尝试使用:

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

有效!

1 个答案:

答案 0 :(得分:1)

我认为“最简单”就是为你的传奇创建一个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)

enter image description here

<强>更新 关于您更新的问题:您的问题是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)