繁体   English   中英

防止标签在 matplotlib 垂直时间轴 plot 中重叠

[英]Prevent labels from overlapping in matplotlib vertical timeline plot

我通常用于防止数据标签重叠的方法似乎不适用于这个基于 matplotlib 的垂直时间线。 通常我会使用类似autofmt_xdate的东西。

我实际上并不关心图表需要有多“高”(长),或者项目之间的垂直距离是否完美地保留了项目之间的日期差距的比率。 我只是不希望文本标签重叠。

我对matplotlib不是很有经验,但到目前为止我已经确定控制文本标签的代码是

_ = ax.text(label_offsets[i], d, l, ha=align, fontfamily='serif', fontweight='bold', color='royalblue',fontsize=12)

其中d是用作 y 轴坐标的时间戳。 我尝试创建一个循环计数器和一个列表以包含每次循环迭代中的d值,以便我可以在当前日期和前一个日期之间进行比较,然后将一个固定值(例如 15 天)添加到d的当前值如果d的先前值太接近。 这似乎没有奏效。

plot 代码:

chartdata = pd.read_csv(
    "data/Events.csv"
)

chartdata = chartdata.query('Year > 1939')

dates = pd.to_datetime(chartdata['Date_Clean_Approx'])
min_date = date(np.min(dates).year - 2, np.min(dates).month, np.min(dates).day)
max_date = date(np.max(dates).year + 2, np.max(dates).month, np.max(dates).day)

labels = chartdata['Name']

# labels with associated dates
labels = ['{0:%d %b %Y}:\n{1}'.format(d, l) for l, d in zip (labels, dates)]

fig, ax = plt.subplots(figsize=(6, 32), constrained_layout=True)
_ = ax.set_xlim(-20, 20)
_ = ax.set_ylim(min_date, max_date)
_ = ax.axvline(0, ymin=0.05, ymax=0.95, c='deeppink', zorder=1)

_ = ax.scatter(np.zeros(len(dates)), dates, s=120, c='palevioletred', zorder=2)
_ = ax.scatter(np.zeros(len(dates)), dates, s=30, c='darkmagenta', zorder=3)

label_offsets = np.repeat(2.0, len(dates))
label_offsets[1::2] = -2.0

for i, (l, d) in enumerate(zip(labels, dates)):
    d = d - timedelta(days=90)
    align = 'right'
    if i % 2 == 0:
        align = 'left'
    _ = ax.text(label_offsets[i], d, l, ha=align, fontfamily='serif', fontweight='bold', color='royalblue',fontsize=12)

stems = np.repeat(2.0, len(dates))
stems[1::2] *= -1.0    
x = ax.hlines(dates, 0, stems, color='darkmagenta')

# hide lines around chart
for spine in ["left", "top", "right", "bottom"]:
    _ = ax.spines[spine].set_visible(False)

# hide tick labels
_ = ax.set_xticks([])
_ = ax.set_yticks([])
_ = ax.set_title('UAP (UFO) Milestones, 1940 - Present', 
                 fontweight="bold", 
                 fontfamily='serif', 
                 fontsize=16, 
                 color='royalblue')

pyplot(fig)

正如您在图片中看到的,我增加了 plot 的高度以减少标签中的重叠。 plot 变得很长,但在文本中仍有重叠。 Once a solution is determined I think that embedding the logic to "adjust relative gap size and chart height as needed to avoid text label overlap" into a convenient plot function would be a large contribution to the matplotlib library.

很长的垂直时间线

我绝对愿意接受更好、更程序化的解决方案,但现在我用相同长度的连续整数向量替换了日期,并用它代替了除标签文本之外的任何地方的实际日期。

###### Timeline#
chartdata = pd.read_csv(
    "/home/kodachi/Documents/ET/aliendb/www/app/data/Events.csv"
)

chartdata=chartdata.query('Year > 1939')
dates = pd.to_datetime(chartdata['Date_Clean_Approx'])
min_date = date(np.min(dates).year - 2, np.min(dates).month, np.min(dates).day)
max_date = date(np.max(dates).year + 2, np.max(dates).month, np.max(dates).day)

###
# fake date 
fake_d=np.c_[1:len(dates)]
###
labels = chartdata['Name']

# labels with associated dates
labels = ['{0:%d %b %Y}:\n{1}'.format(d, l) for l, d in zip (labels, dates)]

fig, ax = plt.subplots(figsize=(8, 28))#, constrained_layout=True)
_ = ax.set_xlim(-20, 20)
#_ = ax.set_ylim(min_date, max_date)
_ = ax.set_ylim(1, 96)
_ = ax.axvline(0, ymin=0.05, ymax=.985, c='deeppink', zorder=1)#ymax=0.95
#_ = ax.scatter(np.zeros(len(dates)), dates, s=120, c='palevioletred', zorder=2)
#_ = ax.scatter(np.zeros(len(dates)), dates, s=30, c='darkmagenta', zorder=3)
_ = ax.scatter(np.zeros(len(fake_d)), fake_d, s=120, c='palevioletred', zorder=2)
_ = ax.scatter(np.zeros(len(fake_d)), fake_d, s=30, c='darkmagenta', zorder=3)

#label_offsets = np.repeat(2.0, len(dates))
label_offsets = np.repeat(2.0, len(fake_d))
label_offsets[1::2] = -2.0


for i, (l, d) in enumerate(zip(labels, fake_d)): #dates
    #d = d - timedelta(days=90) 
    align = 'right'
    if i % 2 == 0:
        align = 'left'
    _ = ax.text(label_offsets[i], d, l, ha=align, fontfamily='serif', 
                fontweight='bold', color='royalblue',fontsize=12)

#stems = np.repeat(2.0, len(dates))
stems = np.repeat(2.0, len(fake_d))
stems[1::2] *= -1.0    
#x = ax.hlines(dates, 0, stems, color='darkmagenta')
x = ax.hlines(fake_d, 0, stems, color='darkmagenta')

# hide lines around chart
for spine in ["left", "top", "right", "bottom"]:
    _ = ax.spines[spine].set_visible(False)

# hide tick labels
_ = ax.set_xticks([])
_ = ax.set_yticks([])
_ = ax.set_title('UAP (UFO) Milestones, 1940 - Present', 
                 fontweight="bold", 
                 fontfamily='serif', 
                 fontsize=16, 
                 color='darkgreen')

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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