『改訂第3版 基礎からわかる情報リテラシー』第13章のPython版

『改訂第3版 基礎からわかる情報リテラシー』第13章「Rによるデータ処理」をPythonに焼き直したものです。

Pythonのインストール・実行についてはお品書きをご覧ください。

グラフの描画

ライブラリ matplotlibnumpy を使っています。

2次関数 $y = x^2$ のグラフを $-3 \leqq x \leqq 3$ の範囲で描きます(Jupyter Notebook では %matplotlib inline という行を最初に追加してください)

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-3, 3, 101)
plt.plot(x, x ** 2)

プロットが現れない場合は plt.show() という行を最後に追加してください。その場合は,プロット窓を閉じないと次に進めなくなります。これは以下でも同じです。

x = np.linspace(-3, 3, 101) は区間 $-3 \leqq x \leqq 3$ を100等分する101個の x を計算します。101 という値に特に意味はありませんが,あまり小さすぎると滑らかに表示されません。

縦横比を 1 にするには plt.plot(x, x ** 2) の後に plt.axis('scaled') または plt.axis('equal') という行を追加してください。

2次関数 $y = x^3 - x$ のグラフを $x$ 軸($y = 0$ の線)とともに $-1.2 \leqq x \leqq 1.2$ の範囲で描きます(IPython などの対話型環境では,まず plt.clf() と打ち込んで,前のグラフをクリアしてください):

x = np.linspace(-1.2, 1.2, 101)
plt.plot(x, x ** 3 - x)
plt.axhline()

データファイルの読み方

ライブラリ pandas, xlrd を使っています。

import pandas as pd

birthdeath = pd.read_excel("https://okumuralab.org/literacy3/birthdeath.xlsx")
birthdeath.head()

データのグラフ化

plt.plot(birthdeath['年'], birthdeath['出生数'], 'o-')
plt.plot(birthdeath['年'], birthdeath['死亡数'], 'o-')

CSVファイルの読み込みと直線のあてはめ

気象庁のデータを読み込んでプロットします:

df = pd.read_csv('http://www.data.jma.go.jp/cpdinfo/temp/list/csv/an_wld.csv',
                 encoding='sjis')
plt.plot(df['年'], df['世界全体'], 'o-')

直線をあてはめます。

slope, intercept = np.polyfit(df['年'], df['世界全体'], 1)
print("傾き", slope, "y切片", intercept)

前のプロットに続けて次のように打ち込むと,予測直線が重ね書きされます(Jupyter Notebookでは上の plt.plot(df['年'], df['世界全体'], 'o-') と同じセルの最後に付け加えてください):

plt.plot(df['年'], df['年'] * slope + intercept)

別のやり方として,機械学習でよく用いられるライブラリ scikit-learn を使う方法も書いておきます。

from sklearn.linear_model import LinearRegression

x = np.array(df['年']).reshape(-1,1)
y = np.array(df['世界全体'])
model = LinearRegression()
model.fit(x, y)
print("傾き", model.coef_, "y切片", model.intercept_)
plt.plot(x, model.predict(x))

ほかに,Rのような統計寄りのライブラリ statsmodels も使えます。

データの集計

学生のデータを読み込み,学部ごとに集計して棒グラフを描きます(Google Colaboratory など日本語フォントが設定されていない環境では文字化けしますが無視するか,あるいはプロットの項を見て環境設定してください):

students = pd.read_csv("https://okumuralab.org/literacy3/students.csv")
s = students.groupby('学部')['学生数'].sum()
plt.bar(s.index, s)

学年ごとに集計するには,上の「学部」を「学年」に変えます。

多数のファイルの集計

以下はそのまま打ち込んでも実行できません。実際に集計したいExcelファイル群が存在するディレクトリを指定して実行してください。

まずディレクトリ名(ここではカレントディレクトリ ".")を与えてファイル名一覧を取得します(Excel で開いているとファイル名の頭に ~$ の付いたテンポラリファイル名を拾ってしまうことがあるので要注意):

import pathlib

path = pathlib.Path(".")
names = [p for p in path.iterdir() if p.match("*.xlsx")]

ファイル名を与えると,ワークブックを開いて,最初のワークシートのセル B2,B3,B4,C2,C3,C4 の中身をリストとして返す関数を定義します。

def f(n):
    a = pd.read_excel(n, usecols="B:C", header=None, skiprows=1, nrows=3)
    return a.values.flatten("F")

縦横に並んだセルを1列に並べる flatten() を使っています。デフォルトでは B2,C2,B3,C3,B4,C4 の順に並びますが,"F" を与えると,縦読み(Fortran流)の B2,B3,B4,C2,C3,C4 の順になります。これを次々に呼び出して,リストのリストを作ります。

x = [f(n) for n in names]

CSV形式で保存します。

pd.DataFrame(x).to_csv("x.csv", index=False, header=False, encoding="sjis")

openpyxl ライブラリを直接使えばもっと細かいこともできます(この例ではたいして変わりませんが Excel と同じ形でセル範囲が書けます):

from openpyxl import load_workbook

def f(n):
    wb = load_workbook(n, read_only=True)
    ws = wb.worksheets[0]
    return [ws['B2:C4'][i][j].value for j in range(2) for i in range(3)]
# あるいは return [x.value for x in np.array(ws['B2:C4']).flatten("F")]

Last modified: