アクチュアリーのためのPython入門(第18回)
pandasを使った外部ファイルの取り込み
📚 アクチュアリーのためのPython入門
この記事は入門編の一部です。
▶ 目次はこちら
はじめに
前回までに、保険収支と感応度分析、利源分析を行いました。
これで基本的な保険数理はできたのですが、
Pythonを使って、実務で使いやすく、また効率化をしていきます。
今回は、一般のPython入門でも取り上げられるpandasを使います。
pandasは外部ファイルを簡単に取り込めるようにするライブラリで、
特にCSVファイルやExcelファイルの取り込みを容易にします。
実務に近い形として、
- 契約ポートフォリオをExcelから読み込む
- 契約単位で保険収支を計算する
- ポートフォリオ全体の収支を集計する
- 結果をExcelへ出力する
という流れをpandasを用いて実装します。
前回までは、コード内に契約情報を入れていましたが、
これを外部のExcelファイルにし、
出力もPythonのprintではなく、Excelファイルにします。
pandasを使用する準備
まず、次のライブラリをインストールする必要があります。
-
pandas今回使用するライブラリ -
openpyxlExcel(.xlsx)が読み込むためのライブラリ
これらのインストール方法については、
Pythonの環境によって異なりますし、
本筋から外れてしまいますので、
ここでは省略させてください。
「pandas python インストール」などで検索すれば、
解説しているサイトが探せると思います。
計算の前提
前回と同じように定期保険のファイルterm.pyを使用し、
以下の関数は同ファイルまたはimportされている前提とします。
-
PremT:保険料の計算 -
netPremT:純保険料の計算 -
ResT:保険料積立金の計算 -
SVT:解約返戻金の計算
また、term.pyが置いてある場所に、
Excelファイルをcontr_term.xlsxを作成し、次の契約内容とします。
保険収支のコード
続いて、term.pyのコードに入ります。
保険収支のコード書き換えます。
from core import *
import pandas as pd
まず、from core import *は以前までと同じく、
core.pyの死亡率や生命表、給付現価を読み込みます。
import pandas as pdはpandasのライブラリを読み込み、
使用名をpdとしています。使用名は任意です。
# アサンプションの設定
c_period = 10 # 計算する期間
k = 0.7 # 死亡指数
qwx = [0.02] * c_period # 解約率
# 結果を入れるリスト
results =[]
アサンプション部分は前回と同じです。
結果を入れるリストを作成しておきます。
続いて、今回のポイントのExcelファイルの読み込みです。
# Excelファイルの読み込み
df = pd.read_excel("contr_term.xlsx")
for _, row in df.iterrows():
sex = row["sex"]
age = int(row["age"])
term = int(row["term"])
amount = int(row["amount"])
pd.read_excel("contr_term.xlsx")でpandasを使って、
Excelファイルを読み込んでいます。それをdfに格納します。
for文とdf.iterrows()で、
dfから1行ずつ取り出して処理することができます。
_をついているのはdfの1つ目に、
Excelの行数(1,2,3,…)が入っていますので、
それを読み込まず、2つ目以降をrowに代入しています。
rowのカラムsexの値をsexに代入します。
age、term、amountも同じです。
なお、intをつけているのは、
Excelで書式が数値などで小数を0埋めしていたり、
見えない浮動小数点があったりするための対応です。
次のコードです。
保険金額の初期値を設定したら、
あとは、前回までと同じです。
# 保険収支の計算
l0 = amount # 初期保険金額
# 残存表の作成
lx = [l0] # 保有保険金額
dx = [] # 死亡保険金額
wx = [] # 解約保険金額
# 生命表の作成
for t in range(c_period):
q = qx[sex][age + t]
w = qwx[t]
next_d = lx[-1] * q * k
next_w = lx[-1] * w
next_l = lx[-1] - next_d - next_w
lx.append(next_l)
dx.append(next_d)
wx.append(next_w)
# 保険収支の項目
inprem = [] # 保険料収入
interest =[] # 利息収入
benefit = [] # 保険金支払い
surrender = [] # 解約返戻金支払い
expenses = [] # 事業費
reserve = [] # 保険料積立金繰入
profit = [] # 利益
P = float(PremT(sex, age, term))
# 保険収支の計算
for t in range(0, c_period):
if t < parse_term(term, age):
inprem.append(lx[t] * P) # 保険料の収入
Vt = float(ResT(sex, age, term, t)) # 期始保険料積立金
Vt1 = float(ResT(sex, age, term, t + 1)) # 期末保険料積立金
interest.append((lx[t + 1] * Vt1 + lx[t] * Vt) * 0.006 / (2 + 0.006)) # ハーディの公式
benefit.append(dx[t]) # 死亡保険金の支払い
W = float(SVT(sex, age, term, t + 1))
surrender.append(wx[t] * W) # 解約返戻金の支払い
expenses.append(inprem[t] * 0.4) # 事業費の支払い
# 保険料積立金繰入
if t == 0:
reserve.append(lx[1] * Vt1)
else:
reserve.append(lx[t + 1] * Vt1 - lx[t] * Vt)
# 保険収支の計算
profit.append(inprem[t] + interest[t] - benefit[t] \
- surrender[t] - expenses[t] - reserve[t])
else:
inprem.append(0)
interest.append(0)
benefit.append(0)
surrender.append(0)
expenses.append(0)
reserve.append(0)
profit.append(0)
ここまでは前回までと同じで、
先に作ったリストへ結果を格納します。
results.append({"t":t, "inprem":int(inprem[t]),
"interest":int(interest[t]),
"benefit":int(benefit[t]),
"surrender":int(surrender[t]),
"expenses":int(expenses[t]),
"reserve":int(reserve[t]),
"profit":int(profit[t])
})
続いて、pandasを使って結果をExcelファイルへ出力します。
result_df = pd.DataFrame(results)
grouped = result_df.groupby("t").sum()
summary = grouped.reset_index()
summary.to_excel("term_result.xlsx", index=False)
pd.DataFrame(results)で結果のリストresultsを
2次元のデータ構造へ変換します。
次の行はgroupby("t")でtを基準にsum()で合計しています。
これで契約内容のキャッシュフローが合計されます。
ただ、そのままだとtがインデックス(Excelでいうと行数)に
なってしまうので、reset_index()でtを元に戻しています。
最後にその結果summaryをterm_result.xlsxとして出力しています。
そのまま出力すると、データフレームの行番号と列番号も出力されてしまうので、
index=Falseで出力しないようにします。
まとめ
今回は、定期保険の保険収支計算について、
これまでコード内で直接定義していた契約データを、
Excelファイルから読み込む形に変更し、
さらに計算結果をExcelへ出力する処理を実装しました。
これを応用することで、
実務ではシステムから出力された契約データを取り込んで計算を行い、
結果を再び外部に出力し、Excelでグラフ化といったことが可能です。
また、契約ごとの収支は保持したまま、集計処理を行うことで、
全体の収支をさまざまな切り口で集計することも可能です。
この辺は次回以降で紹介したいと思います。
◀ 前の記事
利源分析
▶ 次の記事
実務的な小ネタ
📚 目次
アクチュアリーのためのPython入門
