【Python入門】やりたいことから探す『逆引きPython使い方辞典』-データ分析・機械学習編-

逆引きPython使い方辞典 テクノロジー

どうも、TJです!(自己紹介はこちら

初心者向けPython入門ということで、今回は「これやりたいんだけど、どうすればいいんだっけ?」という時に役立つ逆引きpython使い方辞典』を作ってみました。

これからPythonを学びたいと考えているみなさんのお役に立てればうれしいです。

  1. ライブラリのインポート・データの読み込み
    1. ライブラリをインポートする
    2. CSVファイルを読み込む
    3. CSVファイルを書き出す
    4. ライブラリ内のデータセットを読み込む
  2. データの確認
    1. 先頭/末尾の5行を表示する
    2. 行数・列数を表示する
    3. 列名/インデックス名を表示する
    4. 列名/インデックス名のリストを表示する
    5. 列ごとのデータの種類を表示する
    6. 列ごとのデータの個数(値の数)を表示する
    7. データの行数を表示する
    8. データの文字数をカウントする
    9. 基本統計量を表示する
    10. 昇順/降順に並び替える
    11. 特定の列データを取り出す
    12. 特定の行データを取り出す
    13. 特定のデータ要素を取り出す
    14. 特定の範囲のデータを指定する
    15. データを横持ちにする
    16. 列データの中でユニークなデータをリストアップする
  3. データの追加・削除・結合
    1. 空のデータフレームを作る
    2. 列データを追加する
    3. 行データを追加する
    4. 列データを削除する
    5. 行データを削除する
    6. データを転置する
    7. 条件に合ったデータを抽出する
    8. ダミー変数を追加する
    9. データをユニオンする
    10. データをジョインする
  4. データの修正・変換
    1. 欠損値の個数をカウントする
    2. 欠損値がある行を削除する
    3. 欠損値を平均値で埋める
    4. 欠損値を1つ前の値で埋める
    5. 欠損値をダミーコードで埋める
    6. 重複データの個数をカウントする
    7. 重複データの2つ目以降を削除する
    8. 文字列の列データを整数に変換する
    9. 文字列の列データをdatetime型に変換する
    10. datetime型の列データを年月日単位のデータに変換する
    11. シリアル値データの個数をカウントする
    12. 数値データのみを抽出する
    13. シリアル値を日付型に変換する
    14. 元データをvariable(項目名)/value(値)の形式に変換する
    15. 文字列を大文字/小文字に統一する
    16. 文字列の特定の箇所を置換する
    17. 先頭と末尾の空白文字を削除する
  5. データの分析
    1. 合計値を求める
    2. 最大値/最小値を求める
    3. 平均値を求める
    4. 中央値を求める
    5. 最頻値を求める
    6. 分散を求める
    7. 標準偏差を求める
    8. 特定のグループ/列ごとに統計量を求める
    9. ピボットテーブルを表示する
    10. 列データの度数分布表を表示する
    11. 正規分布上である値が下から何%に該当するか求める
    12. 正規分布上で下から〇〇%に該当する値を求める
    13. 相関係数(相関行列)を求める
    14. 相関行列を色分けして表示する
  6. グラフの作成
    1. 列データのヒストグラムを表示する
    2. 棒グラフを表示する
    3. 文字列を横軸のインデックスに使う
    4. 折れ線グラフを表示する
    5. 円グラフを表示する
    6. 箱ひげ図を表示する
    7. 散布図を表示する
    8. 横軸の間隔を指定して時系列グラフを表示する
    9. 複数のグラフを同時に表示する
    10. 1つのグラフに複数の列を重ねて表示する
    11. グラフの大きさを変更する
    12. グラフにマーカーを追加する
    13. マーカーのスタイルを変更する
    14. グラフにグリッド線を追加する
    15. グラフに垂直線(axvline)、水平線(axhline)を追加する
    16. 横軸/縦軸の名前を追加する
    17. 横軸/縦軸の範囲を指定する
    18. 凡例を追加する
    19. 横軸の項目を90度回転させて表示する
    20. グラフ領域を塗りつぶす
    21. グラフ領域の面積を計算する
  7. 機械学習モデルを開発する
    1. データの前処理をする
    2. データを分割する
    3. アルゴリズムを選択する
    4. 学習する
    5. 予測する
    6. 評価する
    7. チューニングする
    8. 【番外編】Prophetを用いた時系列分析
    9. 【番外編】クラスタリングと次元圧縮
  8. その他
    1. datetimeを用いた日時情報の扱い
    2. 自然言語処理
    3. Jupyter Notebookで自動補完を有効にする
  9. 参考図書

ライブラリのインポート・データの読み込み

ライブラリをインポートする

%matplotlib inline # JupyterNotebookでノート内にグラフを表示させる
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style="スタイル名", font=["Meiryo", "Yu Gothic", "Hiragino Maru Gothic Pro"])
import scipy.stats import norm

