Pythonでよく使うコード:その3 Pandas編

publicjournal.hatenablog.com
publicjournal.hatenablog.com

Pandasの基礎

抽出

pythondatascience.plavox.info
列の抽出はdf.loc[:,['A','B']]でもいけるし,df[['A','B']]でもいける
deepage.net

イテレータ

sinhrks.hatenablog.com

blog.mwsoft.jp

qiita.com
これは割とはまり易いので注意。apply後の連結はSeriesを使うべし。DataFrameだと、indexが合わないので変になる。

Jsonファイルの取り扱い

qiita.com
teratail.com
qiita.com

データの型

qiita.com

大容量を読み込む

qiita.com

Dockerによる環境構築

先日、図書館に行ったら良さげな本が置いてあったので借りてきました。最低限の機能を使いこなすために必要な知識を丁寧に解説している良書でした。

そういえば、これまでDockerを自己流で使っていました。必要なものだけを調べるだけで、体系的には勉強していませんでした。折角なので、これを機に勉強してみます。

勉強がてらに、この記事に本書の要点をメモしておきます。

本書のメモ

環境を立ち上げる

この書籍では、まず環境を立ち上げるコマンドとして、次のものが紹介されています。

docker run --name tutorial -d -p 80:80 docker/getting-started

コマンドについては次の通り。

コマンド 説明
run コンテナを作成し、実行するコマンド。containerという単語は省略可。
name tutorial ダウンロードしたコンテナに名前を付けるための引数。今回はtutorialという名前が指定されているが、この引数を指定しない場合でも、自動的に名前が付けられる。
p 80:80 仮想コンピュータ内とホストコンピュータ側を接続するための引数。`80:80`は接続するポート番号を示しており、ホストコンピュータ側で80番ポートで接続すると、仮想コンピュータ側の80番ポートに接続される。
docker/getting-started 取り込むイメージファイルを指定するための引数。

dockerコマンドの例

本書で紹介されている代表的なコマンドについて、記載しておきます。
コンテナの停止、削除

// コンテナの停止
docker stop tutorial

// コンテナの一覧を表示
docker ps -a

// 削除
docker rm tutorial

あとは、この書籍では「すべて破棄するまでがDocker」と解説されていました。これまではあまりそういう意識が無かったです・・。作りっぱなしで放置でした。

// イメージを削除
docker image re

// イメージの一覧を表示して、存在するイメージを確認
docker image ls

Docker composeを試す

コマンドだけでは大変なのでDocker composeというDockerの立ち上げ設定書の機能があります。(ここら辺は知っている話なので、割愛)
コンテナとイメージについて紹介されていて、各々には次のような違いがあります。

  • イメージ:プログラムのもととなるファイルのようなもの
  • コンテナ:そのイメージを使って作成するもの

参考:'Docker のイメージとコンテナ: どう違う?' | CircleCI

Docker composeのyamlを編集するにあたって、ボリュームのマウントというのがあります。ボリュームというのは、OSによって定義された区切りであり、ストレージの単位の一つ。マウントの仕方については次の通りです。

  • ボリュームマウント :Docker Engine上でマウント
  • バインドマウント :パソコンに作成したファイルやディレクトリにマウント
  • メモリーマウント :パソコンのメモリにマウント

Docker composeのコマンド

イメージの作成 build
docker compose build
コンテナの作成 create
docker compose create
コンテナの起動 start 、既存コンテナの再起動 restart、 既存コンテナの停止 stop
docker compose start
docker compose restert
docker compose stop
コンテナの廃棄 rm
docker compose rm
一気にコンテナを立ち上げる up、 一式のコンテナを停止して廃棄する down
docker compose up -d

docker compose down

// コンテナが削除されているかを確認する
docker compose images
コンテナを実行 run

runの後にはdocker-compose.ymlファイルのservice内のimage名を入力する

docker compose run httpd bash
特定のコンテナ内でコマンドを実行 exec

runとの違いは既にコンテナがupされているかどうかという違いです。対話形式のコマンドbushも立ち上げられます。新しい画面を開いてほかの操作をするのと同じ感覚でコンテナを操作できる。exitでbushから出る。

docker compose up -d
docker compose exec httpd bash

#exit
docker compose down
docker run -d -p 8001:80 docker5-1

ハンズオンで試してみる

基礎の部分を一通り読んでみたので、自分で手を動かしてみます。最近はよくPythonを使うので、Python環境を作ってみます。本書の解説とググって出てきた下記のサイトを参考に動作を試してみます。

まずは作業ディレクトリを作成する

