Python3 matplotlib多层x标签

9rbhqvlz  于 2023-04-21  发布在  Python
关注(0)|答案(1)|浏览(217)

我是matplotlib的新手,希望得到一些帮助来显示多层x-labels。
我有以下代码:

import matplotlib.pyplot as plt

data = {
    "midterm": {"anna": [2,8,6], "adams": [5,10,8], "jane":[4,10,8]},
    "final": {"anna": [3,7,5], "adams": [6,8,7], "jane":[2,8,7]}
}

for key in data.keys():
    y = data[key]["anna"] + data[key]["adams"]+data[key]["jane"]
    plt.plot(y, label=key)

x_location = [1,4,7]
x_labels = ["anna", "adams", "jane"]
plt.xticks(x_location, x_labels)
plt.legend()
plt.show()

它输出以下图:Current Output
我希望X标签是多层的,如:Required Output
请问我该怎么做?

alen0pnh

alen0pnh1#

你可以使用下面的代码来实现。希望这对你有帮助...
小小的解释...
1.以易于绘制的格式获取数据。基本上,索引必须是这样的,级别0是名称(因此这将是x轴中的最低级别),然后是主题(数学,工程,...)。建议您打印df以查看其外观
1.使用pandas绘图,这将为您提供所需的绘图。
1.对于xticklabels的内部(上部)集合,您需要subjects,它位于第1级索引中。注意,对于lineplot,matplotlib在左侧和右侧提供了额外的空间(空格),并且为了使您能够使用set_xticklabels(),您需要在数组的开头和结尾添加空格,这就是我所做的
1.接下来,绘制每次主题值完成时都会出现的垂直线......添加-0.5,以便线在刻度之间,并且您可以获得每条分隔线的位置。vlines将帮助您绘制这些。请注意,在这里,我跳过了第一条和最后一条垂直线,因为我没有在您预期的图片中看到它
1.最后,在两个位置之间添加文本,并稍微更改了大小和粗体,以区分xticklabels的第一级和第二级。
部分部件已从here借用

## Starting with your data...
data = {"midterm": {"anna": [2,8,6], "adams": [5,10,8], "jane":[4,10,8]}, "final": {"anna": [3,7,5], "adams": [6,8,7], "jane":[2,8,7]}}

## Convert to the form that is easy to plot - First index by name and then by Subject
df=pd.DataFrame(data).drop('final', axis=1).explode('midterm')
df['final']=pd.DataFrame(data).drop('midterm', axis=1).explode('final')
df['Subject'] = ['Math', 'Eng', 'Hist']*3
df.set_index('Subject', append=True, inplace=True)

## Figure of size you want and plot... 
fig, ax = plt.subplots(figsize=(12,5))
df.plot(xlabel='', ax=ax)

## Set the x-tick labels to the subjects (first level). As lineplot gives extra space at start and end, add blanks
myticklabels= df.index.get_level_values(level=1).tolist()
myticklabels.insert(0,'') 
myticklabels.append('')

## First level labels as per subject 
ax.set_xticklabels(myticklabels, rotation=0)

## Draw vertical lines (I am not including the lines at the ends)
pos=[]
pos.append(-0.5)
for i in range(len(df.index.unique(level=0))):
    pos.append((i+1)*len(df.index.unique(level='Subject'))-0.5)
ax.vlines(pos[1:-1], 0, -0.4, color='black', lw=1.5, clip_on=False, transform=ax.get_xaxis_transform())

## Draw second level axes ticklables
for ps0, ps1, lbl in zip(pos[:-1], pos[1:], df.index.unique(level=0)):
    ax.text((ps0 + ps1) / 2, -0.12, lbl, ha='center', clip_on=False, transform=ax.get_xaxis_transform(), weight = 'bold', size=13)

剧情

相关问题