Remrinのpython攻略日記

python3に入門しました。python3についてあれこれとサンプルコードとか。

matplotlibで棒グラフ

matplotlibで棒グラフの描き方
 
Definition :

bar(left,        #それぞれの棒の左端の配列 
    height,      #高さの配列
    width=0.8,   #棒の太さ
    bottom=None, #複数の棒グラフを積み上げるときの土台を示す。
    hold=None,   #
    data=None,   #
    **kwargs)

 
○基本

import matplotlib.pyplot as plt
x = [1, 2, 3]
y = [2, 3, 4]
plt.bar(x, y)

f:id:rare_Remrin:20170428180538p:plain 
 
ちょっと棒が太すぎますね。
太さのデフォルトは0.8なので半分にしてみると
 

import matplotlib.pyplot as plt
x = [1, 2, 3]
y = [2, 3, 4]
plt.bar(x, y, width=0.4)


f:id:rare_Remrin:20170428180906p:plain
スリムになりました。
 
○横棒グラフ

import matplotlib.pyplot as plt
y = [1, 2, 3]
x = [2, 3, 4]
plt.barh(y, x, height=0.4)

f:id:rare_Remrin:20170428183317p:plain
 
他の例も

# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt
import numpy as np

#日本語を使う場合は以下の2行でフォントを準備
from matplotlib.font_manager import FontProperties
fp = FontProperties(fname='C:\WINDOWS\Fonts\msgothic.ttc', size=14)

w = 0.3  #棒の幅
y1 = np.array([80, 90, 60])
y2 = np.array([75, 95, 70])
x = np.arange(len(y1))       #データ数に合わせて横軸を準備

plt.bar(x, y1, width=w, label='第1回', align="center")
plt.bar(x + w, y2, width=w, label='第2回', align="center")
plt.legend(loc="best", prop=fp)    #凡例を表示 日本語を使う場合はprop=fp

# X軸の目盛りを科目名にする 日本語を使う場合はfontproperties=fp
plt.xticks(x + w/2, ['英語','数学','国語'], fontproperties=fp)
plt.show()

f:id:rare_Remrin:20170428150017p:plain
 
2つめのオレンジの棒グラフにbottom=y1のオプションを追加すると

# X軸の目盛りを科目名にする 日本語を使う場合はfontproperties=fp
plt.xticks(x + w/2, ['英語','数学','国語'], fontproperties=fp)
plt.show()

plt.bar(x, y1, width=w, label='第1回', align="center")
plt.bar(x + w, y2, width=w, bottom=y1, label='第2回', align="center")
plt.legend(loc="best", prop=fp)    #凡例を表示 日本語を使う場合はprop=fp

# X軸の目盛りを科目名にする 日本語を使う場合はfontproperties=fp
plt.xticks(x + w/2, ['英語','数学','国語'], fontproperties=fp)
plt.show()

f:id:rare_Remrin:20170428181919p:plain
 
何か浮いてる。
オレンジのグラフを青に重なるようにx座標をそろえて、青も右へ棒の幅の半分ほどずらします。

plt.xticks(x + w/2, ['英語','数学','国語'], fontproperties=fp)
plt.show()

plt.bar(x + w /2, y1, width=w, label='第1回', align="center")
plt.bar(x + w /2, y2, width=w, bottom=y1, label='第2回', align="center")
plt.legend(loc="best", prop=fp)    #凡例を表示 日本語を使う場合はprop=fp

# X軸の目盛りを科目名にする 日本語を使う場合はfontproperties=fp
plt.xticks(x + w/2, ['英語','数学','国語'], fontproperties=fp)
plt.show()

f:id:rare_Remrin:20170428182310p:plain
 
別の例

# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.font_manager import FontProperties
fp = FontProperties(fname=r'C:\WINDOWS\Fonts\msgothic.ttc', size=14)

#         県名   面積  人口
data = [("栃木", 6408, 197),
        ("茨城", 6096, 292),
        ("群馬", 6362, 197),
        ("埼玉", 3797, 727),
        ("千葉", 5157, 622),
        ("東京", 2190, 1352),
        ("神奈川", 2415, 913)]

#dataを種類ごとに分解
x, xlabel, y1, y2 = [], [], [] ,[]
for i in range(len(data)):
    x.append(i)
    xlabel.append(data[i][0])
    y1.append(data[i][1])
    y2.append(data[i][2])
#2つめの棒グラフ(人口)の横軸をブロードキャストでずらすためにarrayに変換    
x = np.array(x)  

w = 0.4
#1つめの棒グラフ(面積)
plt.bar(x, y1, width=w, label='面積(km2)', align="center")
plt.xticks(x + w/2, xlabel, fontproperties=fp)  #x軸に県名

#2つめのグラフ(人口)
plt.bar(x + w, y2, width=w, color="orange", label='人口(万人)', align="center")
plt.legend(loc="upper right", prop=fp)
plt.show()    

f:id:rare_Remrin:20170428164938p:plain
 
