python 如何减少条形图上刻度标签的数量

7d7tgy0s  于 2023-05-21  发布在  Python
关注(0)|答案(3)|浏览(174)

下面的条形图在x轴上太杂乱了。
有没有一种方式可以增加我的刻度?而不是显示18-55之间的每一个刻度,它增加了3或5(或更多),所以它看起来更好?我注意到,当我运行一个线图时,它会自动增加10。**

import matplotlib as mpl
from matplotlib import pyplot as plt
import numpy as np

agesx = [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
          36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55]

py_devy = [20046, 17100, 20000, 24744, 30500, 37732, 41247, 45372, 48876, 53850, 57287, 63016, 65998, 70003, 70000, 71496, 75370, 83640, 84666,
            84392, 78254, 85000, 87038, 91991, 100000, 94796, 97962, 93302, 99240, 102736, 112285, 100771, 104708, 108423, 101407, 112542, 122870, 120000]

js_devy = [16446, 16791, 18942, 21780, 25704, 29000, 34372, 37810, 43515, 46823, 49293, 53437, 56373, 62375, 66674, 68745, 68746, 74583, 79000,
            78508, 79996, 80403, 83820, 88833, 91660, 87892, 96243, 90000, 99313, 91660, 102264, 100000, 100000, 91660, 99240, 108000, 105000, 104000]

all_devy = [17784, 16500, 18012, 20628, 25206, 30252, 34368, 38496, 42000, 46752, 49320, 53200, 56000, 62316, 64928, 67317, 68748, 73752, 77232,
         78000, 78508, 79536, 82488, 88935, 90000, 90056, 95000, 90000, 91633, 91660, 98150, 98964, 100000, 98988, 100000, 108923, 105000, 103117]

width = 0.25
x_indexes = np.arange(len(agesx))
 
plt.xticks(ticks=x_indexes,labels=agesx)

plt.style.use("seaborn-dark")
plt.bar(x_indexes-width, all_devy, width=width, label= "All Devs")
plt.bar(x_indexes,py_devy,width=width, label= "Python Devs")
plt.bar(x_indexes + width, js_devy, width=width, label= "Javascript Dev")

plt.title("Median Developer Salaries by Age (USD)")
plt.xlabel("Ages")
plt.ylabel("Salary (USD)")
plt.tight_layout()

plt.legend()
plt.show()

这导致下图:

起初我以为我可以解决这个问题

plt.xticks(np.arange(18,55,3))

然而,它会导致以下输出:

我怎样才能修改它,使图表从18开始,而不是从18开始?

8yparm6h

8yparm6h1#

如果我们使用matplotlib.pyplotsubplot,那么我们可以迭代get_xticks(),并使用list-comprehension索引agesx中的标签,以获得_xticklabelssetlist作为xticklabels。我们不想改变xticks,因为第0xtick应该是18,我们想改变的是xticklabels,并保持xticks不变:

import matplotlib as mpl
from matplotlib import pyplot as plt
import numpy as np

agesx = [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
          36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55]

py_devy = [20046, 17100, 20000, 24744, 30500, 37732, 41247, 45372, 48876, 53850, 57287, 63016, 65998, 70003, 70000, 71496, 75370, 83640, 84666,
            84392, 78254, 85000, 87038, 91991, 100000, 94796, 97962, 93302, 99240, 102736, 112285, 100771, 104708, 108423, 101407, 112542, 122870, 120000]

js_devy = [16446, 16791, 18942, 21780, 25704, 29000, 34372, 37810, 43515, 46823, 49293, 53437, 56373, 62375, 66674, 68745, 68746, 74583, 79000,
            78508, 79996, 80403, 83820, 88833, 91660, 87892, 96243, 90000, 99313, 91660, 102264, 100000, 100000, 91660, 99240, 108000, 105000, 104000]

all_devy = [17784, 16500, 18012, 20628, 25206, 30252, 34368, 38496, 42000, 46752, 49320, 53200, 56000, 62316, 64928, 67317, 68748, 73752, 77232,
         78000, 78508, 79536, 82488, 88935, 90000, 90056, 95000, 90000, 91633, 91660, 98150, 98964, 100000, 98988, 100000, 108923, 105000, 103117]

width = 0.25
x_indexes = np.arange(len(agesx))
#plt.xticks(ticks=x_indexes,labels=agesx)

ax = plt.subplot(1, 1, 1)
plt.style.use("seaborn-dark")
ax.bar(x_indexes-width, all_devy, width=width, label= "All Devs")
ax.bar(x_indexes,py_devy,width=width, label= "Python Devs")
ax.bar(x_indexes + width, js_devy, width=width, label= "Javascript Dev")

ax.set_title("Median Developer Salaries by Age (USD)")
ax.set_xlabel("Ages")
ax.set_ylabel("Salary (USD)")
plt.tight_layout()
_xticklabels = [agesx[int(_xtick)] for _xtick in ax.get_xticks() if int(_xtick) < len(agesx)]
ax.set_xticklabels(_xticklabels)
ax.legend()
plt.show()

输出:

如果我们希望xticklabels510中,同时从18开始,那么我们还必须修改xticks并使用numpyarange函数,使其成为listinsert成为0的索引:

...
_xticks = list(np.arange(2, len(agesx), 5).astype(int))
_xticks.insert(0, 0)
ax.set_xticks(_xticks)
_xticklabels = [agesx[_xtick] for _xtick in ax.get_xticks()]
ax.set_xticklabels(_xticklabels)
...

输出:

或者如果我们想要每隔一个agesx标签:

