web-dev-qa-db-fra.com

Le graphique à barres Matplotlib l'axe x ne tracera pas les valeurs de chaîne

Je m'appelle David et je travaille pour un service d'ambulance en Floride.

J'utilise Python 2.7 et matplotlib. J'essaie d'accéder à ma base de données d'appels d'ambulance et de compter le nombre d'appels qui se produisent chaque jour de semaine.

Je vais ensuite utiliser matplotlib pour créer un graphique à barres de ces informations pour donner aux ambulanciers paramédicaux un graphique visuel de la façon dont ils sont occupés chaque jour.

ICI IS CODE QUI FONCTIONNE TRÈS BIEN:

import pyodbc
import matplotlib.pyplot as plt
MySQLQuery = """
SELECT 
 DATEPART(WEEKDAY, IIU_tDispatch)AS [DayOfWeekOfCall]
, COUNT(DATEPART(WeekDay, IIU_tDispatch)) AS [DispatchesOnThisWeekday]
FROM AmbulanceIncidents
GROUP BY DATEPART(WEEKDAY, IIU_tDispatch)
ORDER BY DATEPART(WEEKDAY, IIU_tDispatch)
"""
cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=MyServer;DATABASE=MyDatabase;UID=MyUserID;PWD=MyPassword')
cursor = cnxn.cursor()
GraphCursor = cnxn.cursor()
cursor.execute(MySQLQuery)

#generate a graph to display the data
data = GraphCursor.fetchall()
DayOfWeekOfCall, DispatchesOnThisWeekday = Zip(*data)
plt.bar(DayOfWeekOfCall, DispatchesOnThisWeekday)
plt.grid()
plt.title('Dispatches by Day of Week')
plt.xlabel('Day of Week')
plt.ylabel('Number of Dispatches')
plt.show()

Le code ci-dessus fonctionne très bien. Il renvoie un joli graphique et je suis heureux. Je veux juste faire un changement.

Au lieu de l'axe X montrant les noms des jours de la semaine, tels que "dimanche", il montre l'entier. En d'autres termes, dimanche est 1, lundi est 2, etc.

Ma solution est que je réécris ma requête SQL pour utiliser DATENAME () au lieu de DATEPART (). Ci-dessous est mon code sql pour retourner le nom de la semaine (par opposition à un entier).

SELECT 
 DATENAME(WEEKDAY, IIU_tDispatch)AS [DayOfWeekOfCall]
, COUNT(DATENAME(WeekDay, IIU_tDispatch)) AS [DispatchesOnThisWeekday]
FROM AmbulanceIncidents
GROUP BY DATENAME(WEEKDAY, IIU_tDispatch)
ORDER BY DATENAME(WEEKDAY, IIU_tDispatch)

Tout le reste dans mon code python reste le même. Cependant, cela ne fonctionnera pas et je ne peux pas comprendre les messages d'erreur.

Voici les messages d'erreur:

Traceback (most recent call last):
  File "C:\Documents and Settings\kulpandm\workspace\FiscalYearEndReport\CallVolumeByDayOfWeek.py", line 59, in 

<module>
    plt.bar(DayOfWeekOfCall, DispatchesOnThisWeekday)
  File "C:\Python27\lib\site-packages\matplotlib\pyplot.py", line 2080, in bar
    ret = ax.bar(left, height, width, bottom, **kwargs)
  File "C:\Python27\lib\site-packages\matplotlib\axes.py", line 4740, in bar
    self.add_patch(r)
  File "C:\Python27\lib\site-packages\matplotlib\axes.py", line 1471, in add_patch
    self._update_patch_limits(p)
  File "C:\Python27\lib\site-packages\matplotlib\axes.py", line 1489, in _update_patch_limits
    xys = patch.get_patch_transform().transform(vertices)
  File "C:\Python27\lib\site-packages\matplotlib\patches.py", line 547, in get_patch_transform
    self._update_patch_transform()
  File "C:\Python27\lib\site-packages\matplotlib\patches.py", line 543, in _update_patch_transform
    bbox = transforms.Bbox.from_bounds(x, y, width, height)
  File "C:\Python27\lib\site-packages\matplotlib\transforms.py", line 745, in from_bounds
    return Bbox.from_extents(x0, y0, x0 + width, y0 + height)
TypeError: coercing to Unicode: need string or buffer, float found

Je ne peux pas comprendre cela.

Pour résumer, lorsque je produis mes données avec l'axe x sous forme d'entiers représentant les jours de la semaine et l'axe y montrant un décompte du nombre d'incidents d'ambulance, Matplotlib produira un joli graphique. Mais lorsque ma sortie de données est l'axe des x, c'est une chaîne (dimanche, lundi, etc.). alors Matplotlib ne fonctionnera pas.

