Matplotlib histogramme avec un bac pour des valeurs élevées
J'ai un tableau avec des valeurs, et je veux créer un histogramme de il. Je suis surtout intéressé par les faibles chiffres de fin, et que vous voulez collecter chaque nombre au-dessus de 300 dans un bac. Ce bac doit avoir la même largeur que tous les autres (à la même échelle) les bacs. Comment puis-je faire cela?
Remarque: cette question est liée à cette question: La définition bin/largeur de l'axe des x de l'échelle dans Matplotlib histogramme
C'est ce que j'ai essayé jusqu'à présent:
import matplotlib.pyplot as plt
import numpy as np
def plot_histogram_01():
np.random.seed(1)
values_A = np.random.choice(np.arange(600), size=200, replace=True).tolist()
values_B = np.random.choice(np.arange(600), size=200, replace=True).tolist()
bins = [0, 25, 50, 75, 100, 125, 150, 175, 200, 225, 250, 275, 300, 600]
fig, ax = plt.subplots(figsize=(9, 5))
_, bins, patches = plt.hist([values_A, values_B], normed=1, # normed is deprecated and will be replaced by density
bins=bins,
color=['#3782CC', '#AFD5FA'],
label=['A', 'B'])
xlabels = np.array(bins[1:], dtype='|S4')
xlabels[-1] = '300+'
N_labels = len(xlabels)
plt.xlim([0, 600])
plt.xticks(25 * np.arange(N_labels) + 12.5)
ax.set_xticklabels(xlabels)
plt.yticks([])
plt.title('')
plt.setp(patches, linewidth=0)
plt.legend()
fig.tight_layout()
plt.savefig('my_plot_01.png')
plt.close()
C'est le résultat, qui n'a pas l'air sympa:
J'ai ensuite changé la ligne avec xlim en elle:
plt.xlim([0, 325])
Avec le résultat suivant:
C'est plus ou moins comme je le veux, mais la dernière bin n'est pas visible aujourd'hui. Qui truc qui me manque pour visualiser cette dernière bin avec une largeur de 25?
Vous devez vous connecter pour publier un commentaire.
Numpy a une fonction très pratique pour faire face à cette:
np.clip
. Malgré ce que le nom peut sembler, il n'a pas supprimer valeurs, il limite juste à la fourchette que vous spécifiez. Fondamentalement, il ne Artem "sale hack" inline. Vous pouvez laisser les valeurs telles qu'elles sont, mais dans lehist
appel, il suffit d'enrouler le tableau dans unenp.clip
appel, commeC'est plus agréable pour un certain nombre de raisons:
C'est façon plus vite — au moins pour un grand nombre d'éléments. Numpy fait son travail à la C niveau. D'exploitation sur les listes python (comme dans l'Art de la compréhension de liste) a beaucoup de frais généraux pour chaque élément. En gros, si jamais vous avez l'option d'utiliser numpy, vous devriez.
Vous le faire là où c'est nécessaire, ce qui réduit le risque de commettre des erreurs dans votre code.
Vous n'avez pas besoin de conserver une deuxième copie du tableau de traîner, ce qui réduit l'utilisation de la mémoire (à l'exception de l'intérieur de cette ligne) et réduit encore plus les chances de faire des erreurs.
À l'aide de
bins[0], bins[-1]
au lieu de coder en dur les valeurs réduit les chances de faire des erreurs, parce que vous pouvez changer les poubelles juste à l'endroit oùbins
a été défini; vous n'avez pas besoin de penser à changer dans l'appel àclip
ou n'importe où ailleurs.Afin de mettre tout cela ensemble comme dans l'OP:
xlabels = bins.astype(str)
,xlabels[-1] += '+'
xlabels = [str(b) for b in bins[1:]]
. Les deux versions sont raisonnables, mais je vais m'en tenir à l'original juste parce que c'est plus en ligne avec les OP. Mais c'est certainement une réelle amélioration de modifier la deuxième ligne dexlabels[-1] += '+'
.Désolé, je ne suis pas familier avec matplotlib. Donc, j'ai un sale hack pour vous. Je viens de mettre toutes les valeurs supérieures à 300 dans un bac et changé la taille de sa corbeille.
La racine du problème, c'est que matplotlib essaie de mettre des poubelles sur la parcelle. En R je voudrais convertir mes bacs de facteur variable, de sorte qu'ils ne sont pas traités comme des nombres réels.