Open SnoozingJellyfish opened 1 year ago
value_nth_person
にsort機能はありませんが、「第n子のインデックス取得 get_rank
」→「インデックスに対応する値取得 value_nth_person
」と組み合わせることで第n子の値を抽出できるかもしれません。
https://github.com/openfisca/openfisca-core/blob/05980c4bcd44f70485a35855ec5b887abe4bba33/openfisca_core/populations/group_population.py#L269 使い方: https://github.com/openfisca/openfisca-core/blob/05980c4bcd44f70485a35855ec5b887abe4bba33/tests/core/test_entities.py#L324
yamlファイルを使ったOpenFiscaのテストでは複数世帯のinputに対応していなさそうですが、調べ切れてはいません。
entities.pyで、世帯の複数形を「世帯一覧」という別の名前にすることでテスト可能になりました。(少しまとめてPR化します)
条件式による判定も、複数世帯の場合次元が変わってしまい計算できなくなってしまいました。こちらも対応が必要そうです。
if 居住都道府県 != "東京都":
return 0
FAILED openfisca_japan/tests/東京都/福祉/重度心身障害者手当.yaml:: - ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
条件式による判定
判定式のうち、out of boundsを回避するための早期リターンを兼ねている箇所は置き換えられませんでした。
解決策はまだ思いついていません。(あったとしても設計を根本から変える必要がありそうです)
複数世帯入力に対するメソッドの返り値
世帯1
が太郎
(所得: 10000円), 花子
(所得: 20000円), 世帯2
がTom
(所得: 1000円)の例で考えます。
所得一覧 = 対象世帯.members("所得", 対象期間)
のように世帯員ごとの変数を取得するメソッドの返り値は、ndarray([10000, 20000, 1000])
と全世帯員の値が格納された1次元のndarrayになります。対象世帯.max(所得一覧, 対象期間)
のように世帯ごとの変数を取得するメソッドの返り値は、ndarray([20000, 1000])
と世帯ごとの値が格納された1次元のndarrayになります。複数世帯テストのフォーマット 世帯員のフォーマットは単数世帯と同じで、世帯のフォーマットのみ以下のようにする。
input:
世帯一覧:
世帯1:
自分一覧:
....
output:
世帯一覧:
自分一覧:
....
csvファイルの読み込みは表のヘッダー行・列を除いた中身のみndarrayとして読み込む。
ヘッダーを除いた時に1行(1次元配列)になる場合は、np.newaxisで2次元配列にしていますが、
そうならない場合は :
で2次元配列を保つ必要があります。
# 配偶者控除額表[配偶者の所得区分, 納税者本人の所得区分] の形で参照可能
配偶者控除額表 = np.genfromtxt('openfisca_japan/assets/所得/配偶者控除額.csv',
delimiter=',', skip_header=1, dtype='int64')[np.newaxis, 1:] # 1列目はスライスで除外する
if分岐は用いず、世帯・世帯員ごとのbool値のndarrayにして、掛け算を行う。 if分岐の早期リターンは世帯ごとのboolにして最後に掛け算する。
世帯員は世帯ごとに1人以上存在するため、min, max が例外を吐くことは無い
np.selectでcsvを読み込んだndarrayの行・列を選択する場合はインデックスを選択する。デフォルトを-1
にしておけば、あとで一致判定によりFalseにして、掛け算により0を返すことができる。
納税者の所得区分 = np.select(
[納税者の所得 <= 9000000, (納税者の所得 > 9000000) * (納税者の所得 <= 9500000), (納税者の所得 > 9500000) * (納税者の所得 <= 10000000)], # 複数世帯のarrayのためand, orの代わりに *. +
[0, 1, 2],
-1).astype(int)
and
, or
ではなく*
, +
を用いることで、複数世帯のndarrayに対して一括計算ができる。(and
, or
ではエラーになる。) True
, False
は 0
, 1
と等価のため、掛け算によりFalse
の場合は 0
にできる。
*and
, or
と`,
+は演算子の優先順位が異なるため、必要に応じてかっこを用いる。** (例)
A > B and C < Dであれば
(A > B) and (C < D)だが、
andをそのまま
に置き換えた
A > B C < Dは
A > (B C) < Dになるため、
(A > B) (C < D)`と明示的にかっこでくくる必要がある。
value_nth_person
にsort機能はありませんが、「第n子のインデックス取得get_rank
」→「インデックスに対応する値取得value_nth_person
」と組み合わせることで第n子の値を抽出できるかもしれません。https://github.com/openfisca/openfisca-core/blob/05980c4bcd44f70485a35855ec5b887abe4bba33/openfisca_core/populations/group_population.py#L269 使い方: https://github.com/openfisca/openfisca-core/blob/05980c4bcd44f70485a35855ec5b887abe4bba33/tests/core/test_entities.py#L324
上記情報をもとに、複数世帯の場合の第n子判別方法を検討しました。(情報とても助かりました!) 以下の世帯のとき、
世帯1:
自分一覧:
- 親1
配偶者一覧:
- 配偶者1
子一覧:
- 子1_1 # 小3
- 子1_2 # 小1
世帯2:
自分一覧:
- 親2
配偶者一覧:
- 配偶者2
子一覧:
- 子2 # 小2
子である = 対象世帯.has_role(世帯.子)
子の学年降順 = 対象世帯.get_rank(対象世帯, - 学年, condition=子である)
# 子の学年降順: [-1 -1 0 1 -1 -1 0]
児童手当から実装修正してみます。
@SnoozingJellyfish
児童手当から実装修正してみます。
よろしくお願いします!
実装にあたり、もしかしたら 高等学校奨学給付金
のテストが落ちてしまい修正が必要になるかもしれません...
(私も複数世帯化を試してみようとした際に上記の問題にはまってしまいました...原因は調査中ですが、非課税世帯の計算で依存しているため影響していそうです)
問題が起きなかった際はこのコメントは気にしないでください :bow:
高等学校奨学給付金 のテストが落ちてしまい修正が必要になるかもしれません
調査も兼ねてこちらの複数世帯化は別PRで進めています。
生活保護の複数世帯化着手したいと思います。
生活福祉資金貸付制度の複数世帯化着手します。
入学、就学関連制度(受験生チャレンジ支援貸付
, 高等学校等就学支援金
)の複数世帯化着手します。
生活福祉資金貸付制度、入学、就学関連制度対応済み
続いて児童扶養手当着手します。
残りの3制度は軽微な修正で済みそうなので、まとめて対処したいと思います。
政策シミュレータアプリ用に、複数世帯の情報をOpenFiscaで処理できるようにする必要があります。 OpenFiscaバックエンドに複数世帯の情報をPOSTすると、それぞれの世帯での結果が算出されます。 (POST方法:
世帯員
に全ての世帯の構成員を並列に記載する。世帯
以下に各世帯(世帯1, 世帯2等)を記載する)yamlファイルを使ったOpenFiscaのテストでは複数世帯のinputに対応していなさそうですが、調べ切れてはいません。
OpenFiscaで複数世帯を同時処理するにあたって、numpyの関数を直接使用している箇所の実装の修正が必要です。
対象世帯.members
で取得したndarrayは、全世帯の構成員情報が格納された1次元arrayになっています。(対象世帯という名前がミスリーディングですが、、) その後に対象世帯.method(array)
とすると、世帯ごとに世帯員を抽出した上でmethodが実行されます。 一方、np.max(array)
のようにすると、全世帯の世帯員に対してmethodが実行されてしまいます。 そのため、numpyのメソッドをそのまま使うのではなく、OpenFiscaのgroup entityクラスのメソッドを使用する必要があります。 OpenFiscaのgroup entityクラスのメソッドにmax
やsum
はありますが、argsort等はないかもしれないので、value_nth_person
などを使うか、もし難しければフロントエンドでsortしてからPOSTするといった工夫が必要かもしれません。対象世帯
のvariableは世帯数分の長さのarrayが返ってくるため、それらに対してand
やor
が使えず、+
,-
に置き換える必要があります。