web-dev-qa-db-ja.com

Matplotlib棒グラフx軸は文字列値をプロットしません

私の名前はデビッドで、フロリダの救急車に勤めています。

私はPython 2.7とmatplotlibを使用しています。救急車の呼び出しのデータベースにアクセスして、各曜日に発生する呼び出しの数をカウントしようとしています。

次に、matplotlibを使用してこの情報の棒グラフを作成し、救急隊員に毎日の忙しさを視覚的に示します。

こちらIS非常にうまく機能するコード:

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()

上記のコードは非常にうまく機能します。見栄えの良いグラフが返され、嬉しいです。私はただ一つの変更をしたいだけです。

「日曜日」などの曜日の名前を示すX軸の代わりに、整数を示します。つまり、日曜日は1、月曜日は2などです。

これに対する私の修正は、DATEPART()の代わりにDATENAME()を使用するようにSQLクエリを書き換えることです。以下に示すのは、(整数ではなく)週の名前を返すSQLコードです。

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)

pythonコードの他のすべては同じままです。ただし、これは機能せず、エラーメッセージを理解できません。

エラーメッセージは次のとおりです。

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

私はこれを理解できません。

要約すると、曜日を表す整数としてx軸を使用してデータを出力し、救急車事故の数のカウントを示すy軸を使用して、MatplotlibはNiceグラフを生成します。しかし、データ出力がx軸の場合、文字列(日曜日、月曜日など)になります。 Matplotlibは機能しません。

Googleで数時間調査し、matplotlibのドキュメントを読みました。これで私を助けてください。レポートエンジンとしてMatplotlibを使用したいと考えています。

33

あなたの質問はSQLクエリとは何の関係もありません。それは単に終了するための手段です。あなたが本当に求めているのは、pylabの棒グラフのテキストラベルを変更する方法です。 棒グラフ のドキュメントはカスタマイズに役立ちますが、単純に ラベルを変更する は最小限の作業例(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

図を変更するためだけにSQLコードを変更しないでください。代わりに、Pythonコードに少し追加してください。

この答え のようなことができると信じています。目盛りラベルを曜日に設定します。

次の行を追加するだけで簡単になります。

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

ドキュメント:pyplot.xticks

編集:整数キーをインシデントタイプの名前にマッピングする架空のテーブルIncidentTypesを使用したコメントへの応答の例.

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

問題を解決した最終回答:スティーブ、ありがとうございました。とても助かりました。私はプログラミングではなく大学で地理を学んだので、これは非常に難しいです。これが私に役立つ最終的なコードです。

 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()

「results = cursor.fetchall()」と、配列の作成に関係する次の4行のコードとの間の行を本当に理解していません。私はそれを見て、それがまだ沈まないので、あなたがしてくれてうれしいです。ありがとうございます。これは非常に役立ちます。デビッド

1