面積の目盛りを左側、人口の目盛りを右側にするために、subplotsを使う。
ただし、subplotsを使うと
 ・グラフの色がリセットされる → 色を自分で設定する。
 ・凡例が重なって表示される  → グラフごとに重ならないように設定。
   bbox_to_anchor=(x, y)の形で表す。
 

#縦軸を左右に表示するため、subplotsを使う            
_, ax1 = plt.subplots()
#1つめの棒グラフ(面積)
ax1.bar(x, y1, width=w, label='面積(km2)', align="center")
#凡例を枠外に表示するにはbbox_to_anchor(x, y)を使う
plt.legend(bbox_to_anchor=(0, 1.2), loc="upper left", prop=fp)
plt.xticks(x + w/2, xlabel, fontproperties=fp)

#2つめのグラフ(人口)
ax2 = ax1.twinx()
ax2.bar(x + w, y2, width=w, color="orange", label='人口(万人)', align="center")
plt.legend(bbox_to_anchor=(1, 1.2), prop=fp)

plt.show()

 
f:id:rare_Remrin:20170428175907p:plain
 
百人一首のひらがなをカウントする

# -*- coding: utf-8 -*-

from collections import Counter
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib.font_manager import FontProperties
fp = FontProperties(fname=r'C:\WINDOWS\Fonts\msgothic.ttc', size=14)

# 百人一首のデータ読み込み
url = 'http://python-remrin.hatenadiary.jp/entry/2017/04/23/000000'
fetched = pd.io.html.read_html(url) # DataFrameのリスト

d = fetched[0]                      # そのデータフレームをdに代入
l = list(d[1])                      # 1の列を抽出してリスト化
text = "".join(l).replace(" ", "")  # 句間のスペースを除去
c = Counter(text)                   # ひらがなの頻度をカウント

# TOP20のグラフ           
x = range(20)
mc = c.most_common(20)              # 頻度TOP20を抽出
ch = [ch[0] for ch in mc]           # ひらがなのリスト
f = np.array([ch[1] for ch in mc])  # 頻度の数値のリスト

plt.bar(x, f) 
plt.xticks(x, ch, fontproperties=fp)  #日本語表示はfontproperties=fp
plt.title("百人一首のひらがな頻度 TOP20", fontproperties=fp)
plt.show()

#Last20のグラフ
least = c.most_common()[-21:-1] #Counterから末尾20個を抽出
ch = [ch[0] for ch in least]
f = np.array([ch[1] for ch in least])

plt.bar(x, f) 
plt.xticks(x, ch, fontproperties=fp)  #日本語表示はfontproperties=fp
plt.title("百人一首のひらがな頻度 Last20", fontproperties=fp)
plt.show()

 
f:id:rare_Remrin:20170504134729p:plain 
f:id:rare_Remrin:20170504134739p:plain 
 
縦軸の目盛りがそろってないので、Last20のひらがなの方が頻度が多いような錯覚に。
plt.ylim(0, 220)を追加して、縦軸の表示範囲をそろえると

#Last20のグラフ
least = c.most_common()[-21:-1] #Counterから末尾20個を抽出
ch = [ch[0] for ch in least]
f = np.array([ch[1] for ch in least])

plt.bar(x, f) 
plt.xticks(x, ch, fontproperties=fp)  #日本語表示はfontproperties=fp
plt.title("百人一首のひらがな頻度 Last20", fontproperties=fp)
plt.ylim(0, 220)  # 縦軸の範囲を設定
plt.show()

 
f:id:rare_Remrin:20170504135441p:plain
 
・上位と下位をあわせて表示

# -*- coding: utf-8 -*-

from collections import Counter
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib.font_manager import FontProperties
fp = FontProperties(fname=r'C:\WINDOWS\Fonts\msgothic.ttc', size=14)

url = 'http://python-remrin.hatenadiary.jp/entry/2017/04/23/000000'
fetched = pd.io.html.read_html(url) # DataFrameのリスト

d = fetched[0]                      # そのデータフレームをdに代入
l = list(d[1])                      # 1の列を抽出してリスト化
text = "".join(l).replace(" ", "")  # 句間のスペースを除去
c = Counter(text)                   # ひらがなの頻度をカウント
Top, Last = 20, 6                   # 上位と下位の表示数をセット  
           
# 上位のグラフ           
x = range(Top)
mc = c.most_common(Top)             # 頻度TOP20を抽出
ch = [ch[0] for ch in mc]           # ひらがなのリスト
f = np.array([ch[1] for ch in mc])  # 頻度の数値のリスト
plt.bar(x, f, color="green")

# 下位のグラフ
least = c.most_common()[-(Last+1):-1] #Counterから末尾を抽出
ch2 = [ch[0] for ch in least]
f2 = np.array([ch[1] for ch in least])
x2 = range(Top + 2, Top + 2 + Last)
plt.bar(x2, f2, color="gray") 

#横軸の目盛り
xtick = ch + [" ", " "] + ch2
plt.xticks(range(Top + 2 + Last), xtick, fontproperties=fp)

plt.title("百人一首のひらがな頻度", fontproperties=fp)         
plt.show()

 
f:id:rare_Remrin:20170504142404p:plain
 
参考サイト:
Symfoware
サイエンティストとマーケターのはざま