我不知道你是否已经解决了这个问题,但是,从我迄今为止从你的代码中看到的以及(也从 Evgeny 的代码中借用的)你的需求来看,你有不同级别的水平的唯一原因条,因为您已将 matplotlib (matplotlib.pyplot.barh(y, width, height=0.8, left=None, *, align='center', **kwargs) 的 barh 的标量 y 定义为一个范围。因此,每个连续堆叠的条都列在单独的级别上。
所以,我冒昧地下载了您的数据集并稍微修改了一下代码。
我从 google 数据集创建了一个数据框,并为每个 Dynasty(Dynasty_col 列)和 Age(Age_col 列)分配了 matplotlib CSS 颜色(这不是必需的,但是我发现这更易于管理可视化):
然后为了复制您的夏朝表示,我只是创建了一个子集:
在此之后,我主要保留了您/Evgeny 的代码已经显示的内容,并进行了一些小的更改:
event = data_set_xia['EnglishName']
begin = data_set_xia['Start']
end = data_set_xia['Finish']
length = data_set_xia['Length']
这里我添加了一个用垂直线命名的级别(您可以延长或缩短数组 [-2, 2, -1, 1] 以获得不同级别的标签):
levels = np.tile([-2, 2, -1, 1],
int(np.ceil(len(begin)/4)))[:len(begin)]
import matplotlib.pyplot as plt
plt.style.use('ggplot')
plt.figure(figsize=(12,6))
在这里,我基本上将所有朝代添加到同一个 y 标量(列为 0)上,该行的其余部分已修改为对应于条形的颜色并给出边缘颜色。
plt.barh(0, (end-begin), color=data_set_xia.loc[:,"Dynasty_col"], height =0.3 ,left=begin, edgecolor = "black")
plt.tick_params(axis='both', which='major', labelsize=15)
plt.tick_params(axis='both', which='minor', labelsize=20)
plt.title('Xia Dynasty', fontsize = '25')
plt.xlabel('Year', fontsize = '20')
# plt.yticks(range(len(begin)), "")
ax = plt.gca()
ax.axes.yaxis.set_visible(False)
plt.xlim(-2250, -1700)
plt.ylim(-5,5)
我在标签的垂直线上玩了一下,标签与级别相关联以创建情节。
plt.vlines(begin+length/2, 0, levels, color="tab:red")
for i in range(18):
plt.text(begin.iloc[i] + length.iloc[i]/2,
levels[i]*1.3, event.iloc[i],
ha='center', fontsize = '12')
plt.tight_layout()
plt.show()
这导致了夏朝的以下图表:
使用更大的子集,我也可以生成另一个图表:
和
现在显然,条目数越长,图表就越繁忙和混乱,它开始看起来有点难看,但仍然清晰可见。另外,代码不是“完美”的,我会稍微清理一下并更改一些命令选项,例如 barh 参数中的 color,但它现在可以工作。
对于另一种表示,我添加了不同朝代按时间交错表示的代码,因为一些朝代相互重叠:
event = data_set_adj['EnglishName']
begin = data_set_adj['Start']
end = data_set_adj['Finish']
length = data_set_adj['Length']
dynasty = data_set_adj['Dynasty']
dynasty_col = data_set_adj['Dynasty_col']
dict_dynasty = dict(zip(dynasty.unique(), range(0,4*len(dynasty.unique()),4)))
levels = np.tile([-1.2,1.2, -0.8, 0.8, -0.4, 0.4],
int(np.ceil(len(begin)/6)))[:len(begin)]
import matplotlib.pyplot as plt
plt.style.use('ggplot')
plt.figure(figsize=(20,10))
for x in range(len(dynasty)):
plt.vlines(begin.iloc[x]+length.iloc[x]/2, dict_dynasty[dynasty.iloc[x]], dict_dynasty[dynasty.iloc[x]]+levels[x], color="tab:red")
plt.barh(dict_dynasty[dynasty.iloc[x]], (end.iloc[x]-begin.iloc[x]), color=dynasty_col.iloc[x], height =0.3 ,left=begin.iloc[x], edgecolor = "black", alpha = 0.5)
if x%2==0:
plt.text(begin.iloc[x] + length.iloc[x]/2,
dict_dynasty[dynasty.iloc[x]]+1.6*levels[x], event.iloc[x],
ha='center', fontsize = '8')
else:
plt.text(begin.iloc[x] + length.iloc[x]/2,
dict_dynasty[dynasty.iloc[x]]+1.25*levels[x], event.iloc[x],
ha='center', fontsize = '8')
plt.tick_params(axis='both', which='major', labelsize=15)
plt.tick_params(axis='both', which='minor', labelsize=20)
plt.title('Chinese Dynasties', fontsize = '25')
plt.xlabel('Year', fontsize = '20')
ax = plt.gca()
ax.axes.yaxis.set_visible(False)
plt.xlim(900, 1915)
plt.ylim(-4,28)
plt.tight_layout()
plt.show()
这最后一部分是匆忙完成的,所以代码不是最整洁的,但我在这里唯一更改的是根据数据子集中的朝代更新 barh 的 y 标量我正在考虑。我已经修改了级别和字体大小以提高可读性,您可以使用数字和代码来获得适当的表示。
这导致以下表示:
此外,当我添加 Age_col 列时,您可以将整个事物分类为前帝国和帝国(红色或蓝色)。我暂时没有附上任何图表,但如果你在朝代周围添加一块具有不同“zorder”的该颜色的补丁,那就可以了。
对于可缩放和可平移的图形,我想使用 bokeh 或其他类似的库进行绘图会更好,这样,您可以保持它整洁并专注于有意义的部分?