Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
281 views
in Technique[技术] by (71.8m points)

python - Moving matplotlib xticklabels by pixel value

How can I move tick labels by a few pixels?

In my case, I want to move the This is class #N-labels on the X-axis to the right by a few pixels.

I am aware of the horizontalalign/ha values right, center, and left; but I want to "improve" the looks of the right alignment.

Take the following example which will produce the plot shown below:

import pandas as pd
import numpy as np

categories = ['This is class #{}'.format(n) for n in range(10)]
data = {
    'Value': [categories[np.random.randint(10)] for _ in range(100)], 
    'id': [1000+i for i in range(100)]
}

df = pd.DataFrame(data)

ax = df.Value.value_counts().sort_index().plot(kind='bar', rot=45)
plt.xticks(ha='right')

Results in:

I think, subjectively, that the plot would look better if the labels were translated to the right so that the tick were placed over the "#". In other words, a "middle ground" between the right and center alignment options.

Side notes:

I'm using pandas, but I believe that is irrelevant to the issue, as it's using matplotlib to do its plotting anyway.

The plt.xticks() method is used for simplicity, I could just as well use ax.set_xticklabels(), but I don't need to rewrite the label texts, and AFAIK there is no shortcut to set the horizontal alignment without also copying the existing labels into with ax.set_xticklabels(labels, **more_options), as ha is not a valid key in matplotlib 2's ax.xaxis.set_tick_params()-method.

I'm aware of pandas' Series.hist()-method, but I think the Series.value_counts().plot(kind='bar') looks prettier when I have few categories and want the number of bars to be the same as number of categories.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In order to move the ticklabels by a few pixels you may add a translation to their transformation chain. E.g. to move by 20 pixels to the right, use

import matplotlib.transforms as mtrans
# ...
trans = mtrans.Affine2D().translate(20, 0)
for t in ax.get_xticklabels():
    t.set_transform(t.get_transform()+trans)

If course the number of pixels that you need to shift in order for the #-sign to be under the tickmark is not a priori clear - that needs to be found out via trial and error. Or maybe you have a different hint on by how much you want to shift in what other units.

Here is the complete example,

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import matplotlib.transforms as mtrans

categories = ['This is class #{}'.format(n) for n in range(10)]
data = {
    'Value': [categories[np.random.randint(10)] for _ in range(100)], 
    'id': [1000+i for i in range(100)]
}

df = pd.DataFrame(data)

ax = df.Value.value_counts().sort_index().plot(kind='bar', rot=45)
plt.xticks(ha='right')

trans = mtrans.Affine2D().translate(20, 0)
for t in ax.get_xticklabels():
    t.set_transform(t.get_transform()+trans)

plt.tight_layout()
plt.show()

producing

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...