CSVファイルを読み込む

df = pd.read_csv("test.csv")

# Shift-JIS形式の場合
df = pd.read_csv("testSJIS.csv", encoding="Shift_JIS")

# 0列目をインデックスする場合
df = pd.read_csv("test.csv", index_col=0)

# ヘッダーがないデータを読み込む場合
df = pd.read_csv("testNoHeader.csv", index_col=0, header=None)

# 日付を表す列を指定して取り込む場合
df = pd.read_csv('day.csv', parse_dates=[列番号])

CSVファイルを書き出す

df.to_csv("dump_data.csv", index=False)

ライブラリ内のデータセットを読み込む

# アヤメのデータセットを読み込む場合
sns.load_dataset("iris")

必要ライブラリ:pandas,matplotlib,seaborn

データの確認

先頭/末尾の5行を表示する

# 先頭の5行を表示する
df.head()

# 末尾の5行を表示する
df.tail()

行数・列数を表示する

df.shape()

列名/インデックス名を表示する

# 列名を表示する
df.columns

# インデックス名を表示する
df.index

列名/インデックス名のリストを表示する

# 列名のリストを表示する
list1 = [i for i in df.columns]
print(list1)

# インデックス名のリストを表示する
list2 = [i for i in df.index]
print(list2)

列ごとのデータの種類を表示する

df.dtypes

列ごとのデータの個数(値の数)を表示する

df["列名"].value_counts

データの行数を表示する

len(df)

データの文字数をカウントする

df["列名"].str.len()

基本統計量を表示する

df.describe()

昇順/降順に並び替える

# 昇順に並び替える場合
df.sort_values(by="列名",ascending=True)

特定の列データを取り出す

# 1列のデータを取り出す場合
df["列名"]

# 複数列のデータを取り出す場合
df[["列名","列名"]]

特定の行データを取り出す

# 1行のデータを取り出す場合
df.iloc[行番号]

# 複数行のデータを取り出す場合
df.iloc[[行番号,行番号]]

特定のデータ要素を取り出す

# 5-10行目を取り出す場合
df.iloc[4:10]

# 5-10行目の3-6列目を取り出す場合
df.iloc[4:10,2:6]

# すべての行の2列目を取り出す場合
df.iloc[:, 1]

特定の範囲のデータを指定する

df.loc[行名,列名]

データを横持ちにする

df.unstack()

列データの中でユニークなデータをリストアップする

df["列名"].unique()

データの追加・削除・結合

空のデータフレームを作る

df = pd.DataFrame()

列データを追加する

df["新列名"] = 列データ

# 空のデータフレーム(dfB)を作って、列データを追加する
import pandas as pd
dfA = pd.read_csv("test.csv", index_col=0)

dfB = pd.DataFrame()
dfB["新列名"] = dfA["列名"]
dfB

行データを追加する

df = df.append(行データ)

# 空のデータフレーム(dfB)を作って、行データを追加する
dfA = pd.read_csv("test.csv", index_col=0)
dfB = pd.DataFrame()
dfB = dfB.append(dfA.iloc[行番号]]
dfB

列データを削除する

df.drop("列名", axis=1)

※axisは検索の方向を示す。{横方向(列検索):1, 縦方向(行検索):0}

行データを削除する

df.drop(df.index[行番号])

