Skip to the content.

OpenFiscaについて

OpenFiscaとは

概要

Rule as Codeとは

特徴

利点

欠点

主要概念

Tips

テスト

# 単数世帯の場合
- name: 配偶者控除1
  period: 2023-06-01
  input:
    世帯:
      親一覧:
        - 親1
        - 配偶者1
    世帯員:
      親1:
        所得:
          '2023-06-01': 9000000
      配偶者1:
        所得:
          '2023-06-01': 480000
  output:
    世帯:
      配偶者控除:
        '2023-06-01': 380000
# 複数世帯の場合(input.世帯一覧.世帯N, output.世帯一覧.世帯Nの配下に記述)
- name: 配偶者所得(複数世帯)
  period: 2023-06-01
  input:
    世帯一覧:
      世帯1:
        親一覧:
          - 親1
          - 配偶者1
      世帯2:
        親一覧:
          - 親2
          - 配偶者2
    世帯員:
      親1:
        所得:
          '2023-06-01': 9500000
      配偶者1:
        所得:
          '2023-06-01': 480000
      親2:
        所得:
          '2023-06-01': 9000000
        誕生年月日: '1953-05-01'
      配偶者2:
        誕生年月日: '1953-05-01'
        所得:
          '2023-06-01': 480000
  output:
    世帯一覧:
      世帯1:
        配偶者控除:
          '2023-06-01': 260000
      世帯2:
        配偶者控除:
          '2023-06-01': 480000

計算ロジック

Variables

Period

Enum

Entities

複数世帯に対応した実装方法

if文を使用しない
# before
if 居住都道府県 != "東京都":
    return 0
# ...
# after
居住地条件 =  居住都道府県 == "東京都"
# ...
return 居住地条件 * 金額
本人の控除 = np.select(
    [障害者控除対象, 特別障害者控除対象], # 条件一覧
    [parameters(対象期間).所得.障害者控除額, parameters(対象期間).所得.特別障害者控除額], # 条件を満たした場合の出力一覧
    0) # デフォルト値
値の集計、加工には numpy 関数ではなくOpenFiscaのメソッドを使う
or の代わりに +and の代わりに * を使用する
csvファイルの読み込みには np.genfromtxt を使用する
,公立,国立,私立
全日制課程,9900,9600,9900
定時制課程,2700,9600,9900
通信制課程,520,9600,9900
# csvファイル読み込み
@cache
def 支給限度額_学年制表():
    return np.genfromtxt("openfisca_japan/assets/福祉/育児/高等学校等就学支援金/支給額/支給限度額_学年制.csv",
                         delimiter=",", skip_header=1, dtype="int64")[:, 1:] # ヘッダーを読み込まないようインデックスは1始まり
# variable内での参照

# 行名をインデックスに変換(0始まりなので注意)
高校履修種別インデックス = np.select(
    [高校履修種別 == 高校履修種別パターン.全日制課程,
     高校履修種別 == 高校履修種別パターン.定時制課程,
     高校履修種別 == 高校履修種別パターン.通信制課程],
    list(range(3)),
    # NOTE: デフォルト値を-1にすることでindex out of boundエラー防止(条件に当てはまらない入力が来ても必ず最後の要素が取得される)
    -1).astype(int)

# 列名をインデックスに変換(0始まりなので注意)
高校運営種別インデックス = np.select(
    [高校運営種別 == 高校運営種別パターン.公立,
     高校運営種別 == 高校運営種別パターン.国立,
     高校運営種別 == 高校運営種別パターン.私立],
    list(range(3)),
    -1).astype(int)

支給金額 = 支給限度額_学年制表()[高校履修種別インデックス, 高校運営種別インデックス]

# NOTE: out of bound対策として条件外の場合も支給金額が取得できてしまう(誤った値)ため、改めて条件を満たすかどうか確認
支給対象者である = 高校生である * (高校履修種別 != 高校履修種別パターン.) * (高校運営種別 != 高校運営種別パターン.)
return 支給対象者である * 支給金額
世帯員をソートしたい場合(「第一子の○○」、「最も所得が多い世帯員」) get_rank を使用する
子供である = 対象人物.has_role(世帯.)
# condition「子供である」を満たす範囲内で、各世帯員を `-年齢` でソートすると何番目にあたるかを取得 (年齢が高い順に0, 1, 2,...)
# 条件を満たさない場合 `-1` となる
子供の年齢降順インデックス = 対象人物.get_rank(対象人物.世帯, -年齢, condition=子供である)

# 第一子は「子供である」かつ「子供の年齢降順インデックス」のソート順の最初(0始まりのため0番目)となるため、以下で取得可能
第一子である = 子供の年齢降順インデックス == 0
# 以下この条件を金額や他の条件と掛け合わせることで、第一子に関する計算が可能

API