Watson StudioのJupyter NotebookからDb2の表にデータ出力をする

#はじめに
最近Watson Studioの無償版を使って、Pythonや各種機械学習の自習を行なっています。
当文書では、ICOS（IBM Cloud Object Storage)にあるCSVファイルを一度Pandasデータフレームとして取り込み、それを今度はibmdbpyを使ってDb2 on Cloudの表に書き出す、という例を紹介しています。
Panadasデータフレームを新規の表として書き出す方法と、一旦各列のデータタイプを明示的に指定して表を作ってから、その表に書き出す、という方法の２つを紹介しています。
後者のほうが処理は一手間多くなりますが、自分の望む列名やデータタイプを明示的に指定できるというメリットや既存の表を利用したい場合には有効な方法です。
#ibmdbpyとは
ibmdbpyは、Pythonに対して、IBM Db2へのデータ読み書きやインデータベース分析のアルゴリズム（回帰処理やクラスタリングなど、各種分析のための処理をDB内で行うことのできる機能）へのインターフェースを提供します。
ibmdbpyは、Python 2.7から3.6までとの互換性があり、ODBCやJDBCの接続を使ってDb2のデータベースに接続、Pandasと類似の構文で記述した処理ををSQLに変換してDb2データベースの読み書きを行います。
#Jupyter NotebookからDb2にデータを書き出す例
それでは実際にPandasデータフレームの内容をDb2に書き出すコードを見てみましょう。
###入力データの準備
まず初めに入力データをCSVファイルからPandasデータフレームに読み込みます。
ここでは予めWatson Studioのプロジェクトにデータ・アセットとして登録してあったCSVファイルを利用します。
Jupyter Notebookの画面右の方にある"1010"アイコン（"Find and add data"アイコン）をクリックしてデータ・アセット一覧を表示、利用したいCSVファイルの下に表示されている"Insert to code"とあるリンクをクリック、さらに"Insert pandas DataFrame”を選択すると、そのCSVファイルをPadasデータフレームとして取り込むコードが自動入力されます。
![スクリーンショット 2019-05-13 1.42.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404035/9c2af01b-608b-bcd7-7aaf-c3440e3d0174.png)

```python
import types
import pandas as pd
from botocore.client import Config
import ibm_boto3
def __iter__(self): return 0
client_5f49f3cb9952422e92f42dcb40c41528 = ibm_boto3.client(service_name='s3',
    ibm_api_key_id='XXXXXXXXXXXXXXXXXXXX',
    ibm_auth_endpoint="https//iam.bluemix.net/oidc/token",
    config=Config(signature_version='oauth'),
    endpoint_url='https://s3-api.us-geo.objectstorage.service.networklayer.com')

body = client_5f49f3cb9952422e92f42dcb40c41528.get_object(Bucket='XXXXXXXXXX',Key='emp.csv')['Body']
# add missing __iter__ method, so pandas accepts body as file-like object
if not hasattr(body, "__iter__"): body.__iter__ = types.MethodType( __iter__, body )

df_data_1 = pd.read_csv(body)
df_data_1.head()
```
Watson StudioのJupyter　Notebookで自動生成されるコードでは、上記にあるように最後に`head()`を実行して先頭の５行をサンプル表示するようにしています。以下は実行結果です。
![スクリーンショット 2019-05-13 1.49.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404035/a283b770-073b-4457-1871-b7a5812cc2ff.png)

###ibmdbpyによるDb2への接続
Watson Studioが提供するJupyter Notebookの環境には予めibmdbpyが導入されています。
ここでは、Db2への接続を作成するためのパッケージとして`IdaDataBase`、それとPandasデータフレームのような形態でデータを取り扱うためのパッケージである`IdaDataFrame`をインポートして利用します。
Db2 on Cloudに接続するために必要な認証情報は、Db2 on Cloudのコンソールから取得し、手動でコードを記述することもできますが、もしそのDb2 on Cloudへの接続が、Watson Studioのアセットとして登録済みの場合には、認証情報をJupter Notebookのセルに取り込むことができます。
Jupyter Notebookの画面右の方にある"1010"アイコン（"Find and add data"アイコン）をクリックして今度は”Connections"とある方を選択、登録済みのDb2 on Cloudの下に表示されている"Insert to code"とあるリンクをクリック、さらに"Insert Credentials”を選択すると、接続のために必要な認証情報についての変数定義がセルに自動入力されます。（下記例におけるcredential_1の部分）
Db2への接続は`IdaDatabase`によって作成されます。
![スクリーンショット 2019-05-13 18.58.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404035/f3d4ae1a-1669-ef6b-ca95-4f65a66dd638.png)

