Pythonに限らず、for文とif文を使うとさまざまなプログラムを作れるようになります。
そして、defにより関数とすることで、さまざまな条件における出力を短いコードで出せることができるため、条件を変えたシミュレーションが簡単に行えるようになります。
ここでは、額面年収が変わった場合に手取り年収、税金がどのようになるかをシミュレートできるPythonプログラムを作ってみます。家族構成の違いも反映できる内容となっています。
まずは計算の流れ
額面年収から給与所得控除を引いたものが「所得」になります。ここから、住民税と所得税を計算します。
住民税は、「所得」から諸々の控除を引いたものに住民税率を掛け算して算出できます。所得税も同様で、最後に所得税率を掛け算して算出できます。住民税と所得税では計算式が少し異なります。
控除は、家族構成の違いで額が変わってきます。今回は触れませんが、生命保険、地震保険への加入により控除となるものもあります。
そして、額面年収から住民税と所得税、そして社会保険料を引いたものが手取り年収になります。
Pythonコード(計算)
まずは必要なライブラリをインポートします。
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
%matplotlib inline
import seaborn as sns
次に、pandasの表に表示される数値を整数にするコードを書きます。
pd.options.display.precision = 0
健康保険料率と免除保険料率をあらかじめ設定する
健康保険料率は、例えば東京都(令和2年度)なら9.87%になります。免除保険料率とは、厚生年金基金によって2.4〜5.0%の範囲で決められるもので、今回は暫定で3%とします。
# 健康保険料率
health_insurance_premium_rate = 0.0987
# 免除保険料率
rebate_contribution_rate = 0.03
関数を定義する
額面年収から税金や手取り年収を計算する関数を定義します。名前はcalc()とします。
引数は、配偶者、高校生の子ども、大学生の子ども、障害のある家族の人数とし、それぞれpartner、high_school_student、college_student、handicappedとします。
その後、200から1,200まで1刻みで額面年収(万円)を設定します。所得や税金などの空リストも作っておきます。
def calc(partner, high_school_student, college_student, handicapped):
# 額面年収(万円)、200〜1,200まで1刻みで
gross_salaries = [i for i in range(200,1201)]
# 所得
incomes = []
# 税金
total_taxes = []
# 住民税
inhabitant_taxes = []
# 所得税
income_taxes = []
#社会保険料(=社会保険料控除)
social_insurance_premiums = []
# 手取り年収
net_salaries = []
あとは、以下の通り、ひたすらfor文とif文でコードを書いていきます。
まずは、給与所得控除を求めてから、額面年収から引き算することで所得を求めます。次に、社会保険料(=社会保険料控除)を求めます。そして、住民税、所得税ごとに各種控除を算出し、所得から引いたあと、税率を掛けて住民税、所得税を計算します。
for gross_salary in gross_salaries:
# 給与所得控除の計算
if gross_salary < 65:
employment_income_deduction = gross_salary
elif gross_salary >= 65 and gross_salary <180:
employment_income_deduction = gross_salary*0.4
elif gross_salary >=180 and gross_salary <360:
employment_income_deduction = gross_salary*0.3 + 18
elif gross_salary >=360 and gross_salary <660:
employment_income_deduction = gross_salary*0.2 + 54
elif gross_salary >=660 and gross_salary <1000:
employment_income_deduction = gross_salary*0.1 +120
else:
employment_income_deduction = 220
# 所得の計算
income = gross_salary - employment_income_deduction
# 保険料率
insurance_premium_rate = (health_insurance_premium_rate)/2 \
+ (0.183 - rebate_contribution_rate)/2 \
+ 0.003
'''
保険料率 = 健康保険料率/2
+ (厚生年金保険料率18.3%-免除保険料率)/2
+ 雇用保険料率0.3%
'''
# 社会保険料の計算
social_insurance_premium = gross_salary*insurance_premium_rate
'''
社会保険料 = 年収 x 保険料率
'''
# 配偶者控除の計算
if partner == 1:
if income <= 900:
spousal_deduction = 38
elif income > 900 and income <= 950:
spousal_deduction = 26
elif income > 950 and income <= 1050:
spousal_deduction = 13
else:
spousal_deduction = 0
else:
spousal_deduction = 0
# 住民税の扶養控除の計算
dependents_deduction_of_inhabitant_tax = high_school_student*33 + college_student*45
# 所得税の扶養控除の計算
dependents_deduction_of_income_tax = high_school_student*38 + college_student*63
# 住民税の障害者控除の計算
handicapped_deduction_of_inhabitant_tax = handicapped*27
# 所得税の障害者控除を計算する。
handicapped_deduction_of_income_tax = handicapped*26
'''
住民税の一般障害者控除は27万円、所得税の一般障害者控除は26万円
'''
# 住民税の計算
inhabitant_tax = (income
- social_insurance_premium
- spousal_deduction
- dependents_deduction_of_inhabitant_tax
- handicapped_deduction_of_inhabitant_tax
- 33)*0.1 + 0.5 - 0.25
'''
所得から各種控除、基礎控除(33万円)を引き、税率10%をかける
さらに均等割5000円を足して、調整控除2500円を引く
'''
# 計算した住民税がマイナスになった場合はゼロとする
if inhabitant_tax <=0:
inhabitant_tax = 0
# 所得から各種控除、基礎控除(38万円)を引いたもの
target_of_income_tax = (income
- social_insurance_premium
- spousal_deduction
- dependents_deduction_of_income_tax
- handicapped_deduction_of_income_tax
- 38)
# 所得税率
if target_of_income_tax < 195:
income_tax_rate = 0.05
deduction = 0
elif target_of_income_tax >= 195 and target_of_income_tax < 330:
income_tax_rate = 0.1
deduction = 9.75
elif target_of_income_tax >= 330 and target_of_income_tax < 695:
income_tax_rate = 0.2
deduction = 42.75
elif target_of_income_tax >= 695 and target_of_income_tax < 900:
income_tax_rate = 0.23
deduction = 63.6
elif target_of_income_tax >= 900 and target_of_income_tax < 1800:
income_tax_rate = 0.33
deduction = 153.6
elif target_of_income_tax >= 1800 and target_of_income_tax < 4000:
income_tax_rate = 0.40
deduction = 279.6
else:
income_tax_rate = 0.45
deduction = 479.6
# 所得税の計算
income_tax = target_of_income_tax*income_tax_rate - deduction
'''
課税対象額に所得税率をかけて、控除を引く
'''
# 計算した所得税がマイナスになる場合はゼロとする。
if income_tax <= 0:
income_tax = 0
# 税金の計算
total_tax = inhabitant_tax + income_tax
# 手取り年収の計算
net_salary = gross_salary - total_tax - social_insurance_premium
# リストに値を追加
incomes.append(income)
total_taxes.append(total_tax)
inhabitant_taxes.append(inhabitant_tax)
income_taxes.append(income_tax)
social_insurance_premiums.append(social_insurance_premium)
net_salaries.append(net_salary)
最後に、額面年収、手取り年収、税金、住民税、所得税、社会保険料からなるdataframeを返すプログラムにします。
df = pd.DataFrame()
df['年収'] = gross_salaries
df['手取り'] = net_salaries
df['税金'] = total_taxes
df['住民税'] = inhabitant_taxes
df['所得税'] = income_taxes
df['社会保険料'] = social_insurance_premiums
return df
関数を実行してみる
早速、関数を実行してみます。例えば、独身の場合、次のようになります。
#独身の場合
calc(0,0,0,0).head()