test_docker_pythonというディレクトリを作ってみます。この中にyamlとDockerfileを置いておきます。

docker-compose.ymlは次の通りに設定しました。今回はWindows側のDドライブの中に後述のtest.pyというスクリプトを置いて、これの動作を試します。

version: '3'
services:
  python3:
    build:
      context: .
      dockerfile: Dockerfile   
    container_name: 'test_python_env'
    volumes:
      - /mnt/d/test://new_dir
    tty: true


Dockerfileも下記のように作ってみます。よく使うライブラリをインストールする、という想定で作成してみました。

FROM continuumio/miniconda3 

RUN conda create -n chemodel python==3.10

RUN conda install numpy
RUN conda install scipy

RUN conda install pandas

イメージを作成する

dockerを起動して、buildコマンドを実行します。

buildした時に、下記のようなメッセージが出力されました。

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them

これはこれで、一応ビルドされているっぽいです。

コンテナを作成する

背景色が見づらいですが、下記のように実行します。

コンテナを起動する

起動されていることを確認

Python起動

凄い簡単に作ったtest.pyを動かしてみます。マウントされているWindows側のファイルを指定します。

# test.py
import pandas as pd 
import os 
path ='test_csv.csv'
print(os.path.exists(path)) 
#pd = pd.read_csv(path)

トラブル

下記のようにexceコマンドが実行できないというトラブルがありました。元々は下記のようにDocker composeを書いていました

version: '3'
services:
  python3:
    build:
      context: .
      dockerfile: Dockerfile   
    container_name: 'test_python_env'
    volumes:
      - /mnt/d/test://new_dir

これだと、ただbashを実行しただけで終わってしまいます。 State が「Exit 0」(正常終了)で終わっています。

なので、下記を参考にttyを入れました。
teratail.com
もしくはdocker compose startを忘れても同じメッセージが表示されます。

その他

code .でVs codeからもbashが使えます。

WSL2にDockerをインストールする

去年の夏くらいに条件付きでDocker Desktop有償になりました。誤って有償の条件に当てはまっていたら面倒なので、無償の方法を模索して環境構築をしました。
あの時はネットの記事を調べて断片的に実施していったものの、まとまっている記事がなかった気がします。そのせいか、最近PCを変えてDocker無償環境構築をしようとおもってもどうやったのか忘れました・・・。
なので、Dockerの環境構築の方法をメモしておきます。加えて、最近は良くPythonを使うので、Visual Studio CodeとJupyter Notebook上でPythonを使う方法を書いておきます。

WSL2をインストールする

ここら辺は公式ドキュメントやQiita記事を読んだほうが分かりやすいです。とくにハマるところも無いし。転記するのも面倒なのでリンク先を参照のこと。
www.kagoya.jp
qiita.com
【Note】

  • 昔インストールしたときはMicrosoft storeから「Ubuntu 20.04 LTS」をインストールした

Docker環境を構築する

Docker Engineをインストールする

この辺もリンク先を参照のこと。
docs.docker.com

Docker Engineを起動する

# 起動
sudo service docker start
# 状態確認
sudo service docker status
# 動作確認
sudo docker run --rm hello-world

Pythonライブラリに関するチートシート

以前からプログラミング作業効率化のために、Pythonでよく使うライブラリについてまとめていました。
publicjournal.hatenablog.com
publicjournal.hatenablog.com

最近、チートシートがTwitterで流れてきたので、リンクを貼っておきます。

チートシートリンク

Pandas

github.com

Matplotlib

github.com

DockerにNumPyroをインストールする

先日までCmdStanPyを使っていました。が、Anaconda をアンインストールしてPipやconda forgeから再インストールしたら、何故かうまく動作しませんでした。。。やっぱりStan系はインストールが大変です、、。
「諦めてPyStanを使うか、PyCM3に戻ろうかなぁ」なんて思っていた矢先、こういう記事を発見しました。

NumPyroというパッケージがあって、これがなかなか興味深いです。ノーUターンサンプラでMCMCの計算が出来るので、CmdStanPyの代わりになりそうです。NumPyroの公式ドキュメントを以下に貼り付けておきます。

さて、CmdStanPyのインストールを試しているうちに、ローカル環境がぐちゃぐちゃになってしまいました、、。これを反省して、今回からはDocker上に環境構築をします。
(「Numpyro インストール」でググってみるとGoogle Colaboratoryを利用した方法が多く紹介されていましたが、練習もかねてDockerを使いました)

インストール

Pipを利用するといろいろと上手くいかなかったので、miniconda上に構築しました。Docker fileを次のように書きました。割とシンプルな例ですが、結構試行錯誤しました。

