使用numpy和matplotlib绘制总和直方图而不是计数直方图

6

我有一些具有每行两列的数据。在我的情况下是工作提交时间和地区。

我使用matplotlib的hist函数,将时间按天分组放在x轴上,每天的数量放在y轴上生成图表:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import datetime as dt

def timestamp_to_mpl(timestamp):
    return mpl.dates.date2num(dt.datetime.fromtimestamp(timestamp))

nci_file_name = 'out/nci.csv'
jobs = np.genfromtxt(nci_file_name, dtype=int, delimiter=',', names=True, usecols(1,2,3,4,5))

fig, ax = plt.subplots(2, 1, sharex=True)
vect_timestamp_to_mpl = np.vectorize(timestamp_to_mpl)
qtime = vect_timestamp_to_mpl(jobs['queued_time'])
start_date = dt.datetime(2013, 1, 1)
end_date = dt.datetime(2013, 4, 1)
bins = mpl.dates.drange(start_date, end_date, dt.timedelta(days=1))
ax[0].hist(qtime[jobs['charge_rate']==1], bins=bins, label='Normal', color='b')
ax[1].hist(qtime[jobs['charge_rate']==3], bins=bins, label='Express', color='g')
ax[0].grid(True)
ax[1].grid(True)
fig.suptitle('NCI Workload Submission Daily Rate')
ax[0].set_title('Normal Queue')
ax[1].set_title('Express Queue')
ax[1].xaxis.set_major_locator(mpl.dates.AutoDateLocator())
ax[1].xaxis.set_major_formatter(mpl.dates.AutoDateFormatter(ax[1].xaxis.get_major_locator()))
ax[1].set_xlim(mpl.dates.date2num(start_date), mpl.dates.date2num(end_date))
plt.setp(ax[1].xaxis.get_majorticklabels(), rotation=25, ha='right')
ax[1].set_xlabel('Date')
ax[0].set_ylabel('Jobs per Day')
ax[1].set_ylabel('Jobs per Day')
fig.savefig('out/figs/nci_sub_rate_day_sub.png')
plt.show()

NCI工作负载每日提交量

我现在想要一个时间按天分组的图表,x轴表示时间,y轴表示每个时间段内的总和。

到目前为止,我用列表推导式得到了以下结果:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import datetime as dt

def timestamp_to_mpl(timestamp):
    return mpl.dates.date2num(dt.datetime.fromtimestamp(timestamp))

def binsum(bin_by, sum_by, bins):
    bin_index = np.digitize(bin_by, bins)
    sums = [np.sum(sum_by[bin_index==i]) for i in range(len(bins))]
    return sums

fig, ax = plt.subplots(2, 1, sharex=True)
vect_timestamp_to_mpl = np.vectorize(timestamp_to_mpl)
qtime = vect_timestamp_to_mpl(jobs['queued_time'])
area = jobs['run_time'] * jobs['req_procs']
start_date = dt.datetime(2013, 1, 1)
end_date = dt.datetime(2013, 4, 1)
delta = dt.timedelta(days=1)
bins = mpl.dates.drange(start_date, end_date, delta)
sums_norm = binsum(qtime[jobs['charge_rate']==1], area[jobs['charge_rate']==1], bins)
sums_expr = binsum(qtime[jobs['charge_rate']==3], area[jobs['charge_rate']==3], bins)
ax[0].bar(bins, sums_norm, width=1.0, label='Normal', color='b')
ax[1].bar(bins, sums_expr, width=1.0, label='Express', color='g')
ax[0].grid(True)
ax[1].grid(True)
fig.suptitle('NCI Workload Area Daily Rate')
ax[0].set_title('Normal Queue')
ax[1].set_title('Express Queue')
ax[1].xaxis.set_major_locator(mpl.dates.AutoDateLocator())
ax[1].xaxis.set_major_formatter(mpl.dates.AutoDateFormatter(ax[1].xaxis.get_major_locator()))
ax[1].set_xlim(mpl.dates.date2num(start_date), mpl.dates.date2num(end_date))
plt.setp(ax[1].xaxis.get_majorticklabels(), rotation=25, ha='right')
ax[1].set_xlabel('Date')
ax[0].set_ylabel('Area per Day')
ax[1].set_ylabel('Area per Day')
fig.savefig('out/figs/nci_area_day_sub.png')
plt.show()

NCI工作负载区日费率

我还不太熟悉NumPy,想知道是否可以提升:

def binsum(bin_by, sum_by, bins):
    bin_index = np.digitize(bin_by, bins)
    sums = [np.sum(sum_by[bin_index==i]) for i in range(len(bins))]
    return sums

因此,它不使用Python列表。

是否有可能以某种方式展开sum_by [bin_index == i],使我得到一个数组的数组,长度为len(bins)?然后np.sum()将返回一个numpy数组。


3
这个问题太长了。你得到了答案,因为Jamie很棒,但是如果你提出一些最小化代码来演示问题的问题(例如使用合成数据,删除所有格式等),你会做得更好。 - tacaswell
嗯,也许我不需要这段代码,但我认为它会更容易理解我的意思,即总和的直方图而不是计数。这种类型的图表有一个正式名称吗? - ljbade
1个回答

10
Matplotlib的hist函数和NumPy的histogram函数都有一个可选的关键字参数weights。我认为你第一段代码中需要更改的唯一相关行应该是:
ax[0].hist(qtime[jobs['charge_rate']==1], weights=area[jobs['charge_rate']==1],
           bins=bins, label='Normal', color='b')
ax[1].hist(qtime[jobs['charge_rate']==3], weights=area[jobs['charge_rate']==3],
           bins=bins, label='Express', color='g')

2
谢谢,这简单多了。看来我想得太多了!他们应该在matplotlib网站上添加这样的示例。 - ljbade

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接