【2020年度版】税金と手取りの計算を全部Pythonにやらせてみる

## 概要
税金の計算って難しいですよね。
社会人になると毎年なんとなく税金やら保険料やらが引かれてますが、僕は税金について全然詳しくないのでなにがなんやらという状態です。
さらに聞いた話だと今年から控除やら所得税やらのルールが変わるみたいです。
「**退屈なことは全部Pythonにやらせよう**」とう格言（？）があるので、今回は勉強を兼ねて`Python`で税金計算用のクラスを作ってみようと思います。
ゼロからいろいろ調べながら書いたので知ってる人にとっては当たり前の説明が多いかもしれません。


## Github
`Github`に税金計算用のクラスを作ってあげました。

- https://github.com/tetsuro731/Tax

コードを書くにあたって参考にしたサイト

- https://punhundon-lifeshift.com/tax_calc_by_python

## 使い方
税金の難しい話をする前に、まずは簡単に使い方を説明しようと思います。
今回作った`Tax`クラスは`tax.py`の中で実装されています。
例として**年収500万の独身男性の場合**を考えます。
親のディレクトリに`tax.py`がある状態で以下を実行します。

``` Python
# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定
from common.tax import Tax

gross_salary = 5000000
tax = Tax(gross_salary)
print("gross_salary, income = ", tax.gross_salary, tax.income)
print("income_tax, inhabitant_tax, insurance_premiun = ", tax.income_tax(), tax.inhabitant_tax(), tax.social_insurance_premium())
print("net_salary = ", tax.net_salary())
print("max_hurusato_donation = ", tax.max_hurusato_donation())
```

```Bash:出力
gross_salary, income =  5000000 3560000.0
income_tax, inhabitant_tax, insurance_premiun =  110575.0 215575.0 619249.9999999999
net_salary =  4054600.0
max_hurusato_donation =  56035.593432760994
```

- **gross_salary** : 収入
- **income** : 給与所得
- **inhabitant_tax** : 住民税
- **income_tax** : 所得税
- **insurance_premium** : 社会保険料
- **net_salary** : 手取り
- **max_hurusato_donation** : ふるさと納税で自己負担2000円で全額控除できる上限

です。このケースだと**額面が500万円、税金や保険料などでいろいろ引かれて手取りがだいたい400万円くらい**ってことです。
上の例だと`tax`の引数は収入（`=gross_salary`）しか与えていませんが、**扶養家族**がいたり**障害者**である場合は控除されるので、引数を指定することでそういったケースも計算可能です。
では、個々について順番に説明していきます。

## 給与所得

まずは**給与所得**についてです。僕は税金に関して無知だったので、「なんとなく収入から税金が引かれて手取りが減る」ことまでは理解していたものの、**給与所得**とはなんぞ？という状態でした。
実は諸々の税金は額面の収入から直接計算されるわけではなく、**給与所得控除**という控除が行われた後の金額に適用されます。
今回は会社員を前提で話していますが、本来仕事をするときには必要経費が発生するので

```
(収入) - (経費) = (所得) 
```
の図式が成り立ちます。雇われの身である会社員の場合はあまりピンとこないかもしれませんが、働いていれば経費にあたる出費があるだろうという前提で、**すべての会社員が収入から引かれます。**
ちなみにこれは**源泉徴収表**にも会社からの額面の収入のとなりに**給与所得控除後の金額**という名前で控除後の金額が記載されています↓

<img width="664" alt="スクリーンショット 2020-06-28 15.52.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547532/b57aa974-2600-16ea-18df-2b11215491c9.png">

`Python`のコードは以下になります。
2020年以降はルールが変わってこの**給与所得控除**が10万円減り、のちに出てくる**所得税**が10万円増えました。
なのでプラマイゼロで引かれる金額は変わらないのですが、年収850万円以上の人は今回の改正で払う金額が多くなっています。
僕は年収850万もないですが、個人的には頑張って年収が増えても所得税でいっぱい引かれると思うとモチベーションがいまいち上がらないのでこの改正は別に嬉しくはないですね。。
こうして計算した給与所得控除後の金額を`income`として返します。
この`income`の値は他のクラス関数でもよく使うので、コンストラクタの中で`self.income`に代入しています。

``` Python:Tax.income()
def income(self):
    """
    給与所得控除の計算, 収入を引数として控除額を返す
    2020年以降は控除が10万減額し、所得税で10万増えたので実質変わらない
    ただし、850万以上は給与所得控除の額が減ったで実質的には増税
    """
    employment_income_deduction = 0

    if self.gross_salary < 550000:
        employment_income_deduction = self.gross_salary

    elif self.gross_salary <1800000:
        employment_income_deduction = self.gross_salary * 0.4 - 100000

    elif self.gross_salary <3600000:
        employment_income_deduction = self.gross_salary*0.3 + 80000

    elif self.gross_salary <6600000:
        employment_income_deduction = self.gross_salary*0.2 + 440000

    elif self.gross_salary <8500000:
        employment_income_deduction = self.gross_salary*0.1 + 1100000

    else:
        employment_income_deduction = 1950000

    income = self.gross_salary - employment_income_deduction
    return income

```

## 社会保険料

次に**社会保険料**について見ていきます。
これは税金とは別枠の**厚生年金**とか**雇用保険**とかそのへんです。
計算式は以下に書いていますが、**健康保険料率**と**免除保険料率**、**雇用保険料率**なるものが出てきますね。
これらから計算した**保険料率**を収入にかけたものが最終的な保険料になります。
**健康保険料率**は地域によって違いますが、東京の場合は`9.87%`なので、
`self.health_insurance_premium_rate`にはデフォルトで`0.0987`が入っています。
免除保険料率は厚生年金がどれくらい免除されるかを決めるものです。
免除保険料率は年齢と共に上がる傾向がありますが、平均で`0.4%`くらいなので`self.rebate_contribution_rate`はデフォルトで`0.04`です。
これらの値はコンストラクタで個別に設定可能です。
これらの値が2で割られているのは会社と半分ずつ負担しているためです。
**雇用保険料率**は一律`0.3%`なので、それらを足し合わせて保険料率を計算します。

``` Python:Tax.social_insurance_preium()
def social_insurance_premium(self):
    """
    保険料の計算
    保険料率 ＝ 健康保険料率/2
    + (厚生年金保険料率18.3%-免除保険料率)/2
    + 雇用保険料率0.3%
    """
    # 保険料率
    insurance_premium_rate = (self.health_insurance_premium_rate)/2 \
                             + (0.183 - self.rebate_contribution_rate)/2 \
                             + 0.003

    # 社会保険料 = 年収 x 保険料率
    social_insurance_premium = self.gross_salary*insurance_premium_rate
    return social_insurance_premium
```
## 所得税
次に**所得税**です。
**所得税**は`income()`で計算した所得からまず**基礎控除**を引きます。
**基礎控除**は今までは一律`38万円`でしたが、2020年からは`48万円`に引き上げられました。
（上でも述べたようにその分**給与所得控除**が10万円引き下げられました。）
ただし、今回から新しく加わったルールとして年収2400万を超えると段階的に基礎控除の額が減り、2500万円を越えるとゼロになります。
さらにそこから扶養控除（`dependents_deduction`）、障害者控除（`handicapped_deduction`）が引かれます。
コンストラクタで特に指定しない場合は`dependents_deductionもhandicapped_deduction`もゼロに設定されています。

こうして諸々の控除された後の所得を`target_of_income_tax`とし、ここから**所得税**を計算します。
年収が高いほどたくさん取られる仕組みになっています。
なお、ここで出てくる**所得税率**（`self.income_tax_rate`）は**ふるさと納税**をする場合の計算にも使います。


