I use matplotlib to plot a scatter chart:
And label the bubble using a transparent box according to the tip at How to annotate point on a scatter automatically placed arrow
Here is the code:
if show_annote:
for i in range(len(x)):
annote_text = annotes[i][0][0] # STK_ID
ax.annotate(annote_text, xy=(x[i], y[i]), xytext=(-10,3),
textcoords='offset points', ha='center', va='bottom',
bbox=dict(boxstyle='round,pad=0.2', fc='yellow', alpha=0.2),
fontproperties=ANNOTE_FONT)
and the resulting plot:
But there is still room for improvement to reduce overlap (for instance the label box offset is fixed as (-10,3)). Are there algorithms that can:
- dynamically change the offset of label box according to the crowdedness of its neighbourhood
- dynamically place the label box remotely and add an arrow line beween bubble and label box
- somewhat change the label orientation
- label_box overlapping bubble is better than label_box overlapping label_box?
I just want to make the chart easy for human eyes to comprehand, so some overlap is OK, not as rigid a constraint as http://en.wikipedia.org/wiki/Automatic_label_placement suggests. And the bubble quantity within the chart is less than 150 most of the time.
I find the so called Force-based label placement
http://bl.ocks.org/MoritzStefaner/1377729 is quite interesting. I don't know if there is any python code/package available to implement the algorithm.
I am not an academic guy and not looking for an optimum solution, and my python codes need to label many charts, so the speed/memory is in the scope of consideration.