Plot

import numpy as np
import pandas as pd
from leximpact_aggregates.aggregate import AggregateManager, DataStructure
from leximpact_common_python_libraries.csg_simu import compute_quantile

from leximpact_prepare_data.plot import in_euros, plot_distribution
from leximpact_common_python_libraries.config import Configuration

config = Configuration(project_folder="leximpact-prepare-data")
[leximpact_socio-fisca-simu-etat DEBUG @ 10:35:15] Connecting to Redis None:6379
[leximpact_socio-fisca-simu-etat WARNING @ 10:35:15] Unable to connect to Redis cache : Error 111 connecting to None:6379. Connection refused.
/home/jupyter-benoit/leximpact-prepare-data/.venv/lib/python3.8/site-packages/leximpact_socio_fisca_simu_etat/csg_simu.py:139: FutureWarning: The default value of numeric_only in DataFrameGroupBy.sum is deprecated. In a future version, numeric_only will default to False. Either specify numeric_only or select only columns which should be valid for the function.
  sample_foyers_fiscaux = sample_individus.groupby(
pd.options.display.float_format = "{:,.2f}".format
aggregates_path = config.get("AGREGATS_PATH")
from IPython.core.interactiveshell import InteractiveShell

InteractiveShell.ast_node_interactivity = "all"

Distribution

POTE 2020

year = "2020"
aggm_c = AggregateManager(aggregates_path=aggregates_path)
aggm_c.load_aggregate("POTE", "rfr", year=str(year))
for d in aggm_c.aggregate.data:
    if d.data_structure == DataStructure.CENTILE and d.date == "2020":
        df_centile_rfr_2020 = pd.DataFrame(d.values)
        break
aggm_c.load_aggregate("POTE", "rfr", year="2019")
for d in aggm_c.aggregate.data:
    if d.data_structure == DataStructure.CENTILE and d.date == "2019":
        df_centile_2019 = pd.DataFrame(d.values)
        break
else:
    raise Exception()

year = "2020"
aggm_c.load_aggregate(
    "POTE", "rfr", year=str(year), data_structure=DataStructure.DECILE
)
for d in aggm_c.aggregate.data:
    if d.data_structure == DataStructure.DECILE and d.date == year:
        df_decile_rfr_2020 = pd.DataFrame(d.values)
        break
else:
    raise Exception()
df_decile_rfr_2020
quantile_index lower_bound upper_bound bucket_count bucket_sum bucket_mean bucket_stdev
0 0 0.00 2,264.00 3981822 1,069,235,083.00 268.53 569.38
1 1 2,264.00 8,816.00 3981823 23,667,669,211.00 5,943.93 1,826.41
2 2 8,816.00 12,854.00 3981823 43,576,621,785.00 10,943.89 1,150.43
3 3 12,854.00 16,199.00 3981822 58,390,804,988.00 14,664.34 927.05
4 4 16,199.00 19,450.00 3981823 70,800,632,956.00 17,780.96 935.29
5 5 19,450.00 23,865.00 3981823 85,383,203,814.00 21,443.24 1,239.14
6 6 23,865.00 30,112.00 3981822 107,325,704,831.00 26,953.92 1,746.79
7 7 30,112.00 38,713.00 3981823 135,809,071,429.00 34,107.26 2,464.09
8 8 38,713.00 54,548.00 3981823 181,489,645,465.00 45,579.54 4,501.04
9 9 54,548.00 144,609,869.00 3981823 396,160,978,027.00 99,492.36 273,769.98

Base PLF2022

!ls /mnt/data-out/leximpact/erfs-fpr/base_2021/prod
erfs_final_ind_2018_aged_to_2021_N_3.h5
erfs_final_ind_2018_aged_to_2021_N_3_Old.h5
base_plf2022 = pd.read_hdf(
    "/mnt/data-out/leximpact/erfs-fpr/base_2021/prod/erfs_final_ind_2018_aged_to_2021_N_3_Old.h5"
)
base_plf2022 = base_plf2022.query("quifoy == 0")
base_plf2022["rfr_wprm"] = base_plf2022["rfr"] * base_plf2022["wprm"]
# filter_by
in_euros(base_plf2022["rfr_wprm"].sum())
# base_plf2022
'992 Mds €'

Base PLF2023

base_ind_plf2023 = pd.read_hdf(
    "/mnt/data-out/leximpact/pipeline_2022/base_ERFS2018_POTE2019_ind_2022_20221220-101745.h5"
)
base_ind_plf2023 = base_ind_plf2023.query("quifoy == 0")
base_ind_plf2023["wprm"] = base_ind_plf2023["weight_foyers"]
base_ind_plf2023["rfr_wprm"] = base_ind_plf2023["rfr"] * base_ind_plf2023["wprm"]
# filter_by
in_euros(base_ind_plf2023["rfr_wprm"].sum())
len(base_ind_plf2023)
'1 101 Mds €'
56935

Décile de RFR de la base PLF2023

resultat_quantile_test = compute_quantile(
    base_ind_plf2023, ["rfr"], ["rfr_wprm"], do_rounddown=False
)
df_decile_plf2023 = pd.DataFrame(resultat_quantile_test)
df_decile_plf2023.rename(
    columns={"rfr": "rfr_upper_bound", "rfr_wprm": "rfr_sum"}, inplace=True
)

Ecart des frontières de décile

df_decile_plf2023["quantile_index"] = (df_decile_plf2023.fraction * 10).astype(int)
df_bound_diff = df_decile_rfr_2020.merge(df_decile_plf2023, on="quantile_index")
df_bound_diff["diff_upper_bound"] = (
    df_bound_diff.upper_bound - df_bound_diff.rfr_upper_bound
)
df_bound_diff["diff_upper_bound_pct"] = (
    df_bound_diff.diff_upper_bound / df_bound_diff.upper_bound * 100
)
df_bound_diff
quantile_index lower_bound upper_bound bucket_count bucket_sum bucket_mean bucket_stdev fraction count rfr_upper_bound rfr_sum diff_upper_bound diff_upper_bound_pct
0 1 2,264.00 8,816.00 3981823 23,667,669,211.00 5,943.93 1,826.41 0.10 3,978,622.50 0.00 0.00 8,816.00 100.00
1 2 8,816.00 12,854.00 3981823 43,576,621,785.00 10,943.89 1,150.43 0.20 4,052,188.25 7,533.26 16,422,077,988,864.00 5,320.74 41.39
2 3 12,854.00 16,199.00 3981822 58,390,804,988.00 14,664.34 927.05 0.30 3,993,638.00 12,726.58 42,116,109,565,952.00 3,472.42 21.44
3 4 16,199.00 19,450.00 3981823 70,800,632,956.00 17,780.96 935.29 0.40 4,023,054.25 17,209.17 64,863,875,366,912.00 2,240.83 11.52
4 5 19,450.00 23,865.00 3981823 85,383,203,814.00 21,443.24 1,239.14 0.50 4,036,376.25 21,101.08 84,297,599,942,656.00 2,763.92 11.58
5 6 23,865.00 30,112.00 3981822 107,325,704,831.00 26,953.92 1,746.79 0.60 4,094,012.75 26,040.24 110,639,213,182,976.00 4,071.76 13.52
6 7 30,112.00 38,713.00 3981823 135,809,071,429.00 34,107.26 2,464.09 0.70 3,971,741.00 32,305.08 116,012,485,705,728.00 6,407.92 16.55
7 8 38,713.00 54,548.00 3981823 181,489,645,465.00 45,579.54 4,501.04 0.80 4,031,783.50 40,420.87 161,793,464,860,672.00 14,127.13 25.90
8 9 54,548.00 144,609,869.00 3981823 396,160,978,027.00 99,492.36 273,769.98 0.90 4,025,537.00 54,368.48 200,456,206,811,136.00 144,555,500.52 99.96
df_bound_diff[["upper_bound", "rfr_upper_bound"]].iloc[:-1].plot(
    title="Frontière haute sans le dernier décile"
)

# TODO: Lire la base france data et calculer le RFR ?
# base_ind_plf2023_france_data = pd.read_hdf(
#     "/mnt/data-out/leximpact/erfs-fpr/input-2022-09-19_branche_update_off.h5", key="individu_2018"
# )
def get_rfr(row, base_ind):
    row["lower_bound"]
    row["upper_bound"]
    df = base_ind.query("@inf <= rfr < @supp")
    row["rfr_lex_sum"] = df["rfr_wprm"].sum()
    if df["wprm"].sum() > 0:
        row["rfr_lex_mean"] = df["rfr_wprm"].sum() / df["wprm"].sum()
    row["rfr_lex_count_sample"] = len(df)
    row["rfr_lex_count"] = df["wprm"].sum()
    return row


df_centile_base_lex_plf2022 = df_centile_rfr_2020.apply(
    get_rfr, base_ind=base_plf2022, axis=1
).copy()
print(
    f"Somme des RFR de la base centile PLF 2022 : {in_euros(df_centile_base_lex_plf2022['rfr_lex_sum'].sum())}"
)
df_decile_base_lex_plf2022 = df_decile_rfr_2020.apply(
    get_rfr, base_ind=base_plf2022, axis=1
).copy()
print(
    f"Somme des RFR de la base décile PLF 2022 : {in_euros(df_decile_base_lex_plf2022['rfr_lex_sum'].sum())}"
)
df_centile_base_lex_plf2023 = df_centile_rfr_2020.apply(
    get_rfr, base_ind=base_ind_plf2023, axis=1
).copy()
print(
    f"Somme des RFR de la base centile PLF 2023 : {in_euros(df_centile_base_lex_plf2023['rfr_lex_sum'].sum())}"
)
df_decile_base_lex_plf2023 = df_decile_rfr_2020.apply(
    get_rfr, base_ind=base_ind_plf2023, axis=1
).copy()
print(
    f"Somme des RFR de la base décile PLF 2023 : {in_euros(df_decile_base_lex_plf2023['rfr_lex_sum'].sum())}"
)
Somme des RFR de la base centile PLF 2022 : 992 Mds €
Somme des RFR de la base décile PLF 2022 : 992 Mds €
Somme des RFR de la base centile PLF 2023 : 1 101 Mds €
Somme des RFR de la base décile PLF 2023 : 1 101 Mds €
df_decile_base_lex_plf2022.lower_bound.to_list()
df_decile_base_lex_plf2023
[0.0,
 2264.0,
 8816.0,
 12854.0,
 16199.0,
 19450.0,
 23865.0,
 30112.0,
 38713.0,
 54548.0]
quantile_index lower_bound upper_bound bucket_count bucket_sum bucket_mean bucket_stdev rfr_lex_sum rfr_lex_mean rfr_lex_count_sample rfr_lex_count
0 0.00 0.00 2,264.00 3,981,822.00 1,069,235,083.00 268.53 569.38 1,100,346,752.00 205.18 7,631.00 5,362,759.00
1 1.00 2,264.00 8,816.00 3,981,823.00 23,667,669,211.00 5,943.93 1,826.41 20,231,571,456.00 5,841.10 4,897.00 3,463,657.00
2 2.00 8,816.00 12,854.00 3,981,823.00 43,576,621,785.00 10,943.89 1,150.43 37,150,617,600.00 11,013.40 4,790.00 3,373,219.00
3 3.00 12,854.00 16,199.00 3,981,822.00 58,390,804,988.00 14,664.34 927.05 40,729,108,480.00 14,608.43 3,967.00 2,788,054.50
4 4.00 16,199.00 19,450.00 3,981,823.00 70,800,632,956.00 17,780.96 935.29 62,209,150,976.00 17,851.86 4,883.00 3,484,743.00
5 5.00 19,450.00 23,865.00 3,981,823.00 85,383,203,814.00 21,443.24 1,239.14 88,530,632,704.00 21,592.07 5,788.00 4,100,146.50
6 6.00 23,865.00 30,112.00 3,981,822.00 107,325,704,831.00 26,953.92 1,746.79 113,460,436,992.00 26,848.62 5,960.00 4,225,932.50
7 7.00 30,112.00 38,713.00 3,981,823.00 135,809,071,429.00 34,107.26 2,464.09 157,940,744,192.00 34,141.69 6,597.00 4,626,038.00
8 8.00 38,713.00 54,548.00 3,981,823.00 181,489,645,465.00 45,579.54 4,501.04 218,267,910,144.00 45,412.88 6,764.00 4,806,300.00
9 9.00 54,548.00 144,609,869.00 3,981,823.00 396,160,978,027.00 99,492.36 273,769.98 361,383,165,952.00 89,018.82 5,658.00 4,059,626.50
df_decile_base_lex_plf2023.rfr_lex_count.sum()
40290476.0

Calcul différence

for op in ["sum", "mean", "count"]:
    df_centile_base_lex_plf2022["diff_" + op] = (
        df_centile_base_lex_plf2022["bucket_" + op]
        - df_centile_base_lex_plf2022["rfr_lex_" + op]
    )
    df_decile_base_lex_plf2022["diff_" + op] = (
        df_decile_base_lex_plf2022["bucket_" + op]
        - df_decile_base_lex_plf2022["rfr_lex_" + op]
    )
    df_decile_base_lex_plf2022["ratio_diff_" + op] = (
        df_centile_base_lex_plf2022["diff_" + op]
        / df_decile_base_lex_plf2022["bucket_" + op]
    ) * 100
df_decile_base_lex_plf2022
quantile_index lower_bound upper_bound bucket_count bucket_sum bucket_mean bucket_stdev rfr_lex_sum rfr_lex_mean rfr_lex_count_sample rfr_lex_count diff_sum ratio_diff_sum diff_mean ratio_diff_mean diff_count ratio_diff_count
0 0.00 0.00 2,264.00 3,981,822.00 1,069,235,083.00 268.53 569.38 1,093,492,343.50 299.61 21,616.00 3,649,729.38 -24,257,260.50 0.00 -31.08 NaN 332,092.62 10.00
1 1.00 2,264.00 8,816.00 3,981,823.00 23,667,669,211.00 5,943.93 1,826.41 19,163,117,180.62 5,935.38 16,078.00 3,228,627.02 4,504,552,030.38 0.00 8.55 NaN 753,195.98 10.00
2 2.00 8,816.00 12,854.00 3,981,823.00 43,576,621,785.00 10,943.89 1,150.43 31,119,749,132.02 10,932.85 13,883.00 2,846,443.97 12,456,872,652.98 0.00 11.04 NaN 1,135,379.03 10.00
3 3.00 12,854.00 16,199.00 3,981,822.00 58,390,804,988.00 14,664.34 927.05 39,037,894,350.55 14,728.44 13,024.00 2,650,511.49 19,352,910,637.45 0.00 -64.09 NaN 1,331,310.51 10.00
4 4.00 16,199.00 19,450.00 3,981,823.00 70,800,632,956.00 17,780.96 935.29 51,632,236,683.46 17,824.56 14,044.00 2,896,690.55 19,168,396,272.54 0.00 -43.60 NaN 1,085,132.45 10.00
5 5.00 19,450.00 23,865.00 3,981,823.00 85,383,203,814.00 21,443.24 1,239.14 72,180,426,554.86 21,472.10 16,742.00 3,361,591.71 13,202,777,259.14 0.00 -28.85 NaN 620,231.29 10.00
6 6.00 23,865.00 30,112.00 3,981,822.00 107,325,704,831.00 26,953.92 1,746.79 98,319,518,361.53 26,874.02 18,140.00 3,658,534.68 9,006,186,469.47 0.00 79.90 NaN 323,287.32 10.00
7 7.00 30,112.00 38,713.00 3,981,823.00 135,809,071,429.00 34,107.26 2,464.09 146,201,533,593.30 34,322.39 21,270.00 4,259,655.19 -10,392,462,164.30 -0.05 -215.13 0.19 -277,832.19 -59.87
8 8.00 38,713.00 54,548.00 3,981,823.00 181,489,645,465.00 45,579.54 4,501.04 178,542,188,586.82 45,749.46 19,057.00 3,902,607.98 2,947,456,878.18 -0.06 -169.92 0.02 79,215.02 -3.51
9 9.00 54,548.00 144,609,869.00 3,981,823.00 396,160,978,027.00 99,492.36 273,769.98 355,089,378,584.62 103,524.69 16,936.00 3,429,997.00 41,071,599,442.38 0.04 -4,032.33 0.09 551,826.00 1.72

Début bidouille

base_ind_plf2023.query("idfoy == 1172")[["rfr"]]
rfr
2368 1.08
list_id = base_ind_plf2023.iloc[2:10]["foyer_fiscal_id"].to_list()
list_id
base_ind_plf2023["foyer_fiscal_id"].isin(list_id)
[17302, 48076, 4353, 17262, 48111, 17275, 48102, 17290]
74620     False
94892     False
33997      True
94814      True
8504       True
          ...  
1566      False
85645     False
84616     False
102847    False
50247     False
Name: foyer_fiscal_id, Length: 56935, dtype: bool
base_ind_plf2023.loc[base_ind_plf2023["foyer_fiscal_id"].isin(list_id), "decile"] = "15"
base_ind_plf2023.query("foyer_fiscal_id==17302")
quifoy crds_retraite ric statut_marital foyer_fiscal_id crds_non_salarie csg_imposable_retraite csg_deductible_chomage autonomie_financiere heures_remunerees_volume ... revenus_capitaux_prelevement_liberatoire revenus_capitaux_prelevement_bareme menage_ordinaire weight_menages wprm_init wprm rfr_wprm rfr_wprm_wprm new_temp_column_to_compute_qsgf654e6gq decile
33997 0 0.00 0.00 3 17302 0.00 0.00 0.00 False 0.00 ... 0.00 0.00 1 0.00 0.00 793.95 0.00 0.00 0.00 15

1 rows × 73 columns

def create_dict_decile(base_ind):
    """
    Retourne un dictionnaire pour chaque décile de la base de données d'entrée.
    """
    deciles_plf2023 = {}
    base_ind.sort_values("rfr", inplace=True)
    base_ind.weight_foyers.sum()
    nb_lignes = len(base_ind)
    # quantile_fraction = [(1 / nb_quantiles) * (i + 1) for i in range(nb_quantiles)]
    for num_decile in range(1, 10 + 1):
        # ATTENTION TODO : On ne tient pas compte des poids !!!
        # Pour l'ERFS-FPR ça n'a pas l'air trop gênant mais théoriquement ce n'est pas ça du tout !
        # Il faudrait sommer ligne à ligne le poids pour atteindre 1/10 du total des poids.
        lower_indice = int((num_decile - 1) / 10 * nb_lignes)
        upper_indice = int((num_decile / 10) * nb_lignes)
        # print(f'{lower_indice} {upper_indice}')

        list_id = base_ind.iloc[lower_indice:upper_indice]["foyer_fiscal_id"].to_list()
        base_ind.loc[base_ind["foyer_fiscal_id"].isin(list_id), "decile"] = num_decile

        df = base_ind.iloc[lower_indice:upper_indice].copy()
        deciles_plf2023[num_decile] = {
            "data": df,
            "count": len(df),
            "poids_decile": df.weight_foyers.sum(),
            "rfr_min": df.rfr.min(),
            "rfr_max": df.rfr.max(),
            "rfr_sum": (df.rfr * df.weight_foyers).sum(),
            "rfr_mean": (df.rfr * df.weight_foyers).sum() / df.weight_foyers.sum(),
        }
        # print(deciles_plf2023[num_decile]["rfr_sum"])
    return deciles_plf2023


def verif_decile(deciles_dict):
    for k, v in deciles_dict.items():
        df = df_decile_rfr_2020.iloc[k - 1]
        print(
            f'Décile {k} rfr_min={in_euros(df["lower_bound"])} vs {in_euros(v["rfr_min"])} rfr_max={in_euros(df["upper_bound"])} vs {in_euros(v["rfr_max"])}'
        )
        print(
            f'rfr_sum={in_euros(df["bucket_sum"])} vs {in_euros(v["rfr_sum"])} poids_decile={in_euros(v["poids_decile"])}'
        )

        # df
        if df["lower_bound"] > v["rfr_min"]:
            print(
                f'\tLa frontière basse est trop basse : {in_euros(df["lower_bound"])} > {in_euros(v["rfr_min"])}'
            )
        if df["upper_bound"] > v["rfr_max"]:
            print(
                f'\tLa frontière haute est trop basse : {in_euros(df["upper_bound"])} > {in_euros(v["rfr_max"])}'
            )
        if df["bucket_sum"] > v["rfr_sum"]:
            print(
                f'\tLa somme est trop basse : {in_euros(df["bucket_sum"])} > {in_euros(v["rfr_sum"])}'
            )
            nb_foy_to_max = int((df["bucket_sum"] - v["rfr_sum"]) / df["upper_bound"])
            print(
                f'\t => Il faut ajouter {nb_foy_to_max:,.0f} foyers avec un rfr à {df["upper_bound"]:,.2f}'
            )
        if df["bucket_mean"] > v["rfr_mean"]:
            print(
                f'\tLa moyenne est trop basse : {in_euros(df["bucket_mean"])} > {in_euros(v["rfr_mean"])}'
            )
nb_lignes = len(base_ind_plf2023)
sum_poids = base_ind_plf2023.weight_foyers.sum()
deciles_plf2023 = create_dict_decile(base_ind_plf2023)

# decile_1 = base_ind_plf2023.query("0 < rfr < 2264")
# decile_1.rfr.max()
# decile_1.weight_foyers.sum()
# decile_1.weight_foyers.sum()
poids_total_verif = 0
nb_lignes_verif = 0
for k, v in deciles_plf2023.items():
    poids_total_verif += v["poids_decile"]
    nb_lignes_verif += v["count"]
# tc.assertEqual(nb_lignes, nb_lignes_verif)
# tc.assertAlmostEqual(sum_poids, poids_total_verif, delta=1)


verif_decile(deciles_plf2023)
Décile 1 rfr_min=0,00 € vs 0,00 € rfr_max=2 264,00 € vs 0,00 €
rfr_sum=1,07 Mds € vs 0,00 € poids_decile=3,98 M€
    La frontière haute est trop basse : 2 264,00 € > 0,00 €
    La somme est trop basse : 1,07 Mds € > 0,00 €
     => Il faut ajouter 472,276 foyers avec un rfr à 2,264.00
    La moyenne est trop basse : 268,53 € > 0,00 €
Décile 2 rfr_min=2 264,00 € vs 0,00 € rfr_max=8 816,00 € vs 7 533,26 €
rfr_sum=23,67 Mds € vs 14,81 Mds € poids_decile=4,05 M€
    La frontière basse est trop basse : 2 264,00 € > 0,00 €
    La frontière haute est trop basse : 8 816,00 € > 7 533,26 €
    La somme est trop basse : 23,67 Mds € > 14,81 Mds €
     => Il faut ajouter 1,004,402 foyers avec un rfr à 8,816.00
    La moyenne est trop basse : 5 943,93 € > 3 656,02 €
Décile 3 rfr_min=8 816,00 € vs 7 533,26 € rfr_max=12,85 k€ vs 12,73 k€
rfr_sum=43,58 Mds € vs 41,42 Mds € poids_decile=3,99 M€
    La frontière basse est trop basse : 8 816,00 € > 7 533,26 €
    La frontière haute est trop basse : 12,85 k€ > 12,73 k€
    La somme est trop basse : 43,58 Mds € > 41,42 Mds €
     => Il faut ajouter 167,643 foyers avec un rfr à 12,854.00
    La moyenne est trop basse : 10,94 k€ > 10,37 k€
Décile 4 rfr_min=12,85 k€ vs 12,73 k€ rfr_max=16,20 k€ vs 17,21 k€
rfr_sum=58,39 Mds € vs 60,69 Mds € poids_decile=4,02 M€
    La frontière basse est trop basse : 12,85 k€ > 12,73 k€
Décile 5 rfr_min=16,20 k€ vs 17,21 k€ rfr_max=19,45 k€ vs 21,10 k€
rfr_sum=70,80 Mds € vs 77,11 Mds € poids_decile=4,04 M€
Décile 6 rfr_min=19,45 k€ vs 21,10 k€ rfr_max=23,86 k€ vs 26,04 k€
rfr_sum=85,38 Mds € vs 95,73 Mds € poids_decile=4,09 M€
Décile 7 rfr_min=23,86 k€ vs 26,04 k€ rfr_max=30,11 k€ vs 32,30 k€
rfr_sum=107 Mds € vs 116 Mds € poids_decile=3,97 M€
Décile 8 rfr_min=30,11 k€ vs 32,31 k€ rfr_max=38,71 k€ vs 40,42 k€
rfr_sum=136 Mds € vs 146 Mds € poids_decile=4,03 M€
Décile 9 rfr_min=38,71 k€ vs 40,42 k€ rfr_max=54,55 k€ vs 54,37 k€
rfr_sum=181 Mds € vs 187 Mds € poids_decile=4,03 M€
    La frontière haute est trop basse : 54,55 k€ > 54,37 k€
Décile 10 rfr_min=54,55 k€ vs 54,37 k€ rfr_max=145 M€ vs 3,41 M€
rfr_sum=396 Mds € vs 363 Mds € poids_decile=4,08 M€
    La frontière basse est trop basse : 54,55 k€ > 54,37 k€
    La frontière haute est trop basse : 145 M€ > 3,41 M€
    La somme est trop basse : 396 Mds € > 363 Mds €
     => Il faut ajouter 231 foyers avec un rfr à 144,609,869.00
    La moyenne est trop basse : 99,49 k€ > 88,81 k€
base_ind_plf2023.query("idfoy == 1172")[["rfr", "decile"]]
rfr decile
2368 1.08 2
# Il faut ajouter 472,276 foyers avec un rfr à 2,264.00


def increase_rfr(row):
    global current_sum
    if current_sum <= target:
        old_rfr = row["rfr"]
        new_rfr = rfr_max_to_set
        row["rfr"] = new_rfr
        current_sum += (rfr_max_to_set - old_rfr) * row["weight_foyers"]
    return row


def decrease_rfr(row):
    global current_sum
    old_rfr = row["rfr"]
    new_rfr = lower_bound
    if current_sum > target and new_rfr < old_rfr:
        row["rfr"] = new_rfr
        current_sum += (new_rfr - old_rfr) * row["weight_foyers"]
    return row


for k, v in deciles_plf2023.items():
    df_target = df_decile_rfr_2020.iloc[k - 1]
    lower_bound = df_target["lower_bound"]
    target = df_target["bucket_sum"] - v["rfr_sum"]
    print(f"{k} Il faut récupérer {in_euros(target)}")
    current_sum = 0
    # On fixe la borne inférieure
    df_lower = v["data"].query("rfr < @lower_bound").copy()
    if len(df_lower) > 0:
        print("\tOn traite les lignes en dessous du lower_bound")
        df_lower["new_rfr"] = lower_bound
        current_sum += (
            (df_lower["new_rfr"] - df_lower["rfr"]) * df_lower["weight_foyers"]
        ).sum()
        v["data"].loc[v["data"]["rfr"] < lower_bound, "rfr"] = lower_bound
        print(f"\tnous avons déjà récupéré {current_sum} sur {target}")
    # On fixe la borne suppérieure
    upper_bound = df_target["upper_bound"]
    df_upper = v["data"].query("rfr > @upper_bound").copy()
    if len(df_upper) > 0:
        print("\tOn passe aux lignes au dessus du upper_bound")
        df_upper["new_rfr"] = upper_bound
        current_sum = (
            (df_upper["new_rfr"] - df_upper["rfr"]) * df_upper["weight_foyers"]
        ).sum()
        v["data"].loc[v["data"]["rfr"] > upper_bound, "rfr"] = upper_bound
        print(f"\tnous avons encore récupéré {current_sum} sur {target}")

    # On regarde où nous en somme
    sum_rfr = (v["data"].rfr * v["data"].weight_foyers).sum()
    target = df_target["bucket_sum"] - sum_rfr

    if df_target["bucket_sum"] > sum_rfr:
        print("\tOn est encore trop pauvre")
        nb_foy_to_max = int(
            (df_target["bucket_sum"] - sum_rfr) / df_target["upper_bound"]
        )
        rfr_max_to_set = df_target["upper_bound"]
        target = nb_foy_to_max * rfr_max_to_set
        df = v["data"].apply(increase_rfr, axis=1)
        print(
            f"\t Nous avons récupéré {in_euros(current_sum)} au total sur {in_euros(target)}"
        )
    else:
        print("\tOn est trop riche !!")
        # nb_foy_to_min = int((sum_rfr - df_target["bucket_sum"]) / df_target["lower_bound"])
        # target = -df_target["lower_bound"] * nb_foy_to_min
        print(f"\t{target=} {current_sum=}")
        df = v["data"].apply(decrease_rfr, axis=1)
    # On regarde où nous en somme
    sum_rfr = (df.rfr * df.weight_foyers).sum()
    print(
        f'\t=>{in_euros(sum_rfr)} vs {in_euros(df_target["bucket_sum"])} : {abs(sum_rfr-df_target["bucket_sum"])/df_target["bucket_sum"]*100:.2f}%'
    )
    v["data"] = df
    v["count"] = len(df)
    v["poids_decile"] = df.weight_foyers.sum()
    v["rfr_min"] = df.rfr.min()
    v["rfr_max"] = df.rfr.max()
    v["rfr_sum"] = (df.rfr * df.weight_foyers).sum()
    v["rfr_mean"] = (df.rfr * df.weight_foyers).sum() / df.weight_foyers.sum()
1 Il faut récupérer 1,07 Mds €
    On est encore trop pauvre
     Nous avons récupéré 1,07 Mds € au total sur 1,07 Mds €
    =>1,07 Mds € vs 1,07 Mds € : 0.17%
2 Il faut récupérer 8,85 Mds €
    On traite les lignes en dessous du lower_bound
    nous avons déjà récupéré 2035575497.7732534 sur 8854811867.0
    On est encore trop pauvre
     Nous avons récupéré 6,82 Mds € au total sur 6,82 Mds €
    =>21,64 Mds € vs 23,67 Mds € : 8.58%
3 Il faut récupérer 2,15 Mds €
    On traite les lignes en dessous du lower_bound
    nous avons déjà récupéré 502004472.0356902 sur 2154896089.0
    On est encore trop pauvre
     Nous avons récupéré 1,65 Mds € au total sur 1,65 Mds €
    =>43,08 Mds € vs 43,58 Mds € : 1.15%
4 Il faut récupérer -2,30 Mds €
    On traite les lignes en dessous du lower_bound
    nous avons déjà récupéré 10762988.389979929 sur -2295236100.0
    On passe aux lignes au dessus du upper_bound
    nous avons encore récupéré -551491692.4300919 sur -2295236100.0
    On est trop riche !!
    target=-1754506756.0 current_sum=-551491692.4300919
    =>58,94 Mds € vs 58,39 Mds € : 0.94%
5 Il faut récupérer -6,31 Mds €
    On passe aux lignes au dessus du upper_bound
    nous avons encore récupéré -1268450250.5650878 sur -6306558852.0
    On est trop riche !!
    target=-5038109572.0 current_sum=-1268450250.5650878
    =>72,07 Mds € vs 70,80 Mds € : 1.79%
6 Il faut récupérer -10,35 Mds €
    On passe aux lignes au dessus du upper_bound
    nous avons encore récupéré -1506065871.6963296 sur -10348344346.0
    On est trop riche !!
    target=-8842277914.0 current_sum=-1506065871.6963296
    =>86,89 Mds € vs 85,38 Mds € : 1.76%
7 Il faut récupérer -8,53 Mds €
    On passe aux lignes au dessus du upper_bound
    nous avons encore récupéré -1535099597.5374315 sur -8531604865.0
    On est trop riche !!
    target=-6996505985.0 current_sum=-1535099597.5374315
    =>109 Mds € vs 107 Mds € : 1.43%
8 Il faut récupérer -9,83 Mds €
    On passe aux lignes au dessus du upper_bound
    nous avons encore récupéré -628785305.5895054 sur -9828353723.0
    On est trop riche !!
    target=-9199568571.0 current_sum=-628785305.5895054
    =>136 Mds € vs 136 Mds € : 0.46%
9 Il faut récupérer -5,54 Mds €
    On est trop riche !!
    target=-5541808231.0 current_sum=0
    =>181 Mds € vs 181 Mds € : 0.00%
10 Il faut récupérer 33,44 Mds €
    On traite les lignes en dessous du lower_bound
    nous avons déjà récupéré 2164067.3926736116 sur 33442843755.0
    On est encore trop pauvre
     Nous avons récupéré 89,13 Mds € au total sur 33,40 Mds €
    =>452 Mds € vs 396 Mds € : 14.06%
verif_decile(deciles_plf2023)
Décile 1 rfr_min=0,00 € vs 0,00 € rfr_max=2 264,00 € vs 2 264,00 €
rfr_sum=1,07 Mds € vs 1,07 Mds € poids_decile=3,98 M€
Décile 2 rfr_min=2 264,00 € vs 2 264,00 € rfr_max=8 816,00 € vs 8 816,00 €
rfr_sum=23,67 Mds € vs 21,64 Mds € poids_decile=4,05 M€
    La somme est trop basse : 23,67 Mds € > 21,64 Mds €
     => Il faut ajouter 230,349 foyers avec un rfr à 8,816.00
    La moyenne est trop basse : 5 943,93 € > 5 339,31 €
Décile 3 rfr_min=8 816,00 € vs 8 816,00 € rfr_max=12,85 k€ vs 12,85 k€
rfr_sum=43,58 Mds € vs 43,08 Mds € poids_decile=3,99 M€
    La somme est trop basse : 43,58 Mds € > 43,08 Mds €
     => Il faut ajouter 38,904 foyers avec un rfr à 12,854.00
    La moyenne est trop basse : 10,94 k€ > 10,79 k€
Décile 4 rfr_min=12,85 k€ vs 12,85 k€ rfr_max=16,20 k€ vs 16,20 k€
rfr_sum=58,39 Mds € vs 58,94 Mds € poids_decile=4,02 M€
    La moyenne est trop basse : 14,66 k€ > 14,65 k€
Décile 5 rfr_min=16,20 k€ vs 16,20 k€ rfr_max=19,45 k€ vs 19,45 k€
rfr_sum=70,80 Mds € vs 72,07 Mds € poids_decile=4,04 M€
Décile 6 rfr_min=19,45 k€ vs 19,45 k€ rfr_max=23,86 k€ vs 23,86 k€
rfr_sum=85,38 Mds € vs 86,89 Mds € poids_decile=4,09 M€
    La moyenne est trop basse : 21,44 k€ > 21,22 k€
Décile 7 rfr_min=23,86 k€ vs 23,86 k€ rfr_max=30,11 k€ vs 30,11 k€
rfr_sum=107 Mds € vs 109 Mds € poids_decile=3,97 M€
Décile 8 rfr_min=30,11 k€ vs 30,11 k€ rfr_max=38,71 k€ vs 38,71 k€
rfr_sum=136 Mds € vs 136 Mds € poids_decile=4,03 M€
    La moyenne est trop basse : 34,11 k€ > 33,84 k€
Décile 9 rfr_min=38,71 k€ vs 38,71 k€ rfr_max=54,55 k€ vs 54,37 k€
rfr_sum=181 Mds € vs 181 Mds € poids_decile=4,03 M€
    La frontière haute est trop basse : 54,55 k€ > 54,37 k€
    La somme est trop basse : 181 Mds € > 181 Mds €
     => Il faut ajouter 19 foyers avec un rfr à 54,548.00
    La moyenne est trop basse : 45,58 k€ > 45,08 k€
Décile 10 rfr_min=54,55 k€ vs 54,55 k€ rfr_max=145 M€ vs 145 M€
rfr_sum=396 Mds € vs 452 Mds € poids_decile=4,08 M€

Applique les modifications de RFR sur la base initiale

df_new_rfr = pd.DataFrame()
for k, v in deciles_plf2023.items():
    df_new_rfr = pd.concat([df_new_rfr, v["data"][["idfoy", "rfr"]]])
df_new_rfr
idfoy rfr
74620 37864 2,264.00
8504 4353 2,264.00
33904 17262 2,264.00
94878 48111 2,264.00
33938 17275 2,264.00
... ... ...
1566 757 1,258,058.12
85645 43424 1,517,401.75
84616 42915 2,119,405.00
102847 52175 2,282,122.00
50247 25501 3,409,219.25

56935 rows × 2 columns

base_plf2023 = pd.read_hdf(
    "/mnt/data-out/leximpact/pipeline_2022/base_ERFS2018_POTE2019_ind_2022_20221220-101745.h5"
)
# base_plf2023.columns
# Liste des variables que l'on ne veut pas modifier
col_to_not_change = [
    "quifoy",
    "statut_marital",
    "foyer_fiscal_id",
    "autonomie_financiere",
    "heures_remunerees_volume",
    "famille_id",
    "effectif_entreprise",
    "noindiv",
    "weight_individus",
    "categorie_salarie",
    "idfoy",
    "quimen",
    "menage_ordinaire_individus",
    "date_naissance",
    "quifam",
    "idfam",
    "activite",
    "age",
    "menage_id",
    "idmen",
    "famille_role",
    "famille_position",
    "foyer_fiscal_role",
    "foyer_fiscal_position",
    "menage_role",
    "menage_position",
    "weight_familles",
    "menage_ordinaire_familles",
    "weight_foyers",
    "menage_ordinaire_foyers_fiscaux",
    "rfr",
    "menage_ordinaire",
    "weight_menages",
    "wprm_init",
    "wprm",
    "rfr_x",
    "rfr_y",
]
base_ff_plf = base_plf2023.query("quifoy == 0").copy()
base_ff_plf["wprm"] = base_ff_plf["weight_foyers"]
base_ff_plf["rfr_wprm"] = base_ff_plf["rfr"] * base_ff_plf["wprm"]
# filter_by
in_euros(base_ff_plf["rfr_wprm"].sum())
len(base_ff_plf)
'1 101 Mds €'
56935
base_plf2023.query("idfoy == 50")
base_plf2023.query("idfoy == 1172")
quifoy crds_retraite ric statut_marital foyer_fiscal_id crds_non_salarie csg_imposable_retraite csg_deductible_chomage autonomie_financiere heures_remunerees_volume ... rente_viagere_titre_onereux_net menage_ordinaire_foyers_fiscaux rfr crds_revenus_capital revenus_capitaux_prelevement_liberatoire revenus_capitaux_prelevement_bareme menage_ordinaire weight_menages wprm_init wprm
111 0 0.00 0.00 2 50 0.00 0.00 0.00 True 0.00 ... 0.00 1 68,921.50 -0.01 0.00 0.00 1 0.00 0.00 0.00
112 1 0.00 0.00 2 50 0.00 0.00 0.00 True 0.00 ... 0.00 1 68,921.50 -0.01 0.00 0.00 1 0.00 0.00 0.00
113 2 0.00 0.00 2 50 0.00 0.00 0.00 False 0.00 ... 0.00 1 68,921.50 -0.01 0.00 0.00 1 0.00 0.00 0.00

3 rows × 69 columns

quifoy crds_retraite ric statut_marital foyer_fiscal_id crds_non_salarie csg_imposable_retraite csg_deductible_chomage autonomie_financiere heures_remunerees_volume ... rente_viagere_titre_onereux_net menage_ordinaire_foyers_fiscaux rfr crds_revenus_capital revenus_capitaux_prelevement_liberatoire revenus_capitaux_prelevement_bareme menage_ordinaire weight_menages wprm_init wprm
2368 0 0.00 0.00 1 1172 0.00 0.00 0.00 False 0.00 ... 0.00 1 1.08 -0.01 0.00 0.00 1 0.00 0.00 0.00
2369 1 0.00 0.00 1 1172 0.00 0.00 0.00 False 0.00 ... 0.00 1 1.08 -0.01 0.00 0.00 1 0.00 0.00 0.00
2370 2 0.00 0.00 2 1172 0.00 0.00 0.00 False 0.00 ... 0.00 1 1.08 -0.01 0.00 0.00 1 0.00 0.00 0.00
2371 2 0.00 0.00 2 1172 0.00 0.00 0.00 False 0.00 ... 0.00 1 1.08 -0.01 0.00 0.00 1 0.00 0.00 0.00

4 rows × 69 columns

Fusion de la base avec nos modificarions

in_euros((base_plf2023.rfr * base_plf2023.weight_foyers).sum())
base_new_rfr = base_plf2023.merge(df_new_rfr, on="idfoy")
in_euros((base_new_rfr.rfr_x * base_new_rfr.weight_foyers).sum())
in_euros((base_new_rfr.rfr_y * base_new_rfr.weight_foyers).sum())
'2 557 Mds €'
'2 557 Mds €'
'2 674 Mds €'
base_new_rfr.describe()
quifoy crds_retraite ric statut_marital foyer_fiscal_id crds_non_salarie csg_imposable_retraite csg_deductible_chomage heures_remunerees_volume crds_chomage ... menage_ordinaire_foyers_fiscaux rfr_x crds_revenus_capital revenus_capitaux_prelevement_liberatoire revenus_capitaux_prelevement_bareme menage_ordinaire weight_menages wprm_init wprm rfr_y
count 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 ... 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00
mean 0.73 -25.47 199.62 1.80 28,463.38 0.00 -111.46 -2.78 132.66 -0.42 ... 1.00 31,821.13 -6.04 120.75 101.92 1.00 0.00 0.00 0.00 33,629.96
std 0.82 56.21 3,435.84 0.81 16,398.73 0.00 266.87 64.59 378.73 8.98 ... 0.00 39,405.98 127.50 2,387.24 1,778.02 0.00 0.00 0.00 0.00 611,828.34
min 0.00 -1,617.21 -127,951.47 1.00 0.00 0.00 -7,762.63 -7,124.26 0.00 -962.81 ... 1.00 0.00 -28,929.40 0.00 0.00 1.00 0.00 0.00 0.00 0.00
25% 0.00 0.00 0.00 1.00 14,268.00 0.00 0.00 0.00 0.00 0.00 ... 1.00 12,841.74 -0.19 0.00 0.00 1.00 0.00 0.00 0.00 12,854.00
50% 0.00 0.00 0.00 2.00 28,442.00 0.00 0.00 0.00 0.00 0.00 ... 1.00 25,155.27 0.00 0.00 0.00 1.00 0.00 0.00 0.00 23,865.00
75% 1.00 0.00 0.00 2.00 42,652.25 0.00 0.00 0.00 0.00 0.00 ... 1.00 41,782.49 0.00 0.00 0.00 1.00 0.00 0.00 0.00 38,713.00
max 2.00 0.00 368,252.16 4.00 56,934.00 0.00 0.00 0.00 1,819.24 0.00 ... 1.00 3,409,219.25 0.00 261,438.77 215,740.86 1.00 0.00 0.00 0.00 144,609,869.00

8 rows × 67 columns

La colonne rfr_x contient l’ancien RFR et rfr_y contient le nouveau, nous allons donc pouvoir utiliser le ratio entre les deux pour changer les revenus.

base_finale = base_new_rfr.copy()
# df = base_finale.query("rfr_x > 0")
base_finale["ratio"] = base_finale["rfr_y"] / base_finale["rfr_x"]
base_finale.fillna(value={"ratio": 1}, inplace=True)
base_finale.replace([np.inf, -np.inf], 1, inplace=True)
col_to_change = set(base_finale.columns.to_list()) - set(col_to_not_change)
for c in col_to_change:
    base_finale[c] = base_finale[c] * base_finale["ratio"]
col_to_change
{'assiette_csg_abattue',
 'assiette_csg_plus_values',
 'chomage_brut',
 'chomage_imposable',
 'contrat_de_travail',
 'cotisation_sociale_mode_recouvrement',
 'crds',
 'crds_chomage',
 'crds_non_salarie',
 'crds_retraite',
 'crds_revenus_capital',
 'crds_salaire',
 'csg',
 'csg_deductible_chomage',
 'csg_deductible_non_salarie',
 'csg_deductible_retraite',
 'csg_deductible_salaire',
 'csg_imposable_chomage',
 'csg_imposable_retraite',
 'csg_imposable_salaire',
 'csg_revenus_capital',
 'f4ba',
 'irpp',
 'pensions_alimentaires_percues',
 'rag',
 'ratio',
 'rente_viagere_titre_onereux_net',
 'retraite_brute',
 'retraite_imposable',
 'revenus_capitaux_prelevement_bareme',
 'revenus_capitaux_prelevement_forfaitaire_unique_ir',
 'revenus_capitaux_prelevement_liberatoire',
 'ric',
 'rnc',
 'salaire_de_base'}
base_finale.describe()
quifoy crds_retraite ric statut_marital foyer_fiscal_id crds_non_salarie csg_imposable_retraite csg_deductible_chomage heures_remunerees_volume crds_chomage ... rfr_x crds_revenus_capital revenus_capitaux_prelevement_liberatoire revenus_capitaux_prelevement_bareme menage_ordinaire weight_menages wprm_init wprm rfr_y ratio
count 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 ... 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00 112,144.00
mean 0.73 -3,731.65 78,234,431.31 1.80 28,463.38 0.00 -17,901.82 -2.65 132.66 -0.40 ... 31,821.13 -2,392.81 119.49 99,873.60 1.00 0.00 0.00 0.00 33,629.96 158,212.00
std 0.82 1,241,858.04 9,338,648,155.70 0.81 16,398.73 0.00 5,960,919.65 62.61 378.73 8.68 ... 39,405.98 340,469.71 2,384.14 30,466,589.59 0.00 0.00 0.00 0.00 611,828.34 3,076,661.85
min 0.00 -415,872,304.14 -1,595,357.26 1.00 0.00 0.00 -1,996,187,405.29 -7,124.26 0.00 -962.81 ... 0.00 -101,637,446.75 0.00 0.00 1.00 0.00 0.00 0.00 0.00 0.67
25% 0.00 0.00 0.00 1.00 14,268.00 0.00 0.00 0.00 0.00 0.00 ... 12,841.74 -0.20 0.00 0.00 1.00 0.00 0.00 0.00 12,854.00 0.87
50% 0.00 0.00 0.00 2.00 28,442.00 0.00 0.00 0.00 0.00 0.00 ... 25,155.27 0.00 0.00 0.00 1.00 0.00 0.00 0.00 23,865.00 1.00
75% 1.00 0.00 0.00 2.00 42,652.25 0.00 0.00 0.00 0.00 0.00 ... 41,782.49 0.00 0.00 0.00 1.00 0.00 0.00 0.00 38,713.00 1.00
max 2.00 0.00 1,951,624,122,934.01 4.00 56,934.00 0.00 0.00 0.00 1,819.24 0.00 ... 3,409,219.25 0.00 261,438.77 10,177,579,164.88 1.00 0.00 0.00 0.00 144,609,869.00 67,088,648.75

8 rows × 69 columns

base_finale.columns
Index(['quifoy', 'crds_retraite', 'ric', 'statut_marital', 'foyer_fiscal_id',
       'crds_non_salarie', 'csg_imposable_retraite', 'csg_deductible_chomage',
       'autonomie_financiere', 'heures_remunerees_volume', 'crds_chomage',
       'cotisation_sociale_mode_recouvrement', 'csg_deductible_retraite',
       'famille_id', 'effectif_entreprise', 'crds_salaire', 'noindiv',
       'weight_individus', 'categorie_salarie',
       'pensions_alimentaires_percues', 'csg', 'rnc', 'idfoy', 'quimen',
       'menage_ordinaire_individus', 'date_naissance', 'quifam',
       'csg_imposable_salaire', 'retraite_brute', 'retraite_imposable',
       'activite', 'csg_imposable_chomage', 'csg_deductible_non_salarie',
       'chomage_brut', 'idfam', 'age', 'csg_deductible_salaire', 'crds',
       'assiette_csg_abattue', 'menage_id', 'idmen', 'salaire_de_base',
       'chomage_imposable', 'contrat_de_travail', 'rag', 'famille_role',
       'famille_position', 'foyer_fiscal_role', 'foyer_fiscal_position',
       'menage_role', 'menage_position', 'weight_familles',
       'menage_ordinaire_familles', 'f4ba', 'csg_revenus_capital', 'irpp',
       'weight_foyers', 'revenus_capitaux_prelevement_forfaitaire_unique_ir',
       'assiette_csg_plus_values', 'rente_viagere_titre_onereux_net',
       'menage_ordinaire_foyers_fiscaux', 'rfr_x', 'crds_revenus_capital',
       'revenus_capitaux_prelevement_liberatoire',
       'revenus_capitaux_prelevement_bareme', 'menage_ordinaire',
       'weight_menages', 'wprm_init', 'wprm', 'rfr_y', 'ratio'],
      dtype='object')
base_finale.sort_values("ratio").tail(3)[
    ["ratio", "idfoy", "rfr_x", "rfr_y", "salaire_de_base"]
]
ratio idfoy rfr_x rfr_y salaire_de_base
104308 67,088,648.75 52936 1.08 8,816.00 0.00
2368 67,088,648.75 1172 1.08 8,816.00 0.00
104305 67,088,648.75 52936 1.08 8,816.00 0.00
for c in col_to_change - {"ratio"}:
    print(
        f"La somme de {c} qui était \t\t\t{in_euros(base_new_rfr[c].sum())} devient {in_euros(base_finale[c].sum())}"
    )
La somme de csg_deductible_retraite qui était           -29,04 M€ devient -29,59 M€
La somme de revenus_capitaux_prelevement_liberatoire qui était          13,54 M€ devient 13,40 M€
La somme de contrat_de_travail qui était            407,90 k€ devient 11,24 M€
La somme de crds_chomage qui était          -47,24 k€ devient -44,76 k€
La somme de crds qui était          -9,08 M€ devient -57,70 Mds €
La somme de csg_deductible_salaire qui était            -75,28 M€ devient -36,12 Mds €
La somme de assiette_csg_abattue qui était          1,12 Mds € devient 541 Mds €
La somme de crds_non_salarie qui était          0,00 € devient 0,00 €
La somme de crds_retraite qui était             -2,86 M€ devient -418 M€
La somme de rag qui était           11,86 M€ devient 5 655 Mds €
La somme de rente_viagere_titre_onereux_net qui était           5,93 M€ devient 20,33 Mds €
La somme de chomage_brut qui était          53,20 M€ devient 38,57 Mds €
La somme de f4ba qui était          116 M€ devient 487 M€
La somme de cotisation_sociale_mode_recouvrement qui était          224,29 k€ devient 35,49 Mds €
La somme de csg_imposable_chomage qui était             -206,88 k€ devient -196,93 k€
La somme de csg_deductible_non_salarie qui était            0,00 € devient 0,00 €
La somme de csg_revenus_capital qui était           -12,46 M€ devient -4,94 Mds €
La somme de salaire_de_base qui était           1,22 Mds € devient 586 Mds €
La somme de pensions_alimentaires_percues qui était             9,00 M€ devient 5,73 Mds €
La somme de assiette_csg_plus_values qui était          30,25 M€ devient 67,41 M€
La somme de csg qui était           -149 M€ devient -59,77 Mds €
La somme de chomage_imposable qui était             51,60 M€ devient 37,66 Mds €
La somme de revenus_capitaux_prelevement_bareme qui était           11,43 M€ devient 11,20 Mds €
La somme de revenus_capitaux_prelevement_forfaitaire_unique_ir qui était            74,32 M€ devient 22,06 Mds €
La somme de csg_imposable_retraite qui était            -12,50 M€ devient -2,01 Mds €
La somme de crds_salaire qui était          -5,54 M€ devient -2,66 Mds €
La somme de retraite_imposable qui était            584 M€ devient 710 Mds €
La somme de crds_revenus_capital qui était          -677,36 k€ devient -268 M€
La somme de irpp qui était          -249 M€ devient -47,02 Mds €
La somme de rnc qui était           65,81 M€ devient 14 695 Mds €
La somme de csg_imposable_salaire qui était             -26,57 M€ devient -12,75 Mds €
La somme de ric qui était           22,39 M€ devient 8 774 Mds €
La somme de retraite_brute qui était            620 M€ devient 722 Mds €
La somme de csg_deductible_chomage qui était            -312,25 k€ devient -297,15 k€
base_finale.query("ratio>10")[col_to_change]
/tmp/ipykernel_1167510/1537780547.py:1: FutureWarning: Passing a set as an indexer is deprecated and will raise in a future version. Use a list instead.
  base_finale.query("ratio>10")[col_to_change]
csg_deductible_retraite revenus_capitaux_prelevement_liberatoire contrat_de_travail ratio crds_chomage crds csg_deductible_salaire assiette_csg_abattue crds_non_salarie crds_retraite ... csg_imposable_retraite crds_salaire retraite_imposable crds_revenus_capital irpp rnc csg_imposable_salaire ric retraite_brute csg_deductible_chomage
42 0.00 0.00 0.00 261.00 0.00 -6,029.35 0.00 0.00 0.00 0.00 ... 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
43 0.00 0.00 96.93 261.00 0.00 0.00 0.00 0.00 0.00 0.00 ... 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
44 0.00 0.00 96.93 261.00 0.00 0.00 0.00 0.00 0.00 0.00 ... 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
170 0.00 0.00 13.22 174.71 0.00 -1,271.35 -6,854.98 102,611.46 0.00 0.00 ... 0.00 -504.04 0.00 -519.59 0.00 0.00 -2,419.40 0.00 0.00 0.00
453 0.00 0.00 311.35 2,692.74 0.00 -703.16 0.00 0.00 0.00 0.00 ... 0.00 0.00 0.00 -703.16 0.00 0.00 0.00 0.00 0.00 0.00
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
111476 0.00 0.00 8,190.76 1,863,572.75 0.00 0.00 0.00 0.00 0.00 0.00 ... 0.00 0.00 0.00 -57,427.53 0.00 0.00 0.00 0.00 0.00 0.00
111477 0.00 0.00 8,190.76 1,863,572.75 0.00 0.00 0.00 0.00 0.00 0.00 ... 0.00 0.00 0.00 -57,427.53 0.00 0.00 0.00 0.00 0.00 0.00
111483 0.00 0.00 13.02 169.53 0.00 -1,081.92 -14,317.20 214,290.24 0.00 0.00 ... 0.00 -1,052.74 0.00 -29.19 0.00 0.00 -5,053.13 0.00 0.00 0.00
111622 0.00 0.00 49,144.60 67,088,648.75 0.00 -344,565.24 0.00 0.00 0.00 0.00 ... 0.00 0.00 0.00 -344,565.24 0.00 0.00 0.00 0.00 0.00 0.00
111884 0.00 0.00 12,286.15 4,193,040.55 0.00 -86,141.31 0.00 0.00 0.00 0.00 ... 0.00 0.00 0.00 -86,141.31 0.00 0.00 0.00 0.00 0.00 0.00

1297 rows × 35 columns

# base_finale.rename(columns={"rfr_y", "rfr"})
base_finale["rfr"] = base_finale["rfr_y"]
base_finale.drop(["rfr_x", "rfr_y"], axis=1, inplace=True)
base_finale.sort_values("rfr", inplace=True)
base_ff = base_finale.query("quifoy == 0").copy()
base_ff["wprm"] = base_ff["weight_foyers"]
base_ff["rfr_wprm"] = base_ff["rfr"] * base_ff["wprm"]
# filter_by
in_euros(base_ff["rfr_wprm"].sum())
len(base_ff)
'1 162 Mds €'
56935
len(base_finale.query("rfr < 1"))
len(base_ff.query("rfr < 1"))
9143
5008

Décile de RFR de la nouvelle base

resultat_quantile_test = compute_quantile(
    base_ff, ["rfr"], ["rfr_wprm"], do_rounddown=False
)
df_decile_finale = pd.DataFrame(resultat_quantile_test)
df_decile_finale
fraction count rfr rfr_wprm
0 0.10 3,997,605.50 2,264.00 1,239,683,758,893.02
1 0.20 4,041,386.75 8,816.00 23,962,674,421,983.18
2 0.30 3,986,829.75 12,854.00 43,543,202,252,600.75
3 0.40 4,021,649.00 16,199.00 65,051,375,628,405.58
4 0.50 4,086,232.50 19,450.00 80,993,369,471,028.02
5 0.60 3,967,102.50 23,865.00 90,356,243,663,998.53
6 0.70 4,083,626.50 30,112.00 121,171,623,595,181.25
7 0.80 3,974,092.50 38,713.00 137,420,807,345,626.69
8 0.90 4,048,240.50 54,548.00 203,888,893,585,052.19
9 1.00 4,083,711.00 144,609,869.00 475,651,363,542,830.25
base_finale.to_hdf(
    "/mnt/data-out/leximpact/pipeline_2022/base_ERFS2018_POTE2019_ind_2022_20221220-101745-bidouillage.h5",
    key="input",
)
base_finale.loc[62364][["idfoy", "rfr"]]
idfoy    31643
rfr       0.00
Name: 62364, dtype: object
deciles_plf2023 = create_dict_decile(base_finale)
verif_decile(deciles_plf2023)
Décile 1 rfr_min=0,00 € vs 0,00 € rfr_max=2 264,00 € vs 2 264,00 €
rfr_sum=1,07 Mds € vs 3,25 Mds € poids_decile=7,83 M€
Décile 2 rfr_min=2 264,00 € vs 2 264,00 € rfr_max=8 816,00 € vs 10,07 k€
rfr_sum=23,67 Mds € vs 51,44 Mds € poids_decile=7,84 M€
Décile 3 rfr_min=8 816,00 € vs 10,07 k€ rfr_max=12,85 k€ vs 15,88 k€
rfr_sum=43,58 Mds € vs 101 Mds € poids_decile=7,92 M€
Décile 4 rfr_min=12,85 k€ vs 15,88 k€ rfr_max=16,20 k€ vs 19,45 k€
rfr_sum=58,39 Mds € vs 138 Mds € poids_decile=8,04 M€
Décile 5 rfr_min=16,20 k€ vs 19,45 k€ rfr_max=19,45 k€ vs 23,86 k€
rfr_sum=70,80 Mds € vs 163 Mds € poids_decile=7,89 M€
Décile 6 rfr_min=19,45 k€ vs 23,86 k€ rfr_max=23,86 k€ vs 30,11 k€
rfr_sum=85,38 Mds € vs 211 Mds € poids_decile=7,94 M€
Décile 7 rfr_min=23,86 k€ vs 30,11 k€ rfr_max=30,11 k€ vs 37,94 k€
rfr_sum=107 Mds € vs 251 Mds € poids_decile=7,90 M€
Décile 8 rfr_min=30,11 k€ vs 37,94 k€ rfr_max=38,71 k€ vs 46,38 k€
rfr_sum=136 Mds € vs 320 Mds € poids_decile=8,01 M€
Décile 9 rfr_min=38,71 k€ vs 46,38 k€ rfr_max=54,55 k€ vs 61,95 k€
rfr_sum=181 Mds € vs 425 Mds € poids_decile=7,98 M€
Décile 10 rfr_min=54,55 k€ vs 61,95 k€ rfr_max=145 M€ vs 145 M€
rfr_sum=396 Mds € vs 1 010 Mds € poids_decile=8,11 M€

Fin bidouille

Moyennes de RFR, par décile

data1 = {
    "df": df_decile_rfr_2020,
    "trace_name": "POTE 2020",
    "col_to_plot": {
        "y": "bucket_mean",
        "width": "bucket_count",
        "y_lib": "Moyenne",
    },
}
data2 = {
    "df": df_decile_base_lex_plf2022,
    "trace_name": "Base LexImpact PLF2022",
    "col_to_plot": {
        "y": "rfr_lex_mean",
        "width": "bucket_count",
        "y_lib": "Moyenne",
    },
}
data3 = {
    "df": df_decile_base_lex_plf2023,
    "trace_name": "Base LexImpact PLF2023",
    "col_to_plot": {
        "y": "rfr_lex_mean",
        "width": "bucket_count",
        "y_lib": "Moyenne",
    },
}

title = (
    "Moyenne de "
    + aggm_c.aggregate.description.lower()
    + ", par décile de foyer<br><sup>Source "
    + "POTE 2020 et ERFS 2018"
    + "</sup>"
)
plot_distribution(
    data1, data2, data3, replace_num_quantile_by_bound=True, log=False, title=title
)
df_decile_base_lex_plf2023
quantile_index lower_bound upper_bound bucket_count bucket_sum bucket_mean bucket_stdev rfr_lex_sum rfr_lex_mean rfr_lex_count_sample rfr_lex_count
0 0.00 0.00 2,264.00 3,981,822.00 1,069,235,083.00 268.53 569.38 1,100,346,752.00 205.18 7,631.00 5,362,759.00
1 1.00 2,264.00 8,816.00 3,981,823.00 23,667,669,211.00 5,943.93 1,826.41 20,231,571,456.00 5,841.10 4,897.00 3,463,657.00
2 2.00 8,816.00 12,854.00 3,981,823.00 43,576,621,785.00 10,943.89 1,150.43 37,150,617,600.00 11,013.40 4,790.00 3,373,219.00
3 3.00 12,854.00 16,199.00 3,981,822.00 58,390,804,988.00 14,664.34 927.05 40,729,108,480.00 14,608.43 3,967.00 2,788,054.50
4 4.00 16,199.00 19,450.00 3,981,823.00 70,800,632,956.00 17,780.96 935.29 62,209,150,976.00 17,851.86 4,883.00 3,484,743.00
5 5.00 19,450.00 23,865.00 3,981,823.00 85,383,203,814.00 21,443.24 1,239.14 88,530,632,704.00 21,592.07 5,788.00 4,100,146.50
6 6.00 23,865.00 30,112.00 3,981,822.00 107,325,704,831.00 26,953.92 1,746.79 113,460,436,992.00 26,848.62 5,960.00 4,225,932.50
7 7.00 30,112.00 38,713.00 3,981,823.00 135,809,071,429.00 34,107.26 2,464.09 157,940,744,192.00 34,141.69 6,597.00 4,626,038.00
8 8.00 38,713.00 54,548.00 3,981,823.00 181,489,645,465.00 45,579.54 4,501.04 218,267,910,144.00 45,412.88 6,764.00 4,806,300.00
9 9.00 54,548.00 144,609,869.00 3,981,823.00 396,160,978,027.00 99,492.36 273,769.98 361,383,165,952.00 89,018.82 5,658.00 4,059,626.50

Sommes de RFR, par décile

data1 = {
    "df": df_decile_rfr_2020,
    "trace_name": "POTE 2020",
    "col_to_plot": {
        "y": "bucket_sum",
        "width": "bucket_count",
        "y_lib": "Somme",
    },
}
data2 = {
    "df": df_decile_base_lex_plf2022,
    "trace_name": "Base LexImpact PLF2022",
    "col_to_plot": {
        "y": "rfr_lex_sum",
        "width": "bucket_count",
        "y_lib": "Somme",
    },
}
data3 = {
    "df": df_decile_base_lex_plf2023,
    "trace_name": "Base LexImpact PLF2023",
    "col_to_plot": {
        "y": "rfr_lex_sum",
        "width": "bucket_count",
        "y_lib": "Somme",
    },
}

title = (
    "Somme de "
    + aggm_c.aggregate.description.lower()
    + ", par décile de foyer<br><sup>Source "
    + "POTE 2020, base LexImpact"
    + "</sup>"
)
plot_distribution(
    data1, data2, data3, replace_num_quantile_by_bound=True, log=False, title=title
)

Comparaison déciles

data1 = {
    "df": df_decile_rfr_2020,
    "trace_name": "POTE 2020",
    "col_to_plot": {
        "y": "upper_bound",
        "width": "bucket_count",
        "y_lib": "Frontière",
    },
}
data2 = {
    "df": df_decile_plf2023,
    "trace_name": "Base LexImpact PLF2023",
    "col_to_plot": {
        "y": "rfr_upper_bound",
    },
}

title = (
    "Frontières de "
    + aggm_c.aggregate.description.lower()
    + ", par décile de foyer<br><sup>Source "
    + "POTE 2020 et ERFS 2018"
    + "</sup>"
)
plot_distribution(
    data1, data2, replace_num_quantile_by_bound=True, log=True, title=title
)

Moyenne des salaires

# Chargement des données
year = "2020"
aggm_c = AggregateManager(aggregates_path=aggregates_path)
aggm_c.load_aggregate(
    "POTE", "salaire_imposable", year=str(year), data_structure=DataStructure.DECILE
)
for d in aggm_c.aggregate.data:
    if d.data_structure == DataStructure.DECILE:
        print(type(d.date), year)
        if d.date == year:
            break
else:
    raise Exception()
decile = d
df_decile_2020 = pd.DataFrame(decile.values)
# Affichage
data1 = {
    "df": df_decile_2020,
    "trace_name": "POTE 2020",
    "col_to_plot": {
        "y": "upper_bound",
        "width": "bucket_count",
        "y_lib": "Moyenne",
    },
}
plot_distribution(
    data1,
)
<class 'str'> 2020
<class 'str'> 2020
df_decile_2020
quantile_index lower_bound upper_bound bucket_count bucket_sum bucket_mean bucket_stdev width
0 1 0.00 0.00 3981822 0.00 0.00 0.00 0.80
1 2 0.00 0.00 3981823 0.00 0.00 0.00 0.80
2 3 0.00 0.00 3981823 0.00 0.00 0.00 0.80
3 4 0.00 0.00 3981822 0.00 0.00 0.00 0.80
4 5 0.00 6,738.00 3981823 9,741,497,712.00 2,446.49 2,150.20 0.80
5 6 6,738.00 15,728.00 3981823 45,621,285,274.00 11,457.39 2,682.41 0.80
6 7 15,728.00 21,134.00 3981822 73,479,772,858.00 18,453.81 1,535.14 0.80
7 8 21,134.00 28,635.00 3981823 97,557,781,901.00 24,500.78 2,141.25 0.80
8 9 28,635.00 44,526.00 3981823 141,491,060,553.00 35,534.24 4,562.56 0.80
9 10 44,526.00 34,589,257.00 3981823 288,652,561,457.00 72,492.56 61,068.54 0.80