Pythonコード(可視化)
額面年収の内訳を棒グラフで可視化する
額面年収の内訳を100万円刻みの棒グラフで可視化してみます。
額面年収を100で割ったときの余り(calc(0,0,0,0)[‘年収’].values % 100)が0になるものだけをdata1に格納してから、data1をグラフ化します。
data1 = calc(0,0,0,0)[calc(0,0,0,0).index.values%100 == 0]
data1.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, 100, 200, 300, 400, 500, 600, 700, 800, 900,
1000, 1100, 1200]
plt.ylim(0, 1250)
plt.yticks(yticks)
plt.bar(data1.index, data1['手取り'])
plt.bar(data1.index, data1['税金'], bottom= data1['手取り'])
plt.bar(data1.index, data1['社会保険料'],
bottom= data1['手取り'] + data1['税金'])
plt.xlabel('年収(万円)')
plt.ylabel('構成(万円)')
plt.title('独身')
plt.legend(['手取り', '税金', '社会保険料'])
plt.show()

額面年収が増えるほど、税金や社会保険料も増えていることがわかります。
続いて、パーセント表示をしてみます。
data1 = calc(0,0,0,0)[calc(0,0,0,0)['年収'].values%100 == 0]
data1.index = ['200', '300', '400', '500', '600', '700',
'800', '900', '1000', '1100', '1200']
plt.figure(figsize=(12,7))
plt.grid(axis='y')
plt.ylim(0, 100)
plt.rcParams["font.size"] = 14
plt.bar(data1.index, data1['手取り']/data1['年収']*100)
plt.bar(data1.index, data1['税金']/data1['年収']*100,
bottom= data1['手取り']/data1['年収']*100)
plt.bar(data1.index, data1['社会保険料']/data1['年収']*100,
bottom= (data1['手取り'] + data1['税金'])/data1['年収']*100)
plt.xlabel('年収(万円)')
plt.ylabel('構成(%)')
plt.title('独身')
plt.legend(['手取り', '税金', '社会保険料'])
plt.show()

