历元列表的图直方图,x轴按月年在PyPlot中

时间:2019-05-09 07:49:33

标签: python matplotlib histogram

有一个历元列表,pyplotnumpy中是否有一个参数可以构成一个直方图,其中binsdata列表中的月份相匹配?在此示例中,列表对应于2012年至2013年的随机日期。如果data中的值仅对应于这几个月中的日期,我希望直方图显示从2012年2月至2013年10月的条形图

此代码制作了一个直方图,但它为bins=24手动分隔。

import numpy as np
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import random

data = [int(random.randint(1293836400, 1356994800)) for _ in range(1000)]

# convert the epoch format to matplotlib date format
mpl_data = mdates.epoch2num(data)

fig, ax = plt.subplots(1,1)
ax.hist(mpl_data, bins=24, ec='black')
ax.xaxis.set_major_locator(mdates.MonthLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%d.%m.%y'))
fig.autofmt_xdate()
plt.show()

1 个答案:

答案 0 :(得分:0)

为此,您必须选择每个月初开始的时间戳。日期/时间总是比常规数字复杂得多,因此尽管此代码看起来有点麻烦,但它确实可以工作。

import numpy as np
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import random

data = [int(random.randint(1293836400, 1356994800)) for _ in range(1000)]

# create your bins as timestamps marked at the beginning of each month, using datetime objects to increment
import datetime as d
mindate = d.datetime.fromtimestamp(min(data))
maxdate = d.datetime.fromtimestamp(max(data))
bindate = d.datetime(year=mindate.year, month=mindate.month, day=1)
bins = [bindate.timestamp()]
while bindate < maxdate:
    if bindate.month == 12:
        bindate = d.datetime(year=bindate.year + 1, month=1, day=1)
    else:
        bindate = d.datetime(year=bindate.year, month=bindate.month + 1, day=1)
    bins.append(bindate.timestamp())
bins = mdates.epoch2num(bins)

mpl_data = mdates.epoch2num(data)
fig, ax = plt.subplots(1,1, figsize=(16, 4), facecolor='white')
ax.hist(mpl_data, bins=bins, ec='black')
ax.xaxis.set_major_locator(mdates.MonthLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%d.%m.%y'))
fig.autofmt_xdate()

enter image description here

另一种方法是使用pandas按月份对数据进行分组,然后对它们进行计数。代码要短得多,您可以进行快速条形图绘制。要在上面重新创建绘图,将需要更多的工作,但这会让您感觉可以使用其他工具进行操作:

srs = pd.DatetimeIndex(pd.Series(data) * 1e9)  # convert sec to nsec
df = pd.DataFrame({'count': np.ones(shape=len(srs))}, index=srs)
fig, ax = plt.subplots(1, 1, figsize=(16,4), facecolor='white')
df.groupby(pd.Grouper(freq='M')).count().plot.bar(ax=ax)

enter image description here