今回は、Pythonで散布図を描こうと思います。
内容的には「Pythonでヒストグラム」の続編のような形になっていますのでご注意を。
相関係数を求める
シチュエーションとしては、ExcelのセルF10から下にデータ(テストの点数)がずらっと並んでいて、それと対になるデータ(エラー度合いの合計)が隣り合ったセルG10から下に同じく並んでいるものとします。
まずは、xlrd を使ってExcelから対象のデータを抜き出し、相関係数を求めてみます。
相関係数は、Numpy の corrcoef() を使って求めます。
test_corrcoef.py
#! /usr/bin/env python # -*- coding: utf-8 -*- import numpy import xlrd def get_data(sheet, rowx, colx): data = [] for row in range(rowx, sheet.nrows): value = sheet.cell(row, colx).value if value != '': data.append(value) data = numpy.array(data) return data if __name__ == '__main__': book = xlrd.open_workbook('/Users/akiyoko/Documents/temp/2nd_test.xls') sheet = book.sheet_by_name('Statistics (total score)') data1 = get_data(sheet, 9, 5) # データの起点はF10 data2 = get_data(sheet, 9, 6) # データの起点はG10 print 'data1=%s' % data1 print 'size of data 1=%d' % len(data1) print 'mean value of data 1=%.1f' % numpy.mean(data1) print 'data2=%s' % data2 print 'size of data 2=%d' % len(data2) print 'mean value of data 2=%.0f' % numpy.mean(data2) # 相関係数 print 'coefficient of correlation=%.2f' % numpy.corrcoef(data1, data2)[0, 1]
numpy.corrcoef(x, y)[0, 1] は、numpy.corrcoef(x, y)[0][1] と書いてもいいようです(Pythonネイティブの配列だとエラーになります)。
実行結果
$ python test_corrcoef.py data1=[ 42. 42. 40. 38. 38. 38. 38. 35. 35. 35. 35. 34. 34. 34. 34. 33. 33. 33. 33. 32. 32. 32. 30. 30. 30. 30. 30. 30. 30. 30. 29. 29. 29. 28. 28. 28. 28. 28. 27. 27. 27. 27. 27. 27. 26. 26. 26. 26. 26. 26. 25. 24. 24. 24. 24. 23. 23. 23. 23. 23. 23. 23. 23. 23. 22. 22. 22. 22. 22. 22. 22. 22. 21. 21. 20. 20. 20. 20. 20. 19. 19. 19. 19. 19. 18. 18. 17. 17. 16. 16. 16. 16. 15. 15. 15. 15. 14. 13. 13. 13. 13. 12. 12. 11. 9.] size of data 1=105 mean value of data 1=24.9 data2=[ 576. 668. 682. 795. 814. 1046. 1414. 1084. 1107. 1196. 1533. 1205. 1327. 1427. 1434. 1575. 1578. 1683. 1772. 1522. 1585. 1665. 1542. 1642. 1677. 1795. 1813. 1824. 1865. 1980. 1483. 1830. 2257. 1763. 2120. 2207. 2712. 2828. 1793. 1846. 1959. 2049. 2124. 2677. 2223. 2236. 2511. 2910. 3028. 3371. 2528. 2196. 2274. 2469. 2539. 2155. 2158. 2474. 2601. 2733. 2793. 2863. 3398. 3585. 1984. 2413. 2574. 2752. 2892. 3212. 3318. 3794. 2839. 3406. 2435. 2571. 3011. 3133. 3265. 2506. 2931. 2983. 3455. 3609. 2895. 3586. 3722. 3846. 2883. 2937. 3213. 3456. 3161. 3623. 3888. 4035. 4400. 4051. 4364. 4533. 4825. 4063. 4289. 3762. 4453.] size of data 2=105 mean value of data 2=2510 coefficient of correlation=-0.92
相関係数は「-0.92」と求めることができました。
散布図描画
散布図を描画するには Axesクラスの scatter() を使うのですが、これまたパラメータが煩雑。実際に使いながら理解していくしかありません。
自分なりにまとめると、こんな感じです。
scatter(x, y, s=20, c='b', marker='o', cmap=None, norm=None, vmin=None, vmax=None, alpha=None, linewidths=None, verts=None, **kwargs) x: データ1 y: データ2 s: プロットのサイズ c: プロットの色(注1) marker: マーカーの形(注2) 注1. cで色を指定するだけだと枠線がデフォルト色で描画されてしまう。 colorだと、内側の塗りと枠線を一緒に指定できる。 なお、内側の塗りと枠線の色を分けたい場合は、cやcolorを使わず、facecolor='r', edgecolor='r' などとすればよい。 注2. マーカーの形は以下が使い勝手がよさそうだった。
'o' | circle |
'x' | x |
'D' | diamond |
'+' | plus |
'v' | triangle_down |
'<' | triangle_left |
'>' | triangle_right |
'^' | triangle_up |
サンプル
実際に作ったサンプルコードです。
test_scatter.py
#! /usr/bin/env python # -*- coding: utf-8 -*- import numpy import xlrd import matplotlib.mlab as mlab import matplotlib.pyplot as plt def get_data(sheet, rowx, colx): data = [] for row in range(rowx, sheet.nrows): value = sheet.cell(row, colx).value if value != '': data.append(value) data = numpy.array(data) return data if __name__ == '__main__': book = xlrd.open_workbook('/Users/akiyoko/Documents/temp/2nd_test.xls') sheet = book.sheet_by_name('Statistics (total score)') data1 = get_data(sheet, 9, 5) # データの起点はF10 data2 = get_data(sheet, 9, 6) # データの起点はG10 print 'data1=%s' % data1 print 'size of data 1=%d' % len(data1) print 'mean value of data 1=%.1f' % numpy.mean(data1) print 'data2=%s' % data2 print 'size of data 2=%d' % len(data2) print 'mean value of data 2=%.0f' % numpy.mean(data2) # 相関係数 r = numpy.corrcoef(data1, data2)[0, 1] print 'coefficient of correlation=%.2f' % r # 共通初期設定 plt.rc('font', **{'family': 'serif'}) # キャンバス fig = plt.figure() # プロット領域(1x1分割の1番目に領域を配置せよという意味) ax = fig.add_subplot(111) # 散布図 sc = ax.scatter(data1, data2, s=25, marker='x', color='b') # X, Y方向の表示範囲 ax.set_xlim(0, 50) ax.set_ylim(0, 6000) # タイトル ax.set_title('Scatter Graph: r=%.2f' % r, size=16) ax.set_xlabel('Score', size=14) ax.set_ylabel('Error Severity', size=14) # 凡例 ax.legend((sc,), ('2nd Test',), scatterpoints=1, loc='upper left', fontsize=10) # グリッド表示 ax.grid(True) plt.show()
実行結果
$ python test_scatter.py data1=[ 42. 42. 40. 38. 38. 38. 38. 35. 35. 35. 35. 34. 34. 34. 34. 33. 33. 33. 33. 32. 32. 32. 30. 30. 30. 30. 30. 30. 30. 30. 29. 29. 29. 28. 28. 28. 28. 28. 27. 27. 27. 27. 27. 27. 26. 26. 26. 26. 26. 26. 25. 24. 24. 24. 24. 23. 23. 23. 23. 23. 23. 23. 23. 23. 22. 22. 22. 22. 22. 22. 22. 22. 21. 21. 20. 20. 20. 20. 20. 19. 19. 19. 19. 19. 18. 18. 17. 17. 16. 16. 16. 16. 15. 15. 15. 15. 14. 13. 13. 13. 13. 12. 12. 11. 9.] size of data 1=105 mean value of data 1=24.9 data2=[ 576. 668. 682. 795. 814. 1046. 1414. 1084. 1107. 1196. 1533. 1205. 1327. 1427. 1434. 1575. 1578. 1683. 1772. 1522. 1585. 1665. 1542. 1642. 1677. 1795. 1813. 1824. 1865. 1980. 1483. 1830. 2257. 1763. 2120. 2207. 2712. 2828. 1793. 1846. 1959. 2049. 2124. 2677. 2223. 2236. 2511. 2910. 3028. 3371. 2528. 2196. 2274. 2469. 2539. 2155. 2158. 2474. 2601. 2733. 2793. 2863. 3398. 3585. 1984. 2413. 2574. 2752. 2892. 3212. 3318. 3794. 2839. 3406. 2435. 2571. 3011. 3133. 3265. 2506. 2931. 2983. 3455. 3609. 2895. 3586. 3722. 3846. 2883. 2937. 3213. 3456. 3161. 3623. 3888. 4035. 4400. 4051. 4364. 4533. 4825. 4063. 4289. 3762. 4453.] size of data 2=105 mean value of data 2=2510 coefficient of correlation=-0.92
こんな感じでグラフが出力されます。