データを転置する

df.T

条件に合ったデータを抽出する

# 国語の点数が80より大きい行を抽出する(単一条件)
import pandas as pd
dfA = pd.read_csv("test.csv", index_col=0)

dfB = dfA[dfA["国語"] > 80]
dfB

# 国語の点数が80より大きく、かつ数学の点数も80より大きい行を抽出する(AND条件)
dfB = dfA[(dfA["国語"] > 80) & (dfA["数学"] > 80)]
dfB

# 国語の点数が80より大きい、または数学の点数が80より大きい行を抽出する(OR条件)
dfB = dfA[(dfA["国語"] > 80) | (dfA["数学"] > 80)]
dfB

ダミー変数を追加する

pd.get_dummies(df["列名"],prefix="生成される列名に付加するプレフィクス")

データをユニオンする

pd.concat([データ_left, データ_right], ignore_index=True)

データをジョインする

# left joinする場合
pd.merge(データ_left, データ_right[["列名1", "列名2", "列名3"]], on="キーとなる列名", how="left")

# 左右のデータでキーとなる列名が異なる場合
pd.merge(データ_left, データ_right, left_on="データ_leftのキーとなる列名", right_on="データ_rightのキーとなる列名", how="left")

データの修正・変換

欠損値の個数をカウントする

df.isnull().sum()

# 欠損値の有無を確認する場合
df.isnull().any(axis=0)

欠損値がある行を削除する

df = df.dropna()

# 指定した列で欠損値がある行のみ削除する場合
df = df.dropna(subset=["列名"])

欠損値を平均値で埋める

df = df.fillna(df.mean())

欠損値を1つ前の値で埋める

df = df.fillna(method="ffill")

欠損値をダミーコードで埋める

df = df.fillna({"列名":"ダミーコード"})

# 置換元のデータ型が文字列ではない場合
df = df.replace({"列名":{np.nan:"ダミーコード"}})

重複データの個数をカウントする

df.duplicated().value_counts()

重複データの2つ目以降を削除する

df.drop_duplicates()

文字列の列データを整数に変換する

df["列名"] = df["列名"].astype(int)

# カンマ付き文字列の列データのカンマを削除して整数に変換する場合(列ごと)
df["列名"] = df["列名"].str.replace(",","").astype(int)

# カンマ付き文字列の列データのカンマを削除して整数に変換する場合(データフレーム全体)
df = df.apply(lambda x: x.str.replace(',','')).astype(np.int)

文字列の列データをdatetime型に変換する

import datetime
pd.to_datetime(df["列名"])

必要ライブラリ:datetime

datetime型の列データを年月日単位のデータに変換する

import datetime
df["datetime型データ列名"].dt.strftime("%Y/%m/%d")

必要ライブラリ:datetime

シリアル値データの個数をカウントする

df["列名"].astype("str").str.isdigit()
df.sum()

数値データのみを抽出する

df.select_dtypes(include=[np.number])

シリアル値を日付型に変換する

pd.to_timedelta(シリアル値データ.astype("float"), unit="D") 

元データをvariable(項目名)/value(値)の形式に変換する

pd.melt

必要ライブラリ:pandas

文字列を大文字/小文字に統一する

# 大文字に統一する場合
df["列名"].str.upper()

# 小文字に統一する場合
df["列名"].str.lower()

文字列の特定の箇所を置換する

df["列名"].str.replace("置換前の文字列","置換後の文字列")

先頭と末尾の空白文字を削除する

df.strip()

データの分析

合計値を求める

df["列名"].sum()

最大値/最小値を求める

df["列名"].max()
df["列名"].min()

平均値を求める

df.mean()

# 特定の列データの平均値を求める場合
df["列名"].mean()

# 特定のグループ(性別など)ごとに平均値を求める場合
df.groupby("グループ名").mean()

必要ライブラリ:pandas

中央値を求める

df.median()

必要ライブラリ:pandas

最頻値を求める

df.mode()

必要ライブラリ:pandas

分散を求める

df.var()

必要ライブラリ:pandas

標準偏差を求める

df.std()