FROM continuumio/miniconda3  

RUN conda create -n chemodel python==3.10 
  
RUN conda install numpy 
RUN conda install scipy 
RUN conda install -c conda-forge jax 
RUN conda install -c conda-forge numpyro

CmdStanPyの試運転

先日CmdStanPyをインストールしてみました。(詳細は下記参照)
publicjournal.hatenablog.com
RのStanやPyStanと結構違うので、どういうものかと一通り使ってみました。ひとまず“Hello, World”を参照にしながら動作確認をしました。

同じような例題が書籍「Pythonによるベイズ統計モデリング」のP48~57にあるので、同書と同じことをCmdStanPyを使ってやってみたいと思います。

例題

こんな例題を考えます。

コイン投げ問題を考える。コインを10回投げて裏と表を記録する。表を1、裏を0として記録したところ、[1,0,1,0,0,0,0,0,1,0]となった。このデータをもとに、コインが偏っているかを判断する。コインの偏りを調べるために、次のモデルを用いる。


\begin{aligned}
\theta  \sim Beta \big(1,1\big) \\
y  \sim Bin  \big(n=10, p=\theta\big) 
\end{aligned}

プログラムの全貌

プログラムは次の通り。

Stanのファイル

Stanのファイルは次の通り

解説

統計モデルの作成

上記のStanファイルにそって統計モデルを作成します。

モデルオブジェクトの生成

先ほどのStanファイルを読み込みます。
PyStanならばpystan.stan(model_code=XXX, data=XXXX, iter=1000, chains=4)などと書いていましたが、CmdStanPyならばStanファイルを指定して次の通りになります。

### Stanファイルを読み込んでオブジェクトを生成する
stan_file_path = 'sample_model.stan'
model = CmdStanModel(stan_file=stan_file_path)

model_codeでモデルをベタ書きできるのかは調査中です。

サンプリングの実行

sample()でハミルトニアンモンテカルロ法のノーUターンサンプラが走るそうです。

### MCMCを実行して事後分布をサンプリングする
iter_sampling = 1000 # サンプリングの数.デフォルト1000
chains = 4 # 並列サンプリングの数.デフォルト4

# データの作成
front_and_back_list = [1,0,1,0,0,0,0,0,1,0]
data = {
    "N" : len(front_and_back_list),
    "y" : front_and_back_list
    }
# 実行
fit_sm = model.sample(data=data,
                      iter_sampling=iter_sampling,
                      iter_warmup = iter_warmup, 
                      chains = chains,
                      seed=1234)

sample()の引数として、よく使うのは次のものかと思います。

  • data:データの辞書を渡す。これは他のStanと同じ。
  • iter_sampling :サンプル数を指定する。他のStanのiterと同じっぽい。
  • iter_warmup :バーンインの数を指定する。他のStanのwarmupと同じっぽい。
  • chains:並列して走るチェーンの数。これは他のStanと同じ。
  • seed:seed値を設定。これは他のStanと同じ。

下記を参考にしました。

またノーUターンサンプラは下記に詳細が載っています。

診断と結果の解釈

ここら辺はもっと便利なものがあるのかどうか分かりませんが、ひとまずPyMC3の収束診断っぽいものを作ってみました。

### 事後分布の診断
la = fit_sm.stan_variables()
plt.figure(figsize=(10,3))
bins=15
for i, k in enumerate(la.keys()):
    boxplot_list =[]
    for j in range(chains):
        x = la[k][j*iter_sampling:(j+1)*iter_sampling]
        hist, bin_edges = np.histogram(x, bins=bins) # 度数分布に変換
        #print(len(hist),len(bin_edges))
        plt.subplot(len(la.keys()), 3, 3*i+1) 
        plt.plot(bin_edges[:bins], hist, alpha=0.6, lw=0.6)
        plt.subplot(len(la.keys()), 3, 3*i+2) 
        plt.plot(x, alpha=0.5, lw=0.8)
        boxplot_list.append(x)
    plt.subplot(len(la.keys()), 3, 3*i+3) 
    plt.boxplot(boxplot_list)
plt.show()

### 結果を解釈する
samples = az.from_cmdstanpy(posterior = fit_sm)
print(az.summary(samples))

また結果の要約についてもarvizというライブラリを使うと比較的簡単に出来るようです。

Data variables:
    theta    float64 1.002
        mean     sd  hdi_3%  hdi_97%  mcse_mean  mcse_sd  ess_bulk  ess_tail  r_hat
theta  0.335  0.133   0.095    0.577      0.003    0.002    1462.0    1934.0    1.0

arviz-devs.github.io