matplotlib-円グラフの作成メモ

目次

円グラフの作成

目的

機械学習やビッグデータの解析では,大量にある多次元データを様々な側面から見る必要がある.ここでは,matplotlibを用いた円グラフの作成方法を学ぶ.

説明

円グラフの描画

まずは簡単な円グラフを描画してみよう.

from numpy.random import default_rng
import matplotlib.pyplot as plt
def main():
    rg = default_rng(seed=0)
    students_count = 280
    scores = rg.normal(65.9, 10.8, students_count)
    s_count = (90 <= scores).sum()
    a_count = ((80 <= scores) & (scores < 90)).sum()
    b_count = ((70 <= scores) & (scores < 80)).sum()
    c_count = ((60 <= scores) & (scores < 70)).sum()
    d_count = ((50 <= scores) & (scores < 60)).sum()
    e_count = (scores < 50).sum()
    fig = plt.figure(figsize=plt.figaspect(1.0))
    ax = fig.add_subplot()
    ax.pie([s_count, a_count, b_count, c_count, d_count, e_count])
    plt.show()
if __name__ == '__main__':
    main()

6行目から8行目で,280名の学生のある科目のテストの点数からなる配列を作っている.10行目で90点以上の点数をとった学生数を,11行目で80点以上90点未満の点数をとった学生数を求めている.以下同様に,12行目から15行目までで,各範囲の点数をとった学生数を求めている.19行目のように,axオブジェクトのpieメソッドを,円グラフとして表したい数からなるリストを引数として呼び出すと,円グラフを作成することができる.

凡例・タイトルの表示

円グラフに凡例とタイトルを指定するには,以下のようにすればよい.

from numpy.random import default_rng
import matplotlib.pyplot as plt
def main():
    rg = default_rng(seed=0)
    students_count = 280
    scores = rg.normal(65.9, 10.8, students_count)
    labels = ['S', 'A', 'B', 'C', 'D', 'E']
    s_count = (90 <= scores).sum()
    a_count = ((80 <= scores) & (scores < 90)).sum()
    b_count = ((70 <= scores) & (scores < 80)).sum()
    c_count = ((60 <= scores) & (scores < 70)).sum()
    d_count = ((50 <= scores) & (scores < 60)).sum()
    e_count = (scores < 50).sum()
    fig = plt.figure(figsize=plt.figaspect(1.0))
    ax = fig.add_subplot()
    ax.pie([s_count, a_count, b_count, c_count, d_count, e_count])
    ax.legend(labels, loc='best')
    ax.set_title('Fig.1: Student grades.')
    plt.show()
if __name__ == '__main__':
    main()

10行目で凡例として表示する文字列からなるリストを作成し,21行目のように,axオブジェクトのlegendメソッドを,作成したリストを引数として呼び出すと,円グラフに凡例をつけることができる.また,タイトルの指定の仕方はこれまでと同様である.

開始位置と描画方向の指定

上の実行結果からわかるように,この円グラフは3時の位置から開始し,半時計回りに描画されている.これを12時の位置から開始し,時計回りに描画するには,以下のようにすればよい.

from numpy.random import default_rng
import matplotlib.pyplot as plt
def main():
    rg = default_rng(seed=0)
    students_count = 280
    scores = rg.normal(65.9, 10.8, students_count)
    labels = ['S', 'A', 'B', 'C', 'D', 'E']
    s_count = (90 <= scores).sum()
    a_count = ((80 <= scores) & (scores < 90)).sum()
    b_count = ((70 <= scores) & (scores < 80)).sum()
    c_count = ((60 <= scores) & (scores < 70)).sum()
    d_count = ((50 <= scores) & (scores < 60)).sum()
    e_count = (scores < 50).sum()
    fig = plt.figure(figsize=plt.figaspect(1.0))
    ax = fig.add_subplot()
    ax.pie([s_count, a_count, b_count, c_count, d_count, e_count], startangle=90, counterclock=False)
    ax.legend(labels, loc='best')
    ax.set_title('Fig.1: Student grades.')
    plt.show()
if __name__ == '__main__':
    main()

20行目のように,pieメソッドのキーワード引数startangleに90度と指定すると,デフォルトの開始位置から半時計回り(デフォルトの描画方向)に90度の位置から描画を開始できる.また,キーワード引数counterclockにFalseを指定すると,時計回りに描画することができる.