...
_xticks = np.arange(0, len(agesx), 2).astype(int)
ax.set_xticks(_xticks)
xticklabels = [agesx[_xtick] for _xtick in ax.get_xticks()]
ax.set_xticklabels(xticklabels)
...

输出:

但是我们不能设置agesx的每个标签,否则会有重叠的xticklabels

...
_xticks = np.arange(0, len(agesx), 1).astype(int)
ax.set_xticks(_xticks)
xticklabels = [agesx[_xtick] for _xtick in ax.get_xticks()]
ax.set_xticklabels(xticklabels)
...

输出:

7rfyedvj

7rfyedvj2#

  • 问题使用隐式的“pyplot”接口,因此,两个简单的选项是:
  • 增加图形的宽度:
  • fig = plt.figure(figsize=(10, 6))
  • plt.figure(figsize=(10, 6))
  • 使用plt.xticks设置刻度数
    *python 3.11.2pandas 2.0.1matplotlib 3.7.1中测试

增大图幅

# increase the figure size
plt.figure(figsize=(10, 6))

plt.bar(x_indexes-width, all_devy, width=width, label= "All Devs")
plt.bar(x_indexes,py_devy,width=width, label= "Python Devs")
plt.bar(x_indexes + width, js_devy, width=width, label= "Javascript Dev")
_ = plt.xticks(ticks=x_indexes, labels=agesx)

指定xtick标签plt.xticks

  • plt.xticks(np.arange(18, 55, 3))不起作用,因为与线图不同,条形图的刻度是0索引的。print(plt.gca().get_xticklabels())在索引0处显示'18'
  • 使用plt.xticks(ticks=x_indexes, labels=agesx)预设刻度和标签
  • [v if i%2 == 0 else '' for i, v in enumerate(agesx)]使用列表解析将每隔一个标签设置为空字符串。
  • 增加2,以减少刻度标签。
plt.bar(x_indexes-width, all_devy, width=width, label= "All Devs")
plt.bar(x_indexes,py_devy,width=width, label= "Python Devs")
plt.bar(x_indexes + width, js_devy, width=width, label= "Javascript Dev")

# adjust the frequency of the visible labels; the number of ticks and labels must be the same
_ = plt.xticks(ticks=range(len(agesx)), labels=[v if i%2 == 0 else '' for i, v in enumerate(agesx)])

  • 或者,使用pandas,这使得分组和堆叠条形图更容易。matplotlibpandas.DataFrame.plot的默认后端。
  • 下面的示例将返回的matplotlib.axes.Axes分配给ax,这是显式的“Axes”接口。
import pandas as pd

# load data to pandas
data = {'Python Devs': py_devy, 'Javascript Devs': js_devy, 'All Devs': all_devy}
df = pd.DataFrame(data=data, index=agesx)

# 1. plot the bars with rotated labels
ax = df.plot(kind='bar', width=0.85, rot=90)

# 2. plot with increased figure size
ax = df.plot(kind='bar', width=0.85, figsize=(10, 6), rot=0)

# 3. plot horizontal bars, which may be better for many bars, and long labels
ax = df.plot(kind='barh', width=0.85, figsize=(6, 7))

# 4. every other tick label
ax = df.plot(kind='bar', width=0.85, rot=0, xticks=range(len(df.index))[::2])
_ = ax.set_xticklabels(df.index[::2])

plot1plot2plot3plot4
df.head()

Python Devs  Javascript Devs  All Devs
18        20046            16446     17784
19        17100            16791     16500
20        20000            18942     18012
21        24744            21780     20628
22        30500            25704     25206
emeijp43

emeijp433#

下面的条形图在x轴上太杂乱了。
IMHO混乱是Matplotlib试图告诉你,你的图是相当拥挤的。

import matplotlib.pyplot as plt
import numpy as np

agesx = [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55]
py_devy =  [20046, 17100, 20000, 24744, 30500, 37732, 41247, 45372, 48876, 53850, 57287, 63016, 65998, 70003, 70000, 71496, 75370, 83640, 84666, 84392, 78254, 85000, 87038, 91991, 100000, 94796, 97962, 93302, 99240, 102736, 112285, 100771, 104708, 108423, 101407, 112542, 122870, 120000]
js_devy =  [16446, 16791, 18942, 21780, 25704, 29000, 34372, 37810, 43515, 46823, 49293, 53437, 56373, 62375, 66674, 68745, 68746, 74583, 79000, 78508, 79996, 80403, 83820, 88833, 91660, 87892, 96243, 90000, 99313, 91660, 102264, 100000, 100000, 91660, 99240, 108000, 105000, 104000]
all_devy = [17784, 16500, 18012, 20628, 25206, 30252, 34368, 38496, 42000, 46752, 49320, 53200, 56000, 62316, 64928, 67317, 68748, 73752, 77232, 78000, 78508, 79536, 82488, 88935, 90000, 90056, 95000, 90000, 91633, 91660, 98150, 98964, 100000, 98988, 100000, 108923, 105000, 103117]

rmean = lambda l,n:[sum(t)/n for t in zip(*(l[i:]for i in range(n)))]
N = 5

plt.style.use("seaborn-v0_8-dark")
for y, label in zip((py_devy,js_devy,all_devy),
                  'Python JavaScript all'.split()):
     plt.plot(rmean(agesx, N), rmean(y, N), label=label+' devs')
plt.ylim((-1000, 120000))
plt.grid()
plt.legend()
plt.xlabel('Central Age for the running mean')
plt.ylabel('Median Salary, €')
plt.suptitle('              Median Developer Salary')
plt.title('— running mean over %d age classes —'%N, size='small')
plt.tight_layout()
plt.show()

相关问题