0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

アクチュアリーのためのPython入門(pandasを使ったExcelとの連携)

0
Last updated at Posted at 2026-03-20

アクチュアリーのためのPython入門(第18回)

pandasを使った外部ファイルの取り込み

📚 アクチュアリーのためのPython入門
この記事は入門編の一部です。
目次はこちら

はじめに

前回までに、保険収支感応度分析利源分析を行いました。

これで基本的な保険数理はできたのですが、
Pythonを使って、実務で使いやすく、また効率化をしていきます。
今回は、一般のPython入門でも取り上げられるpandasを使います。

pandasは外部ファイルを簡単に取り込めるようにするライブラリで、
特にCSVファイルやExcelファイルの取り込みを容易にします。

実務に近い形として、

  • 契約ポートフォリオをExcelから読み込む
  • 契約単位で保険収支を計算する
  • ポートフォリオ全体の収支を集計する
  • 結果をExcelへ出力する

という流れをpandasを用いて実装します。

前回までは、コード内に契約情報を入れていましたが、
これを外部のExcelファイルにし、
出力もPythonのprintではなく、Excelファイルにします。

pandasを使用する準備

まず、次のライブラリをインストールする必要があります。

  • pandas 今回使用するライブラリ
  • openpyxl Excel(.xlsx)が読み込むためのライブラリ

これらのインストール方法については、
Pythonの環境によって異なりますし、
本筋から外れてしまいますので、
ここでは省略させてください。
「pandas python インストール」などで検索すれば、
解説しているサイトが探せると思います。

計算の前提

前回と同じように定期保険のファイルterm.pyを使用し、
以下の関数は同ファイルまたはimportされている前提とします。

  • PremT :保険料の計算
  • netPremT :純保険料の計算
  • ResT :保険料積立金の計算
  • SVT :解約返戻金の計算

また、term.pyが置いてある場所に、
Excelファイルをcontr_term.xlsxを作成し、次の契約内容とします。

image.png

保険収支のコード

続いて、term.pyのコードに入ります。
保険収支のコード書き換えます。

term.py
from core import *
import pandas as pd

まず、from core import *は以前までと同じく、
core.pyの死亡率や生命表、給付現価を読み込みます。
import pandas as pdpandasのライブラリを読み込み、
使用名をpdとしています。使用名は任意です。

term.py
# アサンプションの設定
c_period = 10  # 計算する期間
k = 0.7        # 死亡指数
qwx = [0.02] * c_period    # 解約率

# 結果を入れるリスト
results =[]

アサンプション部分は前回と同じです。
結果を入れるリストを作成しておきます。

続いて、今回のポイントのExcelファイルの読み込みです。

term.py
# 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埋めしていたり、
見えない浮動小数点があったりするための対応です。

次のコードです。
保険金額の初期値を設定したら、
あとは、前回までと同じです。

term.py
    # 保険収支の計算
    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)

ここまでは前回までと同じで、
先に作ったリストへ結果を格納します。

term.py
        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ファイルへ出力します。

term.py
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を元に戻しています。

最後にその結果summaryterm_result.xlsxとして出力しています。
そのまま出力すると、データフレームの行番号と列番号も出力されてしまうので、
index=Falseで出力しないようにします。

結果のファイルはterm.pyと同じ場所にできています。
image.png

まとめ

今回は、定期保険の保険収支計算について、
これまでコード内で直接定義していた契約データを、
Excelファイルから読み込む形に変更し、
さらに計算結果をExcelへ出力する処理を実装しました。

これを応用することで、
実務ではシステムから出力された契約データを取り込んで計算を行い、
結果を再び外部に出力し、Excelでグラフ化といったことが可能です。

また、契約ごとの収支は保持したまま、集計処理を行うことで、
全体の収支をさまざまな切り口で集計することも可能です。
この辺は次回以降で紹介したいと思います。

前の記事
利源分析

次の記事
実務的な小ネタ

📚 目次
アクチュアリーのためのPython入門

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?