ラベルの指定

凡例としてではなく,円グラフの周囲にラベルを表示するには,pieメソッドのキーワード引数labelsを使用すればよい.

from numpy.random import default_rng
import matplotlib.pyplot as plt
def main():
    rg = default_rng(seed=0)
    students_count = 280
    scores = rg.normal(65.9, 10.8, students_count)
    labels = ['S', 'A', 'B', 'C', 'D', 'E']
    s_count = (90 <= scores).sum()
    a_count = ((80 <= scores) & (scores < 90)).sum()
    b_count = ((70 <= scores) & (scores < 80)).sum()
    c_count = ((60 <= scores) & (scores < 70)).sum()
    d_count = ((50 <= scores) & (scores < 60)).sum()
    e_count = (scores < 50).sum()
    fig = plt.figure(figsize=plt.figaspect(1.0))
    ax = fig.add_subplot()
    ax.pie([s_count, a_count, b_count, c_count, d_count, e_count], labels=labels, startangle=90, counterclock=False)
    ax.set_title('Fig.1: Student grades.')
    plt.show()
if __name__ == '__main__':
    main()

各データの割合をパーセント表示

各データの割合をパーセント表示することができる.

from numpy.random import default_rng
import matplotlib.pyplot as plt
def main():
    rg = default_rng(seed=0)
    students_count = 280
    scores = rg.normal(65.9, 10.8, students_count)
    labels = ['S', 'A', 'B', 'C', 'D', 'E']
    s_count = (90 <= scores).sum()
    a_count = ((80 <= scores) & (scores < 90)).sum()
    b_count = ((70 <= scores) & (scores < 80)).sum()
    c_count = ((60 <= scores) & (scores < 70)).sum()
    d_count = ((50 <= scores) & (scores < 60)).sum()
    e_count = (scores < 50).sum()
    fig = plt.figure(figsize=plt.figaspect(1.0))
    ax = fig.add_subplot()
    ax.pie([s_count, a_count, b_count, c_count, d_count, e_count], autopct='%.1f%%', startangle=90, counterclock=False)
    ax.legend(labels, loc='best')
    ax.set_title('Fig.1: Student grades.')
    plt.show()
if __name__ == '__main__':
    main()

20行目のように,pieメソッドのキーワード引数autopctに’%.1f%%’と指定すると,小数点以下1桁までの浮動小数点数として各データの割合をパーセント表示することができる.記述のルールはf文字列のフォーマット指定と同じである.

この例では,パーセント表示の一部が重複してしまっている.表示位置を変更するには,以下のようにすればよい.

from numpy.random import default_rng
import matplotlib.pyplot as plt
def main():
    rg = default_rng(seed=0)
    students_count = 280
    scores = rg.normal(65.9, 10.8, students_count)
    labels = ['S', 'A', 'B', 'C', 'D', 'E']
    s_count = (90 <= scores).sum()
    a_count = ((80 <= scores) & (scores < 90)).sum()
    b_count = ((70 <= scores) & (scores < 80)).sum()
    c_count = ((60 <= scores) & (scores < 70)).sum()
    d_count = ((50 <= scores) & (scores < 60)).sum()
    e_count = (scores < 50).sum()
    fig = plt.figure(figsize=plt.figaspect(1.0))
    ax = fig.add_subplot()
    ax.pie([s_count, a_count, b_count, c_count, d_count, e_count], autopct='%1.1f%%', pctdistance=1.1, startangle=90, counterclock=False)
    ax.legend(labels, loc='lower right')
    ax.set_title('Fig.1: Student grades.')
    plt.show()
if __name__ == '__main__':
    main()

20行目のように,pieメソッドのキーワード引数pctdistanceに数値を指定することで,パーセント表示の位置を変更できる.0が円の中心を1が円周を表しており,20行目のように1.1と指定することで,円の少し外側に表示位置を変更している.

各領域の色の指定

円グラフの各領域の色を指定するには,以下のようにすればよい.