必要ライブラリ:pandas

特定のグループ/列ごとに統計量を求める

# グループごとに合計値を出す場合
df.groupby("まとめたい列名").sum()["列名"]

# 複数のグループごとに複数の列データの合計値を出す場合
df.groupby(["まとめたい列名1","まとめたい列名2"]).sum()[["列名A", "列名B"]]

ピボットテーブルを表示する

# 合計値のピボットテーブルを表示する場合
pd.pivot_table(df, index='インデックス名', columns='列名', values=['列名A', '列名B'], aggfunc='sum')

列データの度数分布表を表示する

cut = pd.cut(df["列名"], bins=区切る範囲 right=False)
cut.value_counts(sort=False)

必要ライブラリ:pandas

正規分布上である値が下から何%に該当するか求める

cdf = norm.cdf(x=調べたい値, loc=平均値, scale=標準偏差)

必要ライブラリ:scipy.stats

正規分布上で下から〇〇%に該当する値を求める

ppf = norm.ppf(q=パーセント値, loc=平均値, scale=標準偏差)

必要ライブラリ:scipy.stats

相関係数(相関行列)を求める

# 特定の列データの相関係数を求める場合
df.corr()["横の列名"]["縦の列名"]

# 相関行列を求める
df.corr()

必要ライブラリ:pandas

相関行列を色分けして表示する

sns.heatmap(df.corr())
plt.show()

# 相関係数を表示 + 最大値/最小値設定 + 中央の相関なしを0にする場合
sns.heatmap(df.corr(), annot=True, vmax=1, vmin=-1,center=0)
plt.show()

必要ライブラリ:pandas,matplotlib,seaborn

グラフの作成

列データのヒストグラムを表示する

df["列名"].plot.hist(bins=区切る範囲)
plt.title("グラフタイトル")
plt.show()

# 正規分布、推定カーブを付ける場合
sns.distplot(df["列名"], fit=norm, fit_kws={"color":"色"})
plt.title("グラフタイトル")
plt.show()

必要ライブラリ:pandas,matplotlib,seaborn

棒グラフを表示する

df.plot.bar()
plt.title("グラフタイトル")
plt.show()

必要ライブラリ:pandas,matplotlib,(seaborn)

文字列を横軸のインデックスに使う

df.set_index("列名",inplace=True)

折れ線グラフを表示する

df.plot()
plt.title("グラフタイトル")
plt.show()

# x軸、y軸、凡例名を指定する場合
df.plot(x="横軸の列名", y="縦軸の列名" ,label="凡例名")
例)df.plot(x = "dt" , y = "app", label = "アプリユーザ数")

# 方眼を表示する
plt.grid()

必要ライブラリ:pandas,matplotlib,(seaborn)

円グラフを表示する

df["列名"].plot.pie()
plt.title("グラフタイトル")
plt.show()

必要ライブラリ:pandas,matplotlib,(seaborn)

箱ひげ図を表示する

sns.boxplot(data=df, width=幅)
plt.title("グラフタイトル")
plt.show()

必要ライブラリ:pandas,matplotlib,seaborn

散布図を表示する

df.plot.scatter(x="横軸の列名", y="縦軸の列名", c="色", label="凡例名")
plt.title("グラフタイトル")
plt.show()

# seabornを使って散布図を表示する場合
sns.scatterplot(data=df, x="横軸の列名", y="縦軸の列名", hue="色分けしたい列名")

# 散布図 + 回帰直線を表示する
sns.regplot(data=df, x="横軸の列名", y="縦軸の列名", line_kws={"color":"色"})
plt.title("グラフタイトル")
plt.show()

# ヒストグラム付き散布図 + 回帰直線を表示する
sns.jointplot(data=df, x="横軸の列名", y="縦軸の列名", kind="reg", line_kws={"color":"色"})
plt.title("グラフタイトル")
plt.show()

# 散布図のすべての組み合わせを行列で表示する
sns.pairplot(data=df)
plt.title("グラフタイトル")
plt.show()

# 散布図のすべての組み合わせを行列で表示する(回帰直線を追加する)
sns.pairplot(data=df, kind="reg")
plt.title("グラフタイトル")
plt.show()

