python - real - Histograma de suma en lugar de contar usando numpy y maplotlib
matplotlib python (1)
Tengo algunos datos con dos columnas por fila. En mi caso, el tiempo y el área de presentación de trabajos.
He usado la función hist de matplotlib para producir un gráfico con el tiempo agrupado por día en el eje x y contar por día en el eje 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()
Ahora quiero un gráfico con el tiempo agrupado por día en el eje xy el área sumada por el área del depósito en el eje y.
Hasta ahora he llegado a esto usando una lista de comprensión:
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()
Todavía soy nuevo en NumPy y me gustaría saber si puedo mejorar:
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
Entonces no usa listas de Python.
¿Es posible de alguna manera explotar sum_by[bin_index==i]
así que obtengo una matriz de matrices, con length len(bins)
? Entonces np.sum()
devolvería una matriz numpy.
Tanto la función hist
de Matplotlib como la función de histogram
de NumPy tienen un argumento de palabra clave opcional de weights
. Creo que las únicas líneas relevantes para cambiar en tu primer código deberían ser:
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'')