```python
credentials_1 = {
    'username': 'uuuuuuuuuu',
    'password': """pppppppppppp""",
    'database': 'dddddd',
    'host': 'xxxxxxxxxxxxxxxxxxx',
    'port': 'ppppppp'
}
dsn = 'DASHDB;Database={};Hostname={};Port={};PROTOCOL=TCPIP;UID={};PWD={}'.format(
    credentials_1['database'],
    credentials_1['host'],
    credentials_1['port'],
    credentials_1['username'],
    credentials_1['password']
)
from ibmdbpy import IdaDataBase, IdaDataFrame

idadb = IdaDataBase(dsn)
```
###Pandasデータフレームのデータを新規の表として書き出す
`IdaDataBase`によってDb2への接続ができたら、実際にPandasデータフレームの内容をデータベースに書き出すことができます。
Pandasデータフレームの名前を指定して`as_idadataframe`を実行することで、Pandasデータフレームの列名とそのデータタイプに基づいてデータベースの表を自動作成し、Pandasデータフレームの内容をデータベースに書き出すことができます。
以下では、上記定義済みのPandasデータフレーム`df_data_1`の内容を`EMPLOYEE_2`というDb2の表に書き出し、最後にコミット処理をしています。さらに内容確認のため書き込み済みの表の先頭５行をサンプル表示しています。

![スクリーンショット 2019-05-13 2.20.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404035/934dc328-9bb1-08d4-b07a-9c028781742a.png)

```Python
ida_df=idadb.as_idadataframe(df_data_1, 'EMPLOYEE_2')
idadb.commit
```
###Pandasデータフレームのデータを既存の表に追記する
今度は、一旦列名やデータタイプを明示指定して表を作成し、その表にデータを書き込む方法を示します。
まずは、SQLを直接実行することのできる`ida_query`を使って`CREATE TABLE`を実行、明示的に列名やデータタイプを指定して表を作成します。

```python
idadb.ida_query('create table employee_3  (empno char(6) not null , firstnme varchar(12) not null , midinit char(1) , lastname varchar(15) not null , workdept char(3) , phoneno char(4) , hiredate char(10) , job char(8) , edlevel smallint not null , sex char(1) , birthdate char(10) , salary decimal(9,2) , bonus decimal(9,2) , comm decimal(9,2) )')
```
表が無事作成できましたら、作成した表をIDAデータフレームとして定義し、上記作成済みのPandasデータフレームの内容を書き込みます。
下記の例では、作成した表EMPLOYEE_3を参照するIDAデータフレーム`ida_df`を定義し、Pandasデータフレーム`df_data_1`の内容を書き出してから、最後にコミット処理をしています。
こちらの方式のほうが、表を明示的に作成する分一手間余計ですが、Pandasデータフレームの内容から自動的に選択される列名やデータタイプではなくて、明示に内容を自分で指定したい場合や、あるいは既存の表にデータを追加する形で利用したい場合には、こちらの方式のほうが適していると言えます。

```python
ida_df = IdaDataFrame(idadb, 'EMPLOYEE_3')
idadb.append(ida_df, df_data_1)
idadb.commit
```
![スクリーンショット 2019-05-13 2.37.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404035/164abdd6-60ad-2cb0-af29-7dc17efeb15b.png)
Db2への接続を切断するためには`close()`を実行します。
![スクリーンショット 2019-05-13 18.36.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404035/ec78b06b-e35e-146b-5eca-74ad2e6b99fd.png)

#まとめ
Watson StudioのJupyter NoteBookに導入済みのibmdbpyにより、とても簡単にDb2 on Cloudへの読み書きができることがわかりました。
Db2 on Cloudへの読み書きは今回紹介した方法以外にもいくつかあります。次回以降、順次サンプルを紹介します。