from numpy.random import default_rng
import matplotlib.pyplot as plt
def main():
    rg = default_rng(seed=0)
    students_count = 280
    scores = rg.normal(65.9, 10.8, students_count)
    labels = ['S', 'A', 'B', 'C', 'D', 'E']
    colors = ['red', 'green', 'blue', 'cyan', 'magenta', 'yellow']
    s_count = (90 <= scores).sum()
    a_count = ((80 <= scores) & (scores < 90)).sum()
    b_count = ((70 <= scores) & (scores < 80)).sum()
    c_count = ((60 <= scores) & (scores < 70)).sum()
    d_count = ((50 <= scores) & (scores < 60)).sum()
    e_count = (scores < 50).sum()
    fig = plt.figure(figsize=plt.figaspect(1.0))
    ax = fig.add_subplot()
    ax.pie([s_count, a_count, b_count, c_count, d_count, e_count], colors=colors, autopct='%1.1f%%', pctdistance=1.1, startangle=90, counterclock=False)
    ax.legend(labels, loc='lower right')
    ax.set_title('Fig.1: Student grades.')
    plt.show()
if __name__ == '__main__':
    main()

11行目で各領域の色を表す文字列からなるリストを作成し,21行目のpieメソッドのキーワード引数colorsで色のリストを指定している.

各領域の輝度の指定

円グラフをグレースケールとして作成したい場合には,以下のようにすればよい.

from numpy.random import default_rng
import matplotlib.pyplot as plt
def main():
    rg = default_rng(seed=0)
    students_count = 280
    scores = rg.normal(65.9, 10.8, students_count)
    labels = ['S', 'A', 'B', 'C', 'D', 'E']
    brightness = ['0.15', '0.3', '0.45', '0.6', '0.75', '0.9']
    s_count = (90 <= scores).sum()
    a_count = ((80 <= scores) & (scores < 90)).sum()
    b_count = ((70 <= scores) & (scores < 80)).sum()
    c_count = ((60 <= scores) & (scores < 70)).sum()
    d_count = ((50 <= scores) & (scores < 60)).sum()
    e_count = (scores < 50).sum()
    fig = plt.figure(figsize=plt.figaspect(1.0))
    ax = fig.add_subplot()
    ax.pie([s_count, a_count, b_count, c_count, d_count, e_count], colors=brightness, autopct='%1.1f%%', pctdistance=1.1, startangle=90, counterclock=False)
    ax.legend(labels, loc='lower right')
    ax.set_title('Fig.1: Student grades.')
    plt.show()
if __name__ == '__main__':
    main()

11行目で各領域の輝度を表す文字列からなるリストを作成している.0が最も暗く,1が最も明るい画素を表している.21行目のように,pieメソッドのキーワード引数colorsで輝度のリストを指定することで,グレースケールの円グラフを作成できる.

各領域の境界線の指定

円グラフの各領域の境界線を表示するには,以下のようにすればよい.

from numpy.random import default_rng
import matplotlib.pyplot as plt
def main():
    rg = default_rng(seed=0)
    students_count = 280
    scores = rg.normal(65.9, 10.8, students_count)
    labels = ['S', 'A', 'B', 'C', 'D', 'E']
    brightness = ['0.15', '0.3', '0.45', '0.6', '0.75', '0.9']
    s_count = (90 <= scores).sum()
    a_count = ((80 <= scores) & (scores < 90)).sum()
    b_count = ((70 <= scores) & (scores < 80)).sum()
    c_count = ((60 <= scores) & (scores < 70)).sum()
    d_count = ((50 <= scores) & (scores < 60)).sum()
    e_count = (scores < 50).sum()
    fig = plt.figure(figsize=plt.figaspect(1.0))
    ax = fig.add_subplot()
    ax.pie([s_count, a_count, b_count, c_count, d_count, e_count], wedgeprops={'linewidth': 1, 'edgecolor': 'black'}, colors=brightness, autopct='%1.1f%%', pctdistance=1.1, startangle=90, counterclock=False)
    ax.legend(labels, loc='lower right')
    ax.set_title('Fig.1: Student grades.')
    plt.show()
if __name__ == '__main__':
    main()

21行目のように,pieメソッドのキーワード引数wedgepropsに辞書として境界線の太さと色を指定することができる.辞書のキーlinewidthが線の太さを,キーedgecolorが線の色を表している.

参考サイト

http://makotomurakami.com/blog/2020/04/03/4614/


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS