これは数年前に赤石雅典先生の著書『最短コースでわかる Pythonプログラミングとデータ分析』を読んだ際に取ったメモの一部です。皆さんの参考になれば幸いです。
参考として、次の記事も参照してください。
ライブラリの利用 (import文)
-
import文でライブラリを読み込み、その機能を利用できるようにする。
# 標準ライブラリmathをインポート
import math
# math.sqrt の形で関数を呼び出す
r2 = math.sqrt(2)
print(r2) # 1.4142135623730951
-
from ... import ...で特定の関数だけをインポートし、ライブラリ名なしで呼び出す。
from math import sqrt
# ライブラリ名なしで直接呼び出せる
r2 = sqrt(2)
print(r2)
-
import ... as ...で別名(エイリアス)を定義して利用する。
# numpyをnpという別名で利用する
import numpy as np
# np.xxx の形で関数を呼び出す
x = np.linspace(0, 2, 11)
print(x)
y = np.sqrt(x)
print(y)
-
__version__属性でライブラリのバージョンを確認する。
import numpy
print(numpy.__version__)
関数呼び出しとメソッド呼び出しの違い
- 関数呼び出し:ライブラリ名(または別名)をドットで繋いで呼び出す。引数にデータを渡す。
import numpy as np
# np.array は関数呼び出し(npはimportで定義)
n1 = np.array([1, 7, 5, 2])
print(n1)
- メソッド呼び出し:変数(オブジェクト)にドットで繋いで呼び出す。変数自体がデータの所有者。
# s1.upper() はメソッド呼び出し(s1は代入文で定義)
s1 = 'I like an apple.'
print(s1.upper()) # I LIKE AN APPLE.
!pipコマンドによるライブラリのインストール
- Notebook上で
!pip installを使って外部ライブラリを導入する。
# matplotlib日本語化ライブラリの導入
!pip install japanize-matplotlib | tail -n 1
# インポートして利用
import japanize_matplotlib
Python変数の値をOSコマンドに渡す
-
globモジュールでファイルの一覧を取得する。 -
$変数名の形でPython変数の値をシェルコマンドに渡す。
import glob
files = glob.glob('sample_data/*.csv')
print(files)
file = files[1]
# $file で変数の値をOSコマンドに渡す
!head -2 $file
NumPy入門
NumPy表示形式の設定
-
np.set_printoptionsで小数点以下の表示桁数や表示形式を制御する。
import numpy as np
x = np.array([2/7, 1000/7, 0.00304567])
print(x) # デフォルト表示
# 表示形式の設定
# suppress=True : 固定小数点表示
# precision=4 : 小数点以下4桁
# floatmode='fixed' : 最終桁が0でも表示
np.set_printoptions(
suppress=True, precision=4, floatmode='fixed'
)
print(x)
データ定義 (array関数)
-
np.arrayでPythonリストからNumPy配列(ベクトル)を作成する。
# 1次元配列(ベクトル)の定義
n1 = np.array([1, 7, 5, 2])
print(n1)
-
typeで型確認、shapeで配列の形状、lenで要素数を確認する。
print(type(n1)) # <class 'numpy.ndarray'>
print(n1.shape) # (4,)
print(len(n1)) # 4
- 2次元配列(行列)もネストしたリストで定義する。
# 2次元配列(行列)の定義
n2 = np.array([
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
])
print(n2)
print(n2.shape) # (3, 4)
print(len(n2)) # 3(行数)
数値配列の生成 (linspace / arange)
-
np.linspaceで等間隔の数値配列を生成する。第3引数は点の数(植木算)。
# 0から2まで11個の等間隔の点
n3 = np.linspace(0, 2, 11)
print(n3)
# [0. 0.2 0.4 0.6 0.8 1. 1.2 1.4 1.6 1.8 2. ]
-
np.arangeで等間隔の数値配列を生成する。第3引数は間隔値。第2引数は「未満」。
# 0から2.2未満まで0.2刻み
n4 = np.arange(0, 2.2, 0.2)
print(n4)
参照(インデックス・スライス)
- 2次元配列の特定の要素を
[行, 列]で指定して取得する(0始まり)。
n2 = np.array([
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
])
# 1行目2列目の要素(0始まり)
n5 = n2[1, 2]
print(n5) # 7
- 行全体・列全体をスライスで抽出する。
:はすべてを意味する。
# 1行目のすべての列
n6 = n2[1, :]
print(n6) # [5 6 7 8]
print(n6.shape) # (4,)
# すべての行の0列目
n7 = n2[:, 0]
print(n7) # [1 5 9]
print(n7.shape) # (3,)
- 行・列の範囲をスライスで指定して部分行列を取得する。
# 0-1行目、2-3列目
n8 = n2[:2, 2:]
print(n8)
# [[ 3 4]
# [ 7 8]]
print(n8.shape) # (2, 2)
- True/False配列(ブールインデックス)を使って特定の行を抽出する。
# 0行目と1行目を抽出(2行目は除外)
n2_index = np.array([True, True, False])
n9 = n2[n2_index]
print(n9)
# [[1 2 3 4]
# [5 6 7 8]]
print(n9.shape) # (2, 4)
演算(要素ごとの演算)
- 同じ形状のNumPy配列同士は、要素ごとの演算が行われる。
n2 = np.array([
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
])
n10 = np.array([
[1, 4, 7, 10],
[2, 5, 8, 11],
[3, 6, 9, 12]
])
# 要素ごとの加算
n11 = n2 + n10
print(n11)
# [[ 2 6 10 14]
# [ 7 11 15 19]
# [12 16 20 24]]
ブロードキャスト機能
- 配列とスカラー値の演算では、スカラーが全要素に自動適用される。
n1 = np.array([1, 7, 5, 2])
# すべての要素から4を引く
n12 = n1 - 4
print(n12) # [-3 3 1 -2]
- 行列変数とスカラー値の演算も同様に全要素に適用される。
n2 = np.array([
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
])
n13 = n2 - 2
print(n13)
- 行列とベクトルの演算では、ベクトルが各行に自動適用される。
n1 = np.array([1, 7, 5, 2])
# 行列の各行からベクトルn1を引く
n14 = n2 - n1
print(n14)
ユニバーサル関数
- NumPyの数学関数は配列全体に一括適用される(ユニバーサル関数)。
x = np.linspace(0, 2, 11)
print(x)
# 全要素の平方根を一度に計算
y = np.sqrt(x)
print(y)
集約関数
-
sum,max,minなどの集約関数で配列全体や特定の軸に沿った集計ができる。 -
axis=0は列方向(縦)、axis=1は行方向(横)、引数なしは全体。
n2 = np.array([
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
])
# 列ごとの合計 (axis=0)
s0 = n2.sum(axis=0)
print(s0) # [15 18 21 24]
# 行ごとの合計 (axis=1)
s1 = n2.sum(axis=1)
print(s1) # [10 26 42]
# 全体の合計
s2 = n2.sum()
print(s2) # 78
応用例:精度計算
- 配列同士の比較で True/False 配列を作成し、
sum()で一致数をカウントする。
yt = np.array([1, 1, 0, 1, 0, 1, 1, 0, 1, 1])
yp = np.array([1, 1, 0, 1, 0, 1, 1, 1, 1, 1])
# 要素ごとの比較
matched = (yt == yp)
print(matched) # [ True True True ... False ...]
# True=1, False=0 として合計
correct = matched.sum()
total = len(matched)
accuracy = correct / total
print('一致数:', correct, '全体数:', total, '一致率:', accuracy)
# 一致数: 9 全体数: 10 一致率: 0.9
応用例:正規化(Min-Max変換)
- ベクトルの値を [0, 1] の範囲に変換する(ブロードキャスト機能の応用)。
n1 = np.array([1, 7, 5, 2])
# 最大値・最小値を取得
n1_max = n1.max()
n1_min = n1.min()
print(n1_max, n1_min) # 7 1
# Min-Max 正規化
n15 = (n1 - n1_min) / (n1_max - n1_min)
print(n15) # [0. 1. 0.6667 0.1667]
Matplotlib入門
ライブラリの利用と日本語化
-
matplotlib.pyplotをpltとしてインポートする。 -
japanize_matplotlibで日本語表示に対応する。
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
# NumPy表示形式の設定
np.set_printoptions(
suppress=True, precision=4, floatmode='fixed'
)
# グラフのデフォルトフォントサイズ
plt.rcParams["font.size"] = 14
# グラフのデフォルトサイズ
plt.rcParams['figure.figsize'] = (6, 6)
scatter(散布図)
-
plt.scatter(x, y)で散布図を描画する。
from sklearn.datasets import load_iris
iris = load_iris()
x, y = iris.data, iris.target
columns = iris.feature_names
# x, yの形状を確認
print(x.shape, y.shape) # (150, 4) (150,)
print(columns)
- 最もシンプルな散布図。
# 簡単な散布図
plt.scatter(x[:,0], x[:,2])
plt.show()
- タイトル・軸ラベル・グリッド・色分けなどを加えた散布図。
-
c引数で色分けの値、cmapでカラーマップを指定する。
# やや複雑な散布図
plt.scatter(x[:,0], x[:,2], c=y, cmap='rainbow')
plt.grid()
plt.xlabel(columns[0])
plt.ylabel(columns[2])
plt.title('アイリスデータセットによる散布図')
plt.show()
plot(関数グラフ)
-
plt.plot(x, y)で折れ線グラフ(関数グラフ)を描画する。
x = np.linspace(0, 2, 11)
y = np.sqrt(x)
plt.plot(x, y)
plt.show()
-
plotを複数回呼び出すと重ね描きになる。label引数とplt.legend()で凡例を表示する。
x = np.linspace(0, 2, 101)
y1 = np.sqrt(x) # ルート関数
y2 = x ** 2 # 2次関数
plt.plot(x, y1, label='ルート関数')
plt.plot(x, y2, label='2次関数')
plt.legend()
plt.grid()
plt.xlabel('x')
plt.ylabel('y')
plt.title('2つの関数グラフの重ね描き')
plt.show()
複数グラフ表示 (subplot)
-
plt.figure(figsize=...)でグラフ全体のサイズを指定する。 -
plt.subplot(行数, 列数, 番号)で複数グラフの配置位置を指定する。 -
axオブジェクト経由でscatter,set_title,gridなどを呼び出す。 -
plt.tight_layout()でグラフの重なりを防ぐ。
from sklearn.datasets import load_iris
iris = load_iris()
x, y = iris.data, iris.target
columns = iris.feature_names
plt.figure(figsize=(15, 5))
for i in range(1, 4):
ax = plt.subplot(1, 3, i)
ax.scatter(x[:,0], x[:,i], c=y, cmap='rainbow')
ax.set_title(columns[0] + ' vs ' + columns[i])
ax.grid()
plt.tight_layout()
plt.show()
Pandas入門
ライブラリのインポートと初期設定
-
pandasをpdとしてインポートし、display関数でデータフレームを整形表示する。
import pandas as pd
from IPython.display import display
- パラメータの初期化で表示精度と列の表示数を設定する。
# 小数点以下4桁表示
pd.options.display.float_format = '{:.4f}'.format
# すべての列を表示
pd.set_option("display.max_columns", None)
データフレームの定義
- 2重リストと列名リストから
pd.DataFrameを定義する。
data1 = [
['田中優花', '女', 140, 40.5],
['佐藤和也', '男', 175, 70.2],
['鈴木一郎', '男', 170, 65.0],
['高橋美香', '女', 158, 55.6],
]
df1 = pd.DataFrame(
data1, columns=['氏名', '性別', '身長', '体重']
)
print(type(df1)) # <class 'pandas.core.frame.DataFrame'>
display(df1)
- データフレームの構成要素(列インデックス・行インデックス・データの値)を確認する。
# 列名のリスト
print('列インデックス', list(df1.columns))
# 行インデックス
print('行インデックス', list(df1.index))
# データの値(NumPy配列として取得)
print('データの値')
print(df1.values)
CSVファイルの読み込み
-
pd.read_csv()でCSVファイルを読み込む。ローカルファイルパスまたはURLを指定できる。
# ローカルファイルからの読み込み
df2 = pd.read_csv('df-sample.csv')
display(df2)
# URLから直接読み込む
csv_url = 'https://raw.githubusercontent.com/makaishi2/samples/main/data/df-sample.csv'
df3 = pd.read_csv(csv_url)
display(df3)
Excelファイルの読み込み
-
pd.read_excel()でExcelファイルを読み込む。
excel_url = 'https://github.com/makaishi2/samples/raw/main/data/df-sample.xlsx'
df4 = pd.read_excel(excel_url)
display(df4)
Series(1次元データ)
-
pd.Seriesでリストから1次元データを定義する。name引数で名前を付ける。
s1 = pd.Series(
[140, 175, 170, 158],
name='身長')
print(type(s1)) # <class 'pandas.core.series.Series'>
print(s1)
- データフレームの特定列を参照するとSeries型になる。
# 列名を指定してSeriesを抽出
s2 = df2['身長']
print(type(s2)) # <class 'pandas.core.series.Series'>
print(s2)
-
locで特定行を参照するとSeries型になる。
# 行インデックスを指定してSeriesを抽出
s3 = df2.loc[1]
print(type(s3))
print(s3)
参照(列・行の絞り込み)
- 各列のデータ型を
dtypesで確認する。
print(df2.dtypes)
- 列名のリストを使って部分的なデータフレームを抽出する。
cols = ['身長', '体重']
df5 = df2[cols]
display(df5)
-
head(n)で先頭n行を取得する。
display(df2.head(2))
- 条件式でTrue/False配列を作成し、行を絞り込む。
# 「性別が男」かどうかの判定
index1 = df2['性別'] == '男'
print(index1)
# True/False配列で行を絞り込む
df6 = df2[index1]
display(df6)
# 1行でまとめて書くこともできる
df7 = df2[df2['性別'] == '男']
display(df7)
操作(列の追加・削除・結合、行の追加)
列の削除
-
dropメソッドで指定した列を削除する。axis=1で列方向を指定する。 -
copy()でオリジナルデータに影響を与えないようにする。
df9 = df2.copy()
df9 = df9.drop('氏名', axis=1)
display(df9)
列の追加
- 新しい列名を指定してSeries変数を代入する方法。
# BMI値の計算
s4 = df2['体重'] / ((df2['身長']/100) ** 2)
df10 = df2.copy()
# 末尾に列を追加
df10['BMI'] = s4
display(df10)
-
insertメソッドで指定位置に列を追加する方法。
df10 = df2.copy()
# 2番目の位置に'BMI'列を挿入
df10.insert(2, 'BMI', s4)
display(df10)
列結合 (concat)
-
pd.concatで既存データフレームに新しい列を結合する(axis=1で横方向結合)。
s5 = pd.Series(np.array([10, 25, 45, 34]), name='年齢')
df11 = pd.concat([df10, s5], axis=1)
display(df11)
行の追加
-
appendメソッドやpd.concatで行を追加する。ignore_index=Trueで行インデックスを振り直す。
# 辞書形式で新しい行を追加
df12 = df2.append({
'氏名': '山田太郎', '性別': '男',
'身長': 165, '体重': 64.2},
ignore_index=True)
display(df12)