Phlya - 1 year ago 68

Python Question

I recently saw this package for R/ggplot2, which lets one to have multiple annotations on a plot and automatically adjust their position to minimize overlap, and this way improve the readability. Is there anything

similar available for python/matplotlib?

EDIT:

I've found Matplotlib overlapping annotations / text and it looks promising, but seems like the result is inferior to the R package.

Example:

`from matplotlib import pyplot as plt`

import numpy as np

xs = np.arange(10, step=0.1)+np.random.random(100)*3

ys = np.arange(10, step=0.1)+np.random.random(100)*3

labels = np.arange(100)

plt.scatter(xs, ys)

for x, y, s in zip(xs, ys, labels):

plt.text(x, y, s)

plt.show()

You can see that even such short labels create a crazy mess when the data density is high.

Answer Source

[12-11-2016 updated the code and second figure again since the library has been significantly improved since then]

ANSWER COMPLETELY REWRITTEN

I've made a small library for this purpose, which works similarly to above mentioned ggrepel: https://github.com/Phlya/adjustText

With switched off repelling from points it produces something decent even for this difficult example:

```
from matplotlib import pyplot as plt
from adjustText import adjust_text
import numpy as np
np.random.seed(2016)
xs = np.arange(10, step=0.1)+np.random.random(100)*3
ys = np.arange(10, step=0.1)+np.random.random(100)*3
labels = np.arange(100)
f = plt.figure()
scatter = plt.scatter(xs, ys, s=15, c='r', edgecolors='w')
texts = []
for x, y, s in zip(xs, ys, labels):
texts.append(plt.text(x, y, s))
plt.show()
```

```
adjust_text(texts, force_points=0.2, force_text=0.2, expand_points=(1,1), expand_text=(1,1),
arrowprops=dict(arrowstyle="-", color='black', lw=0.5))
plt.show()
```