必要ライブラリ:pandas,matplotlib,seaborn

横軸の間隔を指定して時系列グラフを表示する

import matplotlib.dates as mdates
fig, ax = plt.subplots(figsize=(x, y))

ax.plot(dates_test, y_test, label='系列名A', c='カラー名') # グラフ描画
ax.plot(dates_test, y_pred, label='系列名B', c='カラー名')

weeks = mdates.WeekdayLocator(byweekday=mdates.TH) # 日付目盛間隔の指定(木曜日ごとに日付を表示)
ax.xaxis.set_major_locator(weeks)
ax.tick_params(axis='x', rotation=90) # 日付表記を90度回転

ax.grid() # 方眼表示など
ax.legend()
ax.set_title('グラフタイトル')
plt.show()

複数のグラフを同時に表示する

# パターン1
df.plot(subplots=True, layout=(x, y),sharex=True/False, sharey=True/False)

例)df.plot(subplots=True, layout=(2, 2),sharex=True, sharey=True)
※上記の例はx軸, y軸の範囲の共通化を行う場合(共通化しない場合はshareの部分不要)

# パターン2
fig, axes = plt.subplots(nrows=行数, ncols=列数, figsize=(x, y))
df.plot(ax=axes[行数, 列数], x="列名" ,y="列名",legend=True/False)

例)
fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(9, 6))
df.plot(ax=axes[0, 0], x="dt" ,y="app",legend=True)
df.plot(ax=axes[0, 1], x="dt" ,y="sp",legend=False, color="red")
df.plot(ax=axes[0, 2], x="dt" ,y="pc",legend=False, color="green")
df.plot(ax=axes[1, 0], x="dt" ,y="app",legend=False, kind="area")

1つのグラフに複数の列を重ねて表示する

ax = df.plot(y="列名1")
df.plot(x="横軸名",y="列名2", ax=ax)

例)
ax = df.plot(y="app")
df.plot(x="dt",y="sp", ax=ax)
plt.xticks(rotation=90)
plt.show()

グラフの大きさを変更する

df.plot(figsize=(x, y))

例)df.plot(figsize=(9, 6))

グラフにマーカーを追加する

plt.plot(x座標, y座標, c="色", marker="X", markersize=サイズ)
plt.show()

マーカーのスタイルを変更する

df.plot.line(style=['[color][marker][line]')

例)
df.plot.line(style=['r--', 'b.-', 'g+'])

# 指定例
color: r(赤), g(緑), b(青), k(黒)など
marker: o(丸), .(点), s(四角), +(プラス)など
line: -(破線), --(破線), :(点線)など
詳細URL:https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.plot.html

グラフにグリッド線を追加する

plt.grid()

グラフに垂直線(axvline)、水平線(axhline)を追加する

plt.axvline(x=x座標, c="色", linestyle="線の種類")
plt.axhline(y=y座標, c="色", linestyle="線の種類")
plt.show()

横軸/縦軸の名前を追加する

plt.xlabel("横軸名")
plt.ylabel("縦軸名")

横軸/縦軸の範囲を指定する

plt.xlim([MIN値:MAX値])
plt.ylim([MIN値:MAX値])

凡例を追加する

plt.legend()

横軸の項目を90度回転させて表示する

plt.xticks( rotation=90)

グラフ領域を塗りつぶす

plt.fill_between(x,y1,y2)
※y2は省略可

グラフ領域の面積を計算する

auc(x,y)
※area under the curveの略

機械学習モデルを開発する

データの前処理をする

# 2値ラベルを数値に変換する
tf_map = {True: 1, False: 0} # 辞書の定義
df["列名"].map(tf_map)

# 2値ラベルを数値に変換する(関数定義してyes/noを1/0に置換する場合)
def enc_bin(df, column):
    df[column] = df[column].map(dict(yes=1, no=0)) 
    return df
df = enc(df, "列名")

# データを正規化する(standardization)
from sklearn.preprocessing import StandardScaler
stdsc = StandardScaler()
df["列名"] = stdsc.fit_transform(df["列名"])

# One-Hotエンコーディングする(多値ラベルの数値化)
def enc(df, column):
    df_dummy = pd.get_dummies(df[column], prefix=column)
    df = pd.concat([df.drop([column],axis=1),df_dummy],axis=1)
    return df
df = enc(df, "列名")

データを分割する

# 入力データと正解データに分割する
x = df.drop('目的変数となる列名', axis=1)
y = df['目的変数となる列名'].values

# 訓練データと検証データに分割する(7:3で分ける場合)
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, 
    train_size=0.7, test_size=0.3, random_state=random_seed)

# 時系列データを訓練データと検証データに分割する場合
mday = pd.to_datetime('分割の境となる日付') # 分割日 mdayの設定
train_index = df['日付'] < mday # 訓練用indexと検証用indexを作る
test_index = df['日付'] >= mday
x_train = x[train_index] # 入力データの分割
x_test = x[test_index]
y_train = y[train_index]
y_test = y[test_index]

アルゴリズムを選択する

# ロジスティック回帰
from sklearn.linear_model import LogisticRegression
algorithm = LogisticRegression(random_state=random_seed)

# サポートベクターマシン(カーネル)
from sklearn.svm import SVC
algorithm = SVC(kernel='rbf', random_state=random_seed)

# XGBRegressor
from xgboost import XGBRegressor
algorithm = XGBRegressor(objective ='reg:squarederror',
    random_state=random_seed)

# 決定木
from sklearn.tree import DecisionTreeClassifier
algorithm = DecisionTreeClassifier(random_state=random_seed)

# ランダムフォレスト
from sklearn.ensemble import RandomForestClassifier
algorithm = RandomForestClassifier(random_state=random_seed)

# XGBClassifier
from xgboost import XGBClassifier
algorithm = XGBClassifier(random_state=random_seed)

# アルゴリズムから名称を取得する
name = algorithm.__class__.__name__

学習する

algorithm.fit(x_train, y_train)

予測する

y_pred = algorithm.predict(x_test)

評価する

# 精度(正解率)を計算する
score = algorithm.score(x_test, y_test)

# 適合率(precision)・再現率(recall)・F値(fscore)を計算する
from sklearn.metrics import precision_recall_fscore_support
precision, recall, fscore, _ = precision_recall_fscore_support(y_test, y_pred, average='binary')

# 混同行列を計算する
from sklearn.metrics import confusion_matrix
matrix = confusion_matrix(y_test, y_pred)
print(matrix)

# 確率値を計算する
y_proba = algorithm.predict_proba(x_test)

# 偽陽性率(fpr)・敏感度(tpr)・閾値(thresholds)を計算する
from sklearn.metrics import roc_curve
fpr, tpr, thresholds = roc_curve(y_test, y_proba1,drop_intermediate=False)

# 重要度を分析する
importances = algorithm.feature_importances_ # 重要度ベクトルの取得
w = pd.Series(importances, index=x.columns) # 項目名をキーにSeriesを生成
u = w.sort_values(ascending=False) # 値の大きい順にソート
v = u[:10] # top10のみ抽出
plt.title('入力項目の重要度') # 重要度の棒グラフ表示
plt.bar(range(len(v)), v, color='b', align='center')
plt.xticks(range(len(v)), v.index, rotation=90)
plt.show()

# 入力項目の影響度を分析する(重要度分析の続き)
column = '入力項目名'
sns.distplot(x_test[y_test==1][column], kde=False, norm_hist=True, bins=5,color='b', label='成功')
sns.distplot(x_test[y_test==0][column], kde=False, norm_hist=True, bins=5,color='k', label='失敗')
plt.legend()
plt.show()

# 決定係数(r2 score)を計算する
from sklearn.metrics import r2_score
r2_score = r2_score(y, y_pred)

# 閾値を変化させて適合率(precision)・再現率(recall)・F値(fscore)を計算する
def pred(algorithm, x, thres): # 閾値を変更した場合の予測関数の定義
    y_proba = algorithm.predict_proba(x) # 確率値の取得(行列)    
    y_proba1 =  y_proba[:,1] # 予測結果1の確率値
    y_pred = (y_proba1 > thres).astype(int) # 予測結果1の確率値 > 閾値
    return y_pred
thres_list = np.arange(0.5, 0, -0.05) # 閾値を0.05刻みに変化させる
for thres in thres_list:
    y_pred = pred(algorithm, x_test, thres)
    pred_sum =  y_pred.sum()
    precision, recall, fscore, _ = precision_recall_fscore_support(
        y_test, y_pred, average='binary')
    print(f'閾値: {thres:.2f} 陽性予測数: {pred_sum}\
 適合率: {precision:.4f} 再現率: {recall:.4f}  F値: {fscore:.4f})')

チューニングする

# 交差検定を行う(分割数=3)
from sklearn.model_selection import cross_val_score
scores = cross_val_score(algorithm , x_train, y_train, 
cv=3, scoring="評価指標")

# グリッドサーチと交差検定と組み合わせて最適パラメータを探索する(交差検定の分割数=3)
params = {
'パラメータ名A':[範囲], 'パラメータ名B':[範囲]}
from sklearn.model_selection import GridSearchCV
gs = GridSearchCV(algorithm, params, cv=3)
gs.fit(x_train, y_train)
best = gs.best_estimator_
best_pred = best.predict(x_test)
print(best)

【番外編】Prophetを用いた時系列分析

# 前提条件
・入力変数の形式:データフレーム
・命名規則:日付:ds、目的変数:y

# ライブラリのimport
from fbprophet import Prophet

# アルゴリズム選択
## 3つのseasonalityパラメータはTrue/Falseの他に数値での指定も可能 (三角関数の個数)
## seasonality_mode: additive(加算的) /multiplicative(乗算的)
 ※デフォルトはadditive
 ※増減の度合いを「率」で想定したい場合はmultiplicativeを指定する

m1 = Prophet(yearly_seasonality=True, weekly_seasonality=True, 
    daily_seasonality=False,
    seasonality_mode='multiplicative')

# 学習
m1.fit(x_train)

# 予測 
## 予測用データの作成
future1 = m1.make_future_dataframe(periods=予測したい日数, freq='D')
display(future1.head())
display(future1.tail())
## 予測実行 ※結果はデータフレームで戻ってくる
fcst1 = m1.predict(future1)

# 評価
(要素ごとのグラフ描画)※トレンド、週周期、年周期
fig = m1.plot_components(fcst1)
plt.show()

## 訓練データ・検証データ全体のグラフ化
fig, ax = plt.subplots(figsize=(x,y))

## 予測結果のグラフ表示(prophetの関数)
m1.plot(fcst1, ax=ax)
ax.set_title('グラフタイトル')
ax.set_xlabel('横軸名')
ax.set_ylabel('縦軸名')
plt.show()

## ypred1: fcst1から予測部分のみ抽出する
ypred1 = fcst1[-予測したい日数:][['yhat']].values
## ytest1: 予測期間中の正解データ
ytest1 = x_test['y'].values

## R2値の計算
from sklearn.metrics import r2_score
score = r2_score(ytest1, ypred1)
print(f'R2 score:{score:.4f}')

## 時系列グラフの描画 
import matplotlib.dates as mdates
fig, ax = plt.subplots(figsize=(x, y))
ax.plot(dates_test, ytest1, label='系列名A', c='カラー名')
ax.plot(dates_test, ypred1, label='系列名B', c='カラー名')
weeks = mdates.WeekdayLocator(byweekday=mdates.TH)
ax.xaxis.set_major_locator(weeks)
ax.tick_params(axis='x', rotation=90)
ax.grid()
ax.legend()
ax.set_title('グラフタイトル')
plt.show()

#チューニング
STEP1:「休日」を特別な日として追加(holidaysパラメータの利用)

## 休日の抽出
df_holiday = df[df['祝日']==1]
holidays = df_holiday['日付'].values

## データフレーム形式に変換
df_add = pd.DataFrame({'holiday': 'holi',
    'ds': holidays,
    'lower_window': 0,
    'upper_window': 0
})
display(df_add.head())     
display(df_add.tail())    

