スプレッドシートの計算をPandasで再現してみた
スプレッドシートでやる計算を、軽量化のためにpythonのPandasで実装しようとしたら、思いの他詰まったのでまとめたいと思います。
取り込んだ統計データのcsv等を使ってシミュレーションを組みたいときに活用できるかと思います。
なおサンプルとして、口座から引落と預入をして残高を算定するスプレッドシートを挙げています。
引落し額の上限を3,000円と設定しており、入力した引落し額が3,000円を超えている場合は、自動的に3,000円を引落し額として設定しています。
pandas化のテクニックとして取り上げているのは、以下の2つになります。
2つのセルを比較して小さい(大きい)数字をピックアップする
pandasの列(又は)行の中で一番小きい(大きい)値をピックアップする方法はたくさん紹介されているのですが、Aという列の要素とBという列の要素を比較して、小さい(大きい)数値を入力する列を作成する手法を見つけるのに苦労しました。
1つ上の行の計算結果を参照する (前月末の残高を当月頭の残高にするイメージ)
なお、コードをダウンロードする場合はこちら。
import pandas as pd # 使用する日付、引落入力、預入のDataFrameを作成。 # 実務ではこちらのデータはcsv等で取り込むイメージです df1 = pd.DataFrame({ "date":["4/1", "4/8", "4/15", "4/22", "4/29", "5/6", "5/13", "5/20", "5/27", "6/3"], "withd_inp":[2000, 0, 4000, 0, 1500,3500,0,6000,0,4000], "deposit":[0,3000,0,0,2000,0,0,0,8000,0] })
色々調べたのですが、for文を使う以外に変数とpandasの要素を比較して最小値、最大値を抽出する方法が見つからなかったので、引出制限 3,000円をpandasの要素として設定しています。
見た目を気にする場合は、最後に削除するとOK。
# 引落入力と比較するための"引出制限 3,000円" をlimitカラムに入力 # 次にdf の要素に min関数を適用するためにカラムに入力している df1["limit"] = 3000 # 要素同士を比較して小さい方を実際の引落に入力 df1["withd_act"] = df1[["withd_inp", "limit"]].min(axis=1) # for文を適用するために 今週頭の残高と、今週終の残高のカラムを作成する # None を入力する必然性はないが、数字と区別するために None を入力しておく df1["accnt_head"] = None df1["accnt_tail"] = None
出力結果はこうなります。
# 今週頭の残高と、今週終の残高の作成 for i in range(len(df1)): if i == 0: df1["accnt_head"][0] = 3000 else: df1["accnt_head"][i] = df1["accnt_tail"][i-1] df1["accnt_tail"][i] = df1["accnt_head"][i] - df1["withd_act"][i] + df1["deposit"][i]
以下のようにエラーが出てしまいますが、一応計算されているようです。
C:\path\lib\site-packages\ipykernel_launcher.py:4: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy after removing the cwd from sys.path.
SettingWithCopyWarningの参考サイト note.nkmk.me
スプレッドシートと並びが違いますので、気になる方は以下の処理をご参考ください。
# 順番が気になるので並び替え df2 = pd.DataFrame(df1["date"]) df2 = pd.concat([df2, df1.iloc[:,-2]], axis=1) df2 = pd.concat([df2, df1.iloc[:,1]], axis=1) df2 = pd.concat([df2, df1.iloc[:,4]], axis=1) df2 = pd.concat([df2, df1.iloc[:,2]], axis=1) df2 = pd.concat([df2, df1.iloc[:,-1]], axis=1)
また、スプレッドシートでは使用していないのでgithub中のコードでは省略しましたが、pandasの要素に自作の関数等を使うテクニックもご紹介します。
# pandasの要素に、自作の関数を適用したい場合 def 自作の関数: 設定したい処理 df['X'] = df['A'].map(自作の関数) # pandasの要素に、無名関数 lambda を適用したい場合 df["X"] = df["A"].map(lambda x : 設定したい処理 ) # 単純にmax()、min()関数を設定するだけなら関数を作成する必要はありませんが、要素を計算した後の数値に対してmax()、min()を設定したい場合には、以下のような方法も使えます。 def 関数名(row): #rowはDataFrame型にあたります return max((row['A'] - row['B'])*0.9, 0) df['X'] = df.apply(関数名, axis=1)
以上になります、最後までお読みいただきありがとうございました。
参考サイト
「はじめてのパターン認識」を読む 第2章 識別規則と学習法の概要 2項 汎化能力
はじめてのパターン認識 を1章ずつ読んでまとめたいと思います。
2章は長いので、半分に分けています。
前半はこちら。
学習データとテストデータの作り方
<用語解説>
学習
学習データに対する識別関数の出力値と、教師データとの誤差が最小になるように、識別関数のパラメーターを調整すること
汎化能力
未知のデータに対する識別能力
汎化誤差
未知の学習データに対する識別関数の出力値と教師データとの誤差誤差
母集団
データの集合
真の分布
母集団の d次元特徴の分布のこと。 で表される
偏り(バイアス)
学習データとテストデータの各特徴の平均値や分散に生じているズレのこと
学習データとテストデータは、あくまで真の分布からランダムでサンプリングされているため、偏り(バイアス)をゼロにすることは非常に困難である。
真の誤り率
母集団から学習データを抽出して識別関数を設計し、同じ母集団から抽出したテストデータを用いてテストした際の誤り率のこと
再代入誤り率
母集団から学習データを抽出して識別関数を設計し、テストの際も学習データと同じデータを用いて測定した誤り率のこと
再代入誤り率が大きい場合は、そもそも識別機の能力が足りていないことがわかる。
手元にあるデータを、学習用とテスト用に分割する手法
(1)ホールドアウト法
手元のデータを二つに分割し、一方を学習に使い、もう一つをテストのために使い、誤り率を推定するために使用する手法
Pythonで簡単にホールドアウト法用のデータ分割をする方法 | WATLAB -Python, 信号処理, AI-
学習につかうデータを多くすればテスト用のデータが減少するため、学習精度はよくなるが性能評価bigdata-tools.comの精度は悪くなる。
テストに使うデータを多くすれば学習用のデータが減少するため、学習そのものの精度が悪くなる。
真の誤り率、再代入誤り率、ホールド誤り率の間には、下記の関係が成り立つ。
再代入誤り率の期待値 =< 真の誤り率 =< ホールドアウト誤り率
pythonだと、train_test_split を使って実装しますね。
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y)
scikit-learnでデータを訓練用とテスト用に分割するtrain_test_split | note.nkmk.me
(2)クロスバリデーション法(交差確認法)
手元の各クラスのデータをそれぞれ m 個のグループに分割し、m - 1 個のグループのデータを使って識別機を学習し、残りの一つのグループのデータでテストを行う。
これを m 回繰り返し、それらの誤り率の平均を性能予測値とする手法。
クロスバリデーションとグリッドサーチ(備忘録) - Qiita
手元にあるすべてのデータを学習とテストに利用するので、よい性能予測を行える。
ただし、分割のやり方次第では偏りが生じてしまうので、分割のやり方を変えて考査確認法を繰り返し、その平均で誤差識別率を予測することが必要。
pythonですと、cross_val_score を使いますね。
from sklearn.model_selection import cross_val_score # cv=5で分割数を指定 scores = cross_val_score(forest, X, y, cv=5)
(3)ジャックナイフ法(一つ抜き法)
データ全体のうち1つだけをテストデータとする方法。
その後、テストデータと学習用データを入れ替えて繰り返し、全てのケースがテスト事例となるよう検証を繰り返す。
機械学習、ディープラーニングでの学習データとテストデータの分割手法について - AI人工知能テクノロジー
(4)ブーストラップ法
母集団となるデータがあるときに,母集団から重複を許してランダムにいくらかデータを取り出して再標本化をする手法
ブートストラップサンプリング(Bootstrap Sampling)法とそのscikit-learnを用いた実行 - Qiita
汎化能力の評価方法とモデル選択
<用語解説>
モデル選択
パラメータの数を変え、テストデータに対する誤り率がもっとも小さくなるパラメータを選択する方法
平均2乗誤差(MSE Mean Square Error)
線形回帰モデルの性能を数値化する効果的な手法の一つで、実際の値とモデルによる予測値との誤差の平均値。
平均二乗誤差 MSE:Mean Square Errorが楽々わかる!回帰モデルの性能評価 | AIZINE(エーアイジン)
バイアス・分散トレードオフ
バイアス(偏り)を小さくすれば分散(バリアンス)が大きくなり、分散(バリアンス)を小さくすればバイアス(偏り)が大きくなる現象。
汎化能力を決める大きな要因となる。
バイアス(偏り)
真の値(学習データ)と平均予測値のずれの大きさ
バイアスが大きいとはモデルの予測がかなり外れていることを表し、バイアスが小さいということはモデルがかなりの精度で予測できている
分散(バリアンス)
予測値のばらつきの大きさ
バリアンスが大きいと学習データごとに予測値が大きく変化することを表し、バリアンスが小さいと学習データにかかわらず予測値がほぼ一定になる
【機械学習】バイアスとバリアンスの違いを分かりやすく | pekochin
過学習
学習(訓練)データにあまりに適合しすぎて、学習(訓練)データでは正解率が高いのに学習(訓練)データとは異なるデータ(例えば、評価データ)では正解率が低くなってしまう、つまり、学習(訓練)データだけに最適化されてしまって汎用性がない状態に陥ること
AIが学習しすぎる?「過学習」問題とそれを抑制する方法 | AI入門ブログ
学習データを使ってパラメータの調整をし、テストデータを使って誤り率を評価しても、誤り率が目標よりも小さくならない場合は、学習だけではどうすることはできないので、識別関数を変える必要がある。
過去のまとめ
「はじめてのパターン認識」を読む 第1章 はじめに - koji/メガネ男の日誌
「はじめてのパターン認識」を読む 第2章 識別規則と学習法の概要 1項 識別規則と学習法の分類 - koji/メガネ男の日誌
以上になります、最後までお読みいただきありがとうございました。
GWを振り返る
GWも終わってしまった・・・ということで、2日目に引き続き、振り返ってみました。
<勉強>
統計的機械学習の数理100問ですが、20ページちょっと行ったところで、そもそも数学がよくわからないという厚い壁に阻まれました。
この1冊でショートカットできるかな、と思ったのは甘かったようです。
「大学基礎数学 線形代数キャンパス・ゼミ」を買ったので、まずはコチラで数学の基礎力をあげようと思います。
<運動>
ボクササイズ動画配信を見ながらボクササイズしました。
また、不要不急と言われるとアレですが、、県境まで20km、徒歩で踏破してみました。
人込みは避けているので、お許しください。
非常にいい運動になりました。
歩いている最中は足が痛くなりましたが、何とか筋肉痛にはならずに済みました。
<ゲーム>
2日目ブログで書いた通り、Fallout 1st を軽くプレイしました。
クォータービューなので見づらいのですが、味方を誤射?できる、誤射すると味方にヌッ殺される、等、さすがアメリカゲーだなあ・・・と感じております。
また、GW中のニンテンドースイッチの抽選にはことごとく落ちました。。
ど〇ぶつの森…ゼ〇ブレイド…
でもまだJoshinがありますし、公式でも抽選をやるという噂なので、希望をつないでいこうと思います。
<マンガ>
2日目で書いた通り、サマータイムレンダ。めっさ面白い!
5/13(水)発売予定の10巻も予約しました、楽しみです!
また、なんとなく購入がストップしていた空挺ドラゴンズの続きを買い、これまた狭くて浅いやつらで紹介されていた、マジカルパンチマジカル抜きを買いました。
設定自体は魔法少女+格闘、という使い古されたものの組み合わせな気もしますが、シュールで面白いですw
<読書>
みんなのコンピュータサイエンスを読みました。
アルゴリズムとか、プログラミングの仕組みとかの概念を体系的に学べました。
情報系の学部に行っていればあまり気にしなくて済んだんでしょうが、紆余曲折でIT分野にいる自分には、こういった書籍はありがたい限りです。
<雑感>
後半は疲れもあり、ボーっとすることが多かったですが、勉強も余暇もそれなりに過ごせたかなと思います。
何より、早寝早起きはキープできたので、体調は良いです。
休み明けも引き続き頑張っていきたいと思います。
「はじめてのパターン認識」を読む 第2章 識別規則と学習法の概要 1項 識別規則と学習法の分類
はじめてのパターン認識 を1章ずつ読んでまとめたいと思います。
2章は長いので、半分に分けています。
<用語>
学習データ
たくさんの微妙に異なる特徴ベクトルを正解に対応付けるためのデータ
なお、 特徴ベクトル
抽出されたたくさんの特徴をベクトルの形にまとめたもの
汎用能力
学習データを使った学習モデルを実装したサービスを世に出すと、学習データには含まれていなかったデータが使われる可能性があるが、このような場合でも識別できる能力のこと。
2.1 識別規則と学習法の分類
識別規則の構成法
代表例
(a)事後確率が最大のものに分類する方法
事前確率とは、データを手に入れる前に想定していた確率のことです。
事後確率とは、データを用いて事前確率を修正した結果の確率です。
ある朝、目が覚めたとき、今日の天気は雨か晴れかわからないなと思いました。何となく、今日晴れる確率は50%かなと想像しました。 この50%が事前確率です。
窓の外を見ました。
日の出はとっくに過ぎているのに外がどんよりとして曇っていました。
この結果を見て、雨が降る確率は80%くらいじゃないのかなぁと修正しました。
この80%が事後確率です。
(b)各分類の代表的なベクトルとの距離を計算し、一番近い代表ベクトルに分類する。
代表例:最近傍法
今,緑の円で表される新しいデータを取得したとします.
このデータを青い四角か赤い三角のどちらかのグループに所属させる必要があります.
この過程を 分類 と呼びます.
具体的に何をすれば分類できるのでしょうか?k近傍法を使って分類をしてみましょう.
この新しいデータに最も近いデータを確認するという方法が挙げられます.
画像を見ると,新しいデータに一番近いデータは赤い三角であることは明らかです.
なので,個の新しいデータは赤い三角のグループに追加します.
最も近い距離にあるデータにのみ依存する分類であるため,この方法は単純に 最近傍法(Nearest Neighbour) と呼ばれます.
(参考)scikit-learn KNeighborsClassifier のコード
(c)関数を使って、その正負、または最大値で分類を決める方法。
識別のために用いられる関数を識別関数という。
代表例:パーセプトロン型学習回路、サポートベクトルマシン。
パーセプトロン型学習回路
人間の脳にはニューロンという神経細胞があり, それを数式で表すためにニューロンモデル(形式ニューロン)が作られた.
ニューロンモデルはいくつかの入力とひとつの出力を持っている.
出力は"1"か"0"かの2つの値しか出力しない.
2つの値をどちらか決めるためにしきい値を使う.
入力にそれぞれ結合荷重という定数との積を足し合わせた数(ネット値)よりもしきい値が低ければ"1"そうでなければ"0"を活性化関数を使って出力する.
このモデルをパーセプトロンという.
サポートベクトルマシン
サポートベクトルマシンを理解するためには、名前の由来である「サポートベクトル」について理解する必要があります。
サポートベクトルとは、先に説明したように「予測に必要となる一部のデータ」です。
では「予測に必要となる一部のデータ」はどのようにして決められるのでしょうか。
それを定めるのに「マージン最大化」と呼ばれる考え方を使います。
SVMでは、正しい分類基準を見つけるために、「マージン最大化」という考えを使います。
マージンとは、「判別する境界とデータとの距離」を指します。
これが大きければ、「ほんの少しデータが変わっただけで誤判定してしまう」というミスをなくすことができます。
なお、境界線と最も近くにあるデータを「サポートベクトル」と呼びます。
境界の近くにあるデータ、すなわちサポートベクトルのみを用いて分類を行います。
サポートベクトル以外のデータの値が多少変化したとしても、分類のための境界線の位置は一切変わりません。
(d)決定木
分類木と回帰木の総称して決定木といいます.
分類木
例えば温度が27度で湿度が40%の日は暑くないと感じています.
このデータから「温度と湿度がどのようなときにどう感じるのか?」といったことを木で表現できます.
この図を同様にグラフに描画するとこのようになります.
回帰木
例えば温度が27度で湿度が40%の日は水を1.5L飲んでいます.
分類木のときと同様にこのデータから「温度と湿度がどのようなときに水を何L飲むか?」といったことを木で表現できます.
この図を同様にグラフに描画するとこのようになります.
(参考)scikit-learn DecisionTreeClassifier のコード
教師付き学習
<用語>
パラメータ
写像の性質を決める性質。
で表す
識別規則は、 パラメータと入力ベクトルの線形関数(内積)を用いて表現される。
写像
2つの集合があるとき、一方の集合の要素を他方の集合の要素に結びつける対応関係
教師データ
入力データの分類を指定したデータ
学習データセット
学習に用いられるすべての対の集合
学習の目的と流れ
学習の目的は、学習データを正しく識別できるを求めること。
学習の流れとしては、学習データセットの関数としてwを得る方法 や、学習データを一つずつ用いてを少しずつ修正していく方法がある。
少しずつ修正する場合、正しく識別できるようになるためには、同じ学習データを何度も使って学習する必要がある。
得られた値と、教師データの差が小さくなるように修正し、差が小さくなったら学習を止め、学習に使用しなかったテストデータを用いて性能評価を行う。
教師付き学習と線形回帰
<用語>
教師付き学習
教師データがある学習法
回帰(関数近似)
教師データとして、関数値が与えられる場合に、与えられた関数値に近い値を出せる識別関数の能力のこと。
(簡単に言うと、求めたい値により近い値を出せる関数かどうか、といったところ?)
線形関数で近似する場合を線形回帰と呼ぶ
被説明変数(目的変数)、説明変数
統計やAI(人工知能)分野では求めたいものを「目的変数」、目的変数に作用する変数を「説明変数」と表現します。
教師なし学習
<用語>
教師なし学習、または自己組織型学習
教師のいない学習のこと
クラスタリング
教師がいない学習の場合において、入力データ間の距離や類似度 や、 統計的な性質 に基づいて分類を自動的に生成すること。
形質導入学習(、または半教師あり学習)
一部のデータのみ教師をつけ、他は教師なしで学習を行うこと
Web上などに存在する大量のテキスト・画像・音楽データを分類する際、コストを抑えるために用いられる。
(参考)
過去のまとめ
「はじめてのパターン認識」を読む 第1章 はじめに - koji/メガネ男の日誌
以上になります、最後までお読みいただきありがとうございました。
「はじめてのパターン認識」を読む 第1章 はじめに
はじめてのパターン認識 を1章ずつ読んでまとめたいと思います。
1.1 パターン認識とは
パターン認識の成否を決める鍵
識別に有効な特徴を素早く抽出すること
識別規則の学習
学習データを用いて汎化能力を精度よく推定できること
<用語>
特徴抽出
識別の手がかりとなる特徴量を測定すること。
特徴ベクトル
抽出されたたくさんの特徴をベクトルの形にまとめたもの
識別規則
特徴ベクトルを用いて分類を行うための規則
入力データが所属する正しいクラスに帰属先を探すための規則
学習データ
入力データとクラスの対応関係を対にした沢山のデータ
汎化能力
学習データにはなかった未知の入力データについても正しいクラスを識別する能力
1.2 特徴の型
特徴の型
- 定性的特徴
非数値データ
名義尺度 分類のための名前
名前、住所 etc...
順序尺度 順序関係を表す。比較はできるが加減算は出来ない。
5段階評価、大中小、優良可
- 定量的特徴
数値データ
間隔尺度 一定の単位で量られた量。原点はあっても「無」ではない
テストの成績、摂氏・華氏などの温度、年月
比例尺度 原点が定まっている量。割り算や比例計算が意味を持つ。原点は「無」である
身長、体重、年齢、絶対温度
ダミー変数
定性的な特徴(ほ乳類かどうか etc...)を数値(ほ乳類の場合 1、そうでない場合 0)で符号化すること。
1.3 特徴ベクトル空間と次元の呪い
特徴ベクトル空間
10 ✖ 10 のドットで文字を表現する場合、100個のドットがあるので、この画像データは100次元の特徴を持つ空間である、と考える。
次元の呪い
次元(≒特徴量の種類?)が増えれば増えるほど、必要な学習データの数が指数関数的に増えること。
先ほどの10 ✖ 10 のドットの場合、1つのドットで16色使える場合、情報量が100の16乗(千兆)になる。
超立方体
n次元の各辺が等しい図形のことらしい。
頂点の数と辺の数は以下のとおり導ける。
■ 頂点の数は2倍ずつ増える
■ 辺の数は1つ前の次元の「辺の数の2倍と頂点の数」を足した数になる。
もとのカタチを新しい次元に平行移動して(辺の数は2倍増える)、対応する頂点間を結ぶため(辺の数は頂点の数だけ増える)。
感想
まだ初めの方のため、用語の定義の話が多いので、まだついていける。
超立方体の頂点の数はともかく、辺の数や面の数を計算しようと思うと、その1個前の次元の情報が必要になってくるため、よくわからなかった。。
以上になります、最後までお読みいただきありがとうございました。
GW後半2日目で振り返り
stayhome でロクに遊びにも行けませんが、GWも2日目ということで、気持ちがダレないよう、振り返ってみました。
<勉強>
・統計的機械学習の数理100問 251ページ中、19ページ
行列式と偏微分がわかってないので、テキストを見ながらノートにガリガリ書いて理解進め中。
・DLGのkaggle勉強会
取り組んでいるコンペの進捗を共有した。
と言っても、人のnotebookに書いてコードを整理して理解に努めているだけですが。。
ちゃんと自分で組めるようになるのはいつになるやら。
<動画視聴>
・ネットフリックス
カウボーイビバップを見ました。
3回目くらいに見返した作品ですが、年齢を重ねて見てみると、ジェットの面倒見の良さが際立つ・・・。
<ゲーム>
・Fallout クラシックコレクション
Fallout 歴は4を少しやったことある程度。
PC だけでプレイできる、ある程度知ってて、かつネタバレは知らなくて面白そうな作品、ということでチョイス。
PS4 は売り切れで買えず、申し込んだ Switch の抽選にはことごとく外れているので、PC で出来る Steamで Fallout を堪能しようと思います。。
<マンガ>
・サマータイムレンダ
狭くて浅いやつら、というポッドキャストで知って読み始めたのですが、めちゃくちゃ面白くて一気に9巻まで読み進めてしまいました!
タイムループ、田舎の孤島、得体のしれない敵との闘い、魅力的なキャラクターと盛りだくさんです。
後半のタイムループの説明が高度過ぎて、ちょっと私の頭ではついていけなくなりましたが。。
次の単行本発売が楽しみです!
こういう作品が好きな方は是非!
<雑感>
早寝早起きは継続中。
遊びすぎず、勉強しすぎず、と連休を堪能しております。
連休中で統計的機械学習の数理100問をこなせるかなーと思ってましたが、甘かったようです。
数学の学びなおしもかねてと割り切って、じっくり腰を据えて取り組もうと思います。
以上になります、最後までお読みいただきありがとうございました!
python の melt() でグラフ化しやすいデータに加工する
python の melt でグラフ化しやすいデータに加工するテクニックをまとめました。
まずは、グラフ化しにくい DataFrame型のデータを作成します。
import pandas as pd # データの作成 df = pd.DataFrame(data=[('a',1,2,3,4,5,6,7),('b',8,9,10,11,12,13,14), ('c',15,16,17,18,19,20,21),('d',22,23,24,25,26,27,28), ('e',29,30,31,32,33,34,35),('f',36,37,38,39,40,41,42), ('g',43,44,45,46,47,48,49)]) df.columns = ['category', 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
こんな感じのデータが出力されます。
これだとカラムの1つか2つくらいしかグラフに出来ず、Sun(日曜)~Sat(土曜)と時系列にならべることができません。
df.plot("category", "Sun")
そこで、melt 関数を使って並べ替えます。
df_m = pd.melt(df, id_vars=['category'], value_vars=['Sun','Mon','Tue','Wed','Thu','Fri','Sat'], var_name = "Day of the week", value_name = "Num")
以降、データが続く・・・
このようにデータを整えると、時系列に並べてグラフ化ができます!
df_m.plot("Day of the week", "Num")
以上になります、最後までお読みいただきありがとうございました。
コードはこちら
参考
公式ドキュ