matplotlib:如何防止x轴标签彼此重叠

我正在用matplotlib生成条形图。一切正常,但我想不出如何防止x轴的标签相互重叠。这里有个例子:

在此处输入图片说明

这是一些Postgres 9.1数据库的示例SQL:

drop table if exists mytable;

create table mytable(id bigint, version smallint, date_from timestamp without time zone);

insert into mytable(id, version, date_from) values

('4084036', '1', '2006-12-22 22:46:35'),

('4084938', '1', '2006-12-23 16:19:13'),

('4084938', '2', '2006-12-23 16:20:23'),

('4084939', '1', '2006-12-23 16:29:14'),

('4084954', '1', '2006-12-23 16:28:28'),

('4250653', '1', '2007-02-12 21:58:53'),

('4250657', '1', '2007-03-12 21:58:53')

;

这是我的python脚本:

# -*- coding: utf-8 -*-

#!/usr/bin/python2.7

import psycopg2

import matplotlib.pyplot as plt

fig = plt.figure()

# for savefig()

import pylab

###

### Connect to database with psycopg2

###

try:

conn_string="dbname='x' user='y' host='z' password='pw'"

print "Connecting to database\n->%s" % (conn_string)

conn = psycopg2.connect(conn_string)

print "Connection to database was established succesfully"

except:

print "Connection to database failed"

###

### Execute SQL query

###

# New cursor method for sql

cur = conn.cursor()

# Execute SQL query. For more than one row use three '"'

try:

cur.execute("""

-- In which year/month have these points been created?

-- Need 'yyyymm' because I only need Months with years (values are summeed up). Without, query returns every day the db has an entry.

SELECT to_char(s.day,'yyyymm') AS month

,count(t.id)::int AS count

FROM (

SELECT generate_series(min(date_from)::date

,max(date_from)::date

,interval '1 day'

)::date AS day

FROM mytable t

) s

LEFT JOIN mytable t ON t.date_from::date = s.day

GROUP BY month

ORDER BY month;

""")

# Return the results of the query. Fetchall() = all rows, fetchone() = first row

records = cur.fetchall()

cur.close()

except:

print "Query could not be executed"

# Unzip the data from the db-query. Order is the same as db-query output

year, count = zip(*records)

###

### Plot (Barchart)

###

# Count the length of the range of the count-values, y-axis-values, position of axis-labels, legend-label

plt.bar(range(len(count)), count, align='center', label='Amount of created/edited points')

# Add database-values to the plot with an offset of 10px/10px

ax = fig.add_subplot(111)

for i,j in zip(year,count):

ax.annotate(str(j), xy=(i,j), xytext=(10,10), textcoords='offset points')

# Rotate x-labels on the x-axis

fig.autofmt_xdate()

# Label-values for x and y axis

plt.xticks(range(len(count)), (year))

# Label x and y axis

plt.xlabel('Year')

plt.ylabel('Amount of created/edited points')

# Locate legend on the plot (http://matplotlib.org/users/legend_guide.html#legend-location)

plt.legend(loc=1)

# Plot-title

plt.title("Amount of created/edited points over time")

# show plot

pylab.show()

有没有一种方法可以防止标签相互重叠?理想情况下以自动方式进行,因为我无法预测条形图的数量。

回答:

我认为您对matplotlib如何处理日期感到有些困惑。

目前,您实际上并没有在绘制日期。您正在x轴上绘制事物[0,1,2,...],然后使用日期的字符串表示形式手动标记每个点。

Matplotlib将自动定位刻度线。但是,您要超越matplotlib的报价定位功能(xticks基本上是在说:“我想在这些位置准确报价”。)

此刻,[10, 20, 30, ...]如果matplotlib自动将它们定位,您将获得滴答声。但是,这些将对应于您用于绘制它们的值,而不是日期(绘制时未使用的日期)。

您可能想使用日期实际绘制事物。

目前,您正在执行以下操作:

import datetime as dt

import matplotlib.dates as mdates

import numpy as np

import matplotlib.pyplot as plt

# Generate a series of dates (these are in matplotlib's internal date format)

dates = mdates.drange(dt.datetime(2010, 01, 01), dt.datetime(2012,11,01),

dt.timedelta(weeks=3))

# Create some data for the y-axis

counts = np.sin(np.linspace(0, np.pi, dates.size))

# Set up the axes and figure

fig, ax = plt.subplots()

# Make a bar plot, ignoring the date values

ax.bar(np.arange(counts.size), counts, align='center', width=1.0)

# Force matplotlib to place a tick at every bar and label them with the date

datelabels = mdates.num2date(dates) # Go back to a sequence of datetimes...

ax.set(xticks=np.arange(dates.size), xticklabels=datelabels) #Same as plt.xticks

# Make space for and rotate the x-axis tick labels

fig.autofmt_xdate()

plt.show()

而是尝试这样的事情:

import datetime as dt

import matplotlib.dates as mdates

import numpy as np

import matplotlib.pyplot as plt

# Generate a series of dates (these are in matplotlib's internal date format)

dates = mdates.drange(dt.datetime(2010, 01, 01), dt.datetime(2012,11,01),

dt.timedelta(weeks=3))

# Create some data for the y-axis

counts = np.sin(np.linspace(0, np.pi, dates.size))

# Set up the axes and figure

fig, ax = plt.subplots()

# By default, the bars will have a width of 0.8 (days, in this case) We want

# them quite a bit wider, so we'll make them them the minimum spacing between

# the dates. (To use the exact code below, you'll need to convert your sequence

# of datetimes into matplotlib's float-based date format.

# Use "dates = mdates.date2num(dates)" to convert them.)

width = np.diff(dates).min()

# Make a bar plot. Note that I'm using "dates" directly instead of plotting

# "counts" against x-values of [0,1,2...]

ax.bar(dates, counts, align='center', width=width)

# Tell matplotlib to interpret the x-axis values as dates

ax.xaxis_date()

# Make space for and rotate the x-axis tick labels

fig.autofmt_xdate()

plt.show()

以上是 matplotlib:如何防止x轴标签彼此重叠 的全部内容, 来源链接: utcz.com/qa/422110.html

回到顶部