## 休日(df_add)をモデルの入力とする
(holidaysパラメータを追加してモデルm2を生成)
m2 = Prophet(yearly_seasonality=True, 
    weekly_seasonality=True, daily_seasonality=False,
    holidays = df_add, seasonality_mode='multiplicative')

## 学習
m2 = m2.fit(x_train)

## 予測
fcst2 = m2.predict(future1)

## 評価
前述の通り

#チューニング
STEP2:日付以外の項目を入力データに追加

## 学習データに項目を追加
df3 = pd.concat([df2, df[['項目名A', '項目名B', '項目名C', '項目名D']]], axis=1)

## 入力データの分割
x2_train = df3[train_index]
x2_test = df3[test_index]
display(x2_train.tail())

m3 = Prophet(yearly_seasonality=True, 
    weekly_seasonality=True, daily_seasonality=False,
    seasonality_mode='multiplicative', holidays = df_add)

## add_regressor関数で、追加項目をモデルに組み込む
m3.add_regressor('項目名A')
m3.add_regressor('項目名B')
m3.add_regressor('項目名C')
m3.add_regressor('項目名D')

# 学習
m3.fit(x2_train)

# 予測
## 予測用の入力データを作る
future3 = df3[['ds', '項目名A', '項目名B', '項目名C', '項目名D']]
## 予測実行
fcst3 = m3.predict(future3)

## 評価
前述の通り

【番外編】クラスタリングと次元圧縮

# クラスタリング(K-Means法)

## アルゴリズム選択
from sklearn.cluster import KMeans
clusters=4 # グループ数を定義
algorithm = KMeans(n_clusters=clusters, random_state=random_seed) # アルゴリズムの定義

## 学習・予測
y_pred = algorithm.fit_predict(df)

# 次元圧縮

## アルゴリズムの選択
from sklearn.decomposition import PCA
pca = PCA(n_components=2) # 散布図表示のため2次元に圧縮

# 学習・変換
d = pca.fit_transform(df)

その他

datetimeを用いた日時情報の扱い

import datetime
from datetime import timedelta

# 現在の日付取得
today = datetime.date.today()

# 任意の日付取得
day = datetime.date(2021,1,1)

# 日付の計算 ※今日の2日前の日付を取得する
day = today - timedelta(days=2)

# フォーマット変換
day = today.strftime('%Y/%m/%d')

自然言語処理

# MeCabのインストール
!pip install mecab-python3

# 形態素解析
## MeCabライブラリのインポート&初期化
import MeCab
tagger = MeCab.Tagger()

## 形態素解析で抽出した名詞を確認
all_words = []
parts = ["名詞"]
for n in range(len(survey)):
    text = survey["comment"].iloc[n]
    words = tagger.parse(text).splitlines()
    words_arr = []
    for i in words:
        if i == "EOS" or i == "": continue
        word_tmp = i.split()[0]
        part = i.split()[1].split(",")[0]
        if not (part in parts):continue
        words_arr.append(word_tmp)
    all_words.extend(words_arr)
print(all_words)

## 関係ない単語を除去
stop_words = ["の"]
all_words = []
parts = ["名詞"]
for n in range(len(survey)):
    text = survey["comment"].iloc[n]
    words = tagger.parse(text).splitlines()
    words_arr = []
    for i in words:
        if i == "EOS" or i == "": continue
        word_tmp = i.split()[0]
        part = i.split()[1].split(",")[0]
        if not (part in parts):continue
        if word_tmp in stop_words:continue
        words_arr.append(word_tmp)
    all_words.extend(words_arr)
print(all_words)

## 頻出単語を表示
all_words_df = pd.DataFrame({"words":all_words, "count":len(all_words)*[1]})
all_words_df = all_words_df.groupby("words").sum()
all_words_df.sort_values("count",ascending=False).head()

Jupyter Notebookで自動補完を有効にする

%config IPCompleter.greedy=True

参考図書

こちらもおすすめです。

Progate(プロゲート) | Learn to code, learn to be creative.
タイトルとURLをコピーしました