简体   繁体   中英

Matplotlib labels are overlapping

I have an image where every column has an associated attribute. I would like to plot the image and label each column with its attribute value. Here is a simple code showing what I mean:

import matplotlib.pyplot as plt
import numpy as np
from scipy.ndimage.filters import gaussian_filter

np.random.seed(200)

cols = 600
attr = list('abcdefghijklmnopqrstuvwxyz') * cols
attr = labels[:cols]
img = gaussian_filter(np.random.rand(400, cols), 100)
plt.imshow(img, cmap='inferno')
plt.xticks(np.arange(cols), attr)
plt.show()

The resulting image below shows how messy the X-labels get. What I would like is to show some labels, which get updated when interacting with the plot, like zooming and panning.

The reason I think this is possible is because the default behavior of maplotlib is correct (when not setting the xticks). It shows the column number in intervals so labels do not overlap, and get updated when zooming & panning.

So, my question is: is it possible to get the default matplotlib's label behavior with custom labels?

Overlapping labels

在此输入图像描述

Default behavior

在此输入图像描述

What you want is called tick formatting . In this case you can create an instance of FuncFormatter and assign it to the major ticks.

First you need to add FuncFormatter to your imports:

import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
import numpy as np
from scipy.ndimage.filters import gaussian_filter

You need a function that takes the tick value and its position and return the tick label. You won't need the position here but it will be passed to the function anyway. Make sure the function can handle unexpected tick values (I used matplotlib 2.0.0b4 and it put a tick at 600).

cols = 600
letters = list('abcdefghijklmnopqrstuvwxyz')
attr = (letters * (1 + cols // len(letters)))[:cols]

def format_tick(labels):
    def get_label(x, pos):
        try:
            return labels[int(round(x))]
        except IndexError:
            return ''
    return get_label

Create a FuncFormatter instance using your format function:

formatter = FuncFormatter(format_tick(attr))

Set formatter as the major formatter for your plot:

rs = np.random.RandomState(seed=200)
img = gaussian_filter(rs.rand(400, cols), 100)
plt.imshow(img, cmap='inferno')
plt.gca().xaxis.set_major_formatter(formatter)

自定义刻度标签

Of course this labelling does not make any sense with your sample data. I'm sure there's a better way for your actual use case, whatever it is.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM