Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

概要

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

Github

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

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

使い方

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

# 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())
出力
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)しか与えていませんが、扶養家族がいたり障害者である場合は控除されるので、引数を指定することでそういったケースも計算可能です。
では、個々について順番に説明していきます。

給与所得

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

(収入) - (経費) = (所得) 

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

スクリーンショット 2020-06-28 15.52.26.png

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

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%なので、それらを足し合わせて保険料率を計算します。

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)はふるさと納税をする場合の計算にも使います。

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

住民税

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

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

手取り

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

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円のみが自己負担で、残りの金額すべてを控除にあてることができます。
以下の関数では控除に全額あてることができる寄付の金額の上限を計算しています。
計算式はコメントやコードを参考にしてください。

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します。

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に突っ込みます。

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()とかで中身を見れます。

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

棒グラフで可視化します。

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

グラフの説明

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

グラフを見た僕の感想

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

まとめ

  • Pythonを使って税金や手取りを計算するクラスを作り、可視化してみた
  • 計算や解釈の誤りがあれば随時直す予定なので、もし見つけた方がいたら教えてもらえると嬉しいです
tetsuro731
都内でエンジニアやってるマン
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away