``` Python:Tax.income_tax()
def income_tax(self):
    """
    所得税の計算
    """

    # 所得税における扶養控除
    dependents_deduction = self.high_school_student * 480000 + self.college_student * 630000
    # 所得税における障害者控除
    handicapped_deduction = self.handicapped * 260000
    # 基礎控除、2019年までは一律38万円だったが、2020年からは48万円に。ただし2000万を超えると段階的に減る
    basic_deduction = 0
    if self.income < 24000000:
        basic_deduction = 480000
    elif self.income < 24500000:
        basic_deduction = 320000
    elif self.income < 25000000:
        basic_deduction = 160000

    # 所得税の対象となる金額、所得から控除や保険料を引いたもの
    target_of_income_tax = (self.income \
                            - self.social_insurance_premium() \
                            - self.spousal_deduction() \
                            - dependents_deduction \
                            - handicapped_deduction \
                            - basic_deduction)
    # 年収別の所得税率と控除額
    if target_of_income_tax < 1950000:
        self.income_tax_rate = 0.05
        deduction = 0

    elif target_of_income_tax < 3300000:
        self.income_tax_rate = 0.1
        deduction = 97500

    elif target_of_income_tax < 6950000:
        self.income_tax_rate = 0.2
        deduction = 427500

    elif target_of_income_tax < 9000000:
        self.income_tax_rate = 0.23
        deduction = 636000

    elif target_of_income_tax < 18000000:
        self.income_tax_rate = 0.33
        deduction = 1536000

    elif target_of_income_tax < 40000000:
        self.income_tax_rate = 0.40
        deduction = 2796000

    else:
        self.income_tax_rate = 0.45
        deduction = 479.6

    # 所得税の計算
    income_tax = target_of_income_tax * self.income_tax_rate - deduction
    # 所得税がマイナスになった場合はゼロにする
    if income_tax <= 0:
        income_tax = 0
    return income_tax
```
## 住民税

**住民税**の計算は所得税と似ているので、所得税の仕組みがわかればそれほど難しくないと思います。
**所得税**とは控除の額が違う他、前年度の収入に対して税金がかかる点でも違います。
（プログラム上では前年度、今年度の区別は特にしていません）

``` Python:Tax.inhabitant_tax()
def inhabitant_tax(self):
    """
    住民税の計算, 課税所得を引数に住民税を計算する
    """

    # 住民税における扶養控除
    dependents_deduction = self.high_school_student * 330000 + self.college_student * 450000
    # 住民税における障害者控除
    handicapped_deduction = self.handicapped * 270000
    # 基礎控除、所得税と同様2020年から変更
    basic_deduction = 0
    if self.income < 24000000:
        basic_deduction = 430000
    elif self.income < 24500000:
        basic_deduction = 190000
    elif self.income < 25000000:
        basic_deduction = 150000

    # 所得から各種控除、基礎控除（43万円）を引き、税率10%をかける
    # さらに均等割5000円を足して、調整控除2500円を引く
    inhabitant_tax = (self.income
                      - self.social_insurance_premium()
                      - self.spousal_deduction()
                      - dependents_deduction
                      - handicapped_deduction
                      - basic_deduction) * 0.1 + 5000 - 2500

    # 計算した住民税がマイナスになった場合はゼロとする
    if inhabitant_tax <=0:
        inhabitant_tax = 0
    return inhabitant_tax
```


## 手取り
ここまでくれば**手取り**を計算することができます。
額面の収入から今まで計算してきた**社会保険料、所得税、住民税**を引きます。

``` Python:Tax.net_salary()
def net_salary(self):
    """
    手取りの計算、収入から所得税、住民税、社会保険料を引く
    """
    total_tax = self.inhabitant_tax() + self.income_tax()
    net_salary = self.gross_salary - total_tax - self.social_insurance_premium()
    return net_salary

```
## ふるさと納税

今まで出てきたものとは少し毛色が違いますが、**ふるさと納税**についても実装しました。
**ふるさと納税**は地方に寄付することで返礼品を受け取れるというシステムです。
その際に寄付に応じて**所得税、住民税**を減税することができます。
上限額までは寄付した金額のうち`2000円`のみが自己負担で、残りの金額すべてを控除にあてることができます。
以下の関数では控除に全額あてることができる寄付の金額の上限を計算しています。
計算式はコメントやコードを参考にしてください。


``` Python:Tax.max_hurusato_donation()
    def max_hurusato_donation(self):
        """
        ふるさと納税で自己負担2000円で全額控除される上限の計算
        言い換えるとreturnの金額から2000円引いたものが所得税および住民税から控除される
        """
        # 住民税所得割額(=住民税)から計算する
        # ふるさと納税控除額の上限
        hurusato_deduction = self.inhabitant_tax() * 0.2

        # (控除金額) =（寄附金額-2000）×（90％-所得税の税率×1.021）
        # (寄付金額) = (控除金額)/(90％-所得税の税率×1.021)+2000
        max_hurusato_donation = hurusato_deduction / (0.9 - self.income_tax_rate * 1.021) + 2000
        return max_hurusato_donation
```
## 可視化
これだけだと`Python`で書く意味ある？と言われてしまいそうなので、`matplotlib`を使って可視化してみます。
まずは必要なライブラリを`import`します。