J'ai fait plusieurs heures de recherche sur Google et lu la documentation de matplotlib. S'il vous plait, j'ai besoin de votre aide avec ceci. J'espère utiliser Matplotlib comme moteur de rapports.

33
David Kulpanowski

Votre question n'a rien à voir avec une requête SQL, c'est simplement un moyen de terminer. Ce que vous demandez vraiment, c'est comment changer les étiquettes de texte sur un graphique à barres dans pylab. Les documents pour graphique à barres sont utiles pour la personnalisation, mais simplement changer les étiquettes voici un exemple de travail minimal (MWE):

import pylab as plt

DayOfWeekOfCall = [1,2,3]
DispatchesOnThisWeekday = [77, 32, 42]

LABELS = ["Monday", "Tuesday", "Wednesday"]

plt.bar(DayOfWeekOfCall, DispatchesOnThisWeekday, align='center')
plt.xticks(DayOfWeekOfCall, LABELS)
plt.show()

enter image description here

74
Hooked

Ne modifiez pas votre code SQL juste pour modifier l'illustration. À la place, faites un petit ajout à votre code Python.

Je crois que vous pouvez faire quelque chose comme cette réponse . Définissez les étiquettes des ticks comme étant les jours de la semaine.

Cela peut être aussi simple que d'ajouter la ligne suivante:

plt.xticks((1, 2, ..., 7), ('Sunday', 'Monday', ..., 'Saturday'))

Documentation: pyplot.xticks

EDIT: Exemple de réponse à un commentaire utilisant une table fictive IncidentTypes qui mappe les clés entières aux noms des types d'incidents.

cursor.execute('select incident_type_id, count(*), incident_type 
    from Incidents join IncidentTypes using (incident_type_id) 
    group by incident_type_id')
results = cursor.fetchall()
tickpositions = [int(r[0]) for r in results]
numincidents = [int(r[1]) for r in results]
ticklabels = [r[2] for r in results]

plt.bar(tickpositions, numincidents)
plt.xticks(tickpositions, ticklabels)
6
Steve Tjoa

Réponse finale terminée qui a résolu le problème: Merci beaucoup Steve. Tu a été d'une aide précieuse. J'ai étudié la géographie à l'université, pas la programmation, donc c'est assez difficile pour moi. Voici le code final qui fonctionne pour moi.

 import pyodbc
    import matplotlib.pyplot as plt
    MySQLQuery = """
    SELECT 
      DATEPART(WEEKDAY, IIU_tDispatch)AS [IntegerOfDayOfWeek]
    , COUNT(DATENAME(WeekDay, IIU_tDispatch)) AS [DispatchesOnThisWeekday]
    , DATENAME(WEEKDAY, IIU_tDispatch)AS [DayOfWeekOfCall]
    FROM IIncidentUnitSummary
    INNER JOIN PUnit ON IIU_kUnit = PUN_Unit_PK
    WHERE PUN_UnitAgency = 'LC'
    AND IIU_tDispatch BETWEEN 'October 1, 2010' AND 'October 1, 2011'
    AND PUN_UnitID LIKE 'M__'
    GROUP BY DATEPART(WEEKDAY, IIU_tDispatch), DATENAME(WEEKDAY, IIU_tDispatch)
    ORDER BY DATEPART(WEEKDAY, IIU_tDispatch)
    """
    cnxn = pyodbc.connect("a bunch of stuff I don't want to share")
    cursor = cnxn.cursor()
    GraphCursor = cnxn.cursor()
    cursor.execute(MySQLQuery)

    results = cursor.fetchall()
    IntegerDayOfWeek, DispatchesOnThisWeekday, DayOfWeekOfCall = Zip(*results)
    tickpositions = [int(r[0]) for r in results]
    numincidents = [int(r[1]) for r in results]
    ticklabels = [r[2] for r in results]
    plt.bar(tickpositions, numincidents)
    plt.xticks(tickpositions, ticklabels)
    #plt.bar(DayOfWeekOfCall, DispatchesOnThisWeekday)
    plt.grid()
    plt.title('Dispatches by Day of Week')
    plt.xlabel('Day of Week')
    plt.ylabel('Number of Dispatches')
    plt.show()

    cursor.close()
    cnxn.close()

Je ne comprends pas vraiment les lignes entre "results = cursor.fetchall ()" et les quatre lignes de code suivantes qui impliquent la création de tableaux. Je suis content que vous le fassiez, car je le regarde et il ne s'enfonce toujours pas. Merci beaucoup. Cela aide beaucoup. David

1
David Kulpanowski