額面年収が増えるほど税金の割合が高くなり、手取り率が低下していることがわかります。独身の場合、手取りは額面年収の7~8割といったところです。
家族構成ごとの手取り年収の違いを比較する
家族構成の違いによって、手取り年収がどのくらい変わってくるのかをグラフで比較します。独身の場合、既婚の場合、既婚かつ大きな子どもが2人(高校生1人、大学生1人)いる場合、さらに障害を持つ家族がいる場合、の4ケースを考えます。
まずは手取り年収を比較します。
# 独身
data1 = calc(0,0,0,0)
# 既婚
data2 = calc(1,0,0,0)
# 既婚+高校生1人+大学生1人
data3 = calc(1,1,1,0)
# 既婚+高校生1人+大学生1人+障害のある家族1人
data4 = calc(1,1,1,1)
xticks = [200,300,400,500,600,700,800,900,1000,1100,1200]
yticks = [100,200,300,400,500,600,700,800,900]
plt.rcParams["font.size"] = 14
plt.figure(figsize=(12, 7))
plt.xlim(200,1200)
plt.xticks(xticks)
plt.ylim(100,900)
plt.yticks(yticks)
plt.grid()
sns.lineplot(x='年収', y='手取り', data=data1, color='red')
sns.lineplot(x='年収', y='手取り', data=data2, color='blue')
sns.lineplot(x='年収', y='手取り', data=data3, color='green')
sns.lineplot(x='年収', y='手取り', data=data4, color='orange')
plt.xlabel('年収(万円)')
plt.ylabel('手取り(万円)')
plt.title('手取り比較')
plt.legend(['独身', '既婚', '既婚+大きな子どもx2', '既婚+大きな子どもx2+障害'])
plt.show()

独身よりも既婚、子どもがいないよりもいる方が手取り年収が高くなることがわかります。障害の家族がいる場合も同様です。
続いて、税金の比較です。
xticks = [200,300,400,500,600,700,800,900,1000,1100,1200]
yticks = [50, 100, 150, 200]
plt.rcParams["font.size"] = 14
plt.figure(figsize=(12, 7))
plt.xlim(200,1200)
plt.xticks(xticks)
plt.ylim(0,200)
plt.yticks(yticks)
plt.grid()
sns.lineplot(x='年収', y='税金', data=data1, color='red')
sns.lineplot(x='年収', y='税金', data=data2, color='blue')
sns.lineplot(x='年収', y='税金', data=data3, color='green')
sns.lineplot(x='年収', y='税金', data=data4, color='orange')
plt.xlabel('年収(万円)')
plt.ylabel('税金(万円)')
plt.title('税金比較')
plt.legend(['独身', '既婚', '既婚+大きな子どもx2', '既婚+大きな子どもx2+障害'])
plt.show()

家族構成によって、税金の額が結構変わることが分かります。1年あたり数十万円はでかいですよね。
最後に、社会保険料の比較です。
xticks = [200,300,400,500,600,700,800,900,1000,1100,1200]
yticks = [50, 100, 150, 200]
plt.rcParams["font.size"] = 14
plt.figure(figsize=(12, 7))
plt.xlim(200,1200)
plt.xticks(xticks)
plt.ylim(0,200)
plt.yticks(yticks)
plt.grid()
sns.lineplot(x='年収', y='社会保険料', data=data1, color='red')
sns.lineplot(x='年収', y='社会保険料', data=data2, color='blue')
sns.lineplot(x='年収', y='社会保険料', data=data3, color='green')
sns.lineplot(x='年収', y='社会保険料', data=data4, color='orange')
plt.xlabel('年収(万円)')
plt.ylabel('社会保険料(万円)')
plt.title('社会保険料比較')
plt.legend(['独身', '既婚', '既婚+大きな子どもx2', '既婚+大きな子どもx2+障害'])
plt.show()

社会保険料は家族構成に依存しないことが確認できました。
まとめ
for文、if文を使えば、さまざまな計算を行えるようになります。また、def文を使うことで、条件が変わった場合のシミュレーションを簡単に行えるようになります。
今回は、税金を題材にPythonのプログラムを作成してみました。身近な題材でプログラムを書くとよい勉強になるかなと思います。