``` Python:Tax.show_ipynb
# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定
from common.tax import Tax
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import seaborn as sns
%matplotlib inline
pd.options.display.precision = 0
plt.rcParams['font.family'] = 'AppleGothic'
```

年収200-1200万円まで100万円刻みで計算し、`list`に突っ込みます。

``` Python:Tax.show_ipynb2
# 額面年収、200〜1,200万まで1万刻みで
gross_salaries = [i for i in range(2000000,12010000, 1000000)]
# 所得
incomes = []
# 税金
total_taxes = []
# 住民税
inhabitant_taxes = []
# 所得税
income_taxes = []
#社会保険料（=社会保険料控除）
social_insurance_premiums = []
# 手取り年収
net_salaries = []
# ふるさと納税控除上限とそのときの寄付額
max_hurusato_donation = []

for gross_salary in gross_salaries:
    tax = Tax(gross_salary)

    # リストに値を追加
    incomes.append(tax.income)
    total_taxes.append(tax.income_tax() + tax.inhabitant_tax())
    inhabitant_taxes.append(tax.inhabitant_tax())
    income_taxes.append(tax.income_tax())
    social_insurance_premiums.append(tax.social_insurance_premium())
    net_salaries.append(tax.net_salary())
    max_hurusato_donation.append(tax.max_hurusato_donation() - 2000) #自己負担2000円を引く
```

`dataframe`に格納します。`df.head()`とかで中身を見れます。

``` Python:Tax.show_ipynb3
df = pd.DataFrame()
df['年収'] = gross_salaries
df['手取り'] = net_salaries
df['税金'] = total_taxes
df['住民税'] = inhabitant_taxes
df['所得税'] = income_taxes
df['社会保険料'] = social_insurance_premiums
df['ふるさと納税控除上限'] = max_hurusato_donation
```
棒グラフで可視化します。


``` Python:Tax.show_ipynb4

df.index = ['200', '300', '400', '500', '600', '700',  '800', '900', '1000', '1100', '1200']
plt.figure(figsize=(12,7))
plt.rcParams["font.size"] = 14
plt.grid(axis='y')
yticks = [0, 1000000, 2000000, 3000000, 4000000, 5000000, 6000000, 7000000, 8000000, 9000000, 10000000, 11000000, 12000000]
plt.ylim(0, 12500000)
plt.yticks(yticks)
plt.bar(df.index, df['手取り'])
plt.bar(df.index, df['税金'], bottom= df['手取り'])
plt.bar(df.index, df['ふるさと納税控除上限'], bottom= df['手取り'] + df['税金'] - df['ふるさと納税控除上限'])
plt.bar(df.index, df['社会保険料'], bottom= df['手取り'] + df['税金'])
plt.xlabel('Salary (yen*10000)')
plt.ylabel('Breakdown (yen)')
plt.title('')
plt.legend(['net-salary', 'tax','hurusato_deduction', 'insurance'])
plt.show()
```

![ダウンロード (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547532/ac8a5590-e109-71f2-dd35-206101a90dc0.png)

**グラフの説明**

- 横軸が年収、縦軸のうち青が手取り、(オレンジ+緑)が税金で、緑がそのうちふるさと納税で控除できる上限、赤が社会保険料

**グラフを見た僕の感想**

- 年収800万円くらいまでは税金よりも社会保険料の方が多いが、それ以上だと税金の方が多くなってくる
- 今の日本が高額納税者（=高収入の人）に支えられていることがわかる
- 年収1000万円でも手取り700万ちょっとしかもらえないのか...
- ふるさと納税はやった方が良い

## まとめ
- Pythonを使って税金や手取りを計算するクラスを作り、可視化してみた
- 計算や解釈の誤りがあれば随時直す予定なので、もし見つけた方がいたら教えてもらえると嬉しいです