Python数据分析——(三)

用Python挖掘该不该使用花呗?怎么使用比较合理?

基于蒙特卡洛原理(使用随机数来解决计算问题),建立收入支出模型进行测算:
1.假设月薪1w,每个月平均奖金1500
2.当月全部花费都由花呗支付,当当月花呗欠款大于当月可支出收入时,就宣布“吃土”
3.现预设120个月(十年),如果十年都没有吃上土,就代表有了花呗随心浪

基本思路:
1.每月净收入模型
2.每月支出模型
3.每月花呗还款情况模拟
4.不同情况下(分期和不分期)花呗偿还额度的变化

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

1.构建每月净收入模型

净收入 = 月薪 - 五险一金 + 奖金 - 个人所得税
参考上海市五险一金缴纳系数和个税政策

# 个税计算函数

def tax(salary_sum):
    if salary_sum <= 3500:
        # 月薪低于3500元;
        return 0
    elif salary_sum <= (3500 + 1500):
        # 月薪在3500-4500元之间;
        return (salary_sum - 3500) * 0.03
    elif salary_sum <= (3500 + 1500 + 3000):
        # 月薪在4500-8000元之间;
        return 1500 * 0.03 + (salary_sum - 1500 - 3500) * 0.1
    elif salary_sum <= (3500 + 1500 + 3000 + 4500):
        # 月薪在8000-12500元之间;
        return 1500 * 0.03 + 3000 * 0.1 + (salary_sum - 3500 - 1500 - 3000) * 0.2
    elif salary_sum <= (3500 + 1500 + 3000 + 4500 + 26000):
        # 月薪在12500-38500元之间;
        return 1500 * 0.03 + 3000 * 0.1 + 4500 * 0.2 + (salary_sum - 3500 - 1500 - 3000 - 4500) * 0.25
    elif salary_sum <= (3500 + 1500 + 3000 + 4500 + 26000 + 20000):
        # 月薪在38500-58500元之间;
        return 1500 * 0.03 + 3000 * 0.1 + 4500 * 0.2 + 26000 * 0.25 + (salary_sum - 3500 - 1500 - 3000 - 4500 - 26000) * 0.3
    elif salary_sum <= (3500 + 1500 + 3000 + 4500 + 26000 + 20000 + 25000):
        # 月薪在58500-83500元之间;
        return 1500 * 0.03 + 3000 * 0.1 + 4500 * 0.2 + 26000 * 0.25 + 20000 * 0.3 + (salary_sum - 3500 - 1500 - 3000 - 4500 - 26000 - 20000) * 0.35
    else:
        # 月薪在83500元以上;
        return 1500 * 0.03 + 3000 * 0.1 + 4500 * 0.2 + 26000 * 0.25 + 20000 * 0.3 + 25000 * 0.35 + (salary_sum - 3500 - 1500 - 3000 - 4500 - 26000 - 20000 - 25000) * 0.45

test = 45000
print('函数构建完成,当月薪为%.1f元时,需要缴税%.2f元' % (test,tax(test)))

五险一金缴纳的系数总和是17.5%,上限基数是21396,所以高于21396的都应缴纳3744.58

# 五险一金函数

def insurance(salary):
    if salary <= 21396:
        return salary * 0.175
    else:
        return 3744.58

test = 15000
print('函数构建完成,当月薪为%.1f元时,需要缴五险一金%.2f元' % (test,insurance(test)))
# 奖金随机函数

def bonus(b_avg):
    # 预设10年的奖金,生成120个随机值
    return pd.Series(np.random.normal(loc = b_avg,scale = 200,size = 120))

print('函数构建完成,当奖金均值为1500时,随机数组为:')
print(bonus(1500)[:10])

plt.title('奖金随机函数 - 数据分布直方图')
plt.hist(bonus(1500),bins = 30)
plt.grid()

在这里插入图片描述

# 构建每月净收入函数

def final_income(s,b_avg):
    df_i = pd.DataFrame({
            '月薪':[s for i in range(120)],                                              # 月薪基数
            '五险一金':[insurance(s) for i in range(120)],                                # 计算五险一金
            '奖金':bonus(b_avg)                                                          # 计算奖金
        })
    df_i['计税部分'] = df_i['月薪'] + df_i['奖金']
    df_i['个人所得税'] = df_i['计税部分'].apply(lambda x : tax(x))                         # 计算个人所得税
    df_i['月净收入'] = df_i['月薪'] - df_i['五险一金'] + df_i['奖金'] - df_i['个人所得税']
    return df_i

# 测试当月收入1万,平均奖金1500元时的月净收入情况    
result = final_income(10000,1500)
result.head()

在这里插入图片描述

2.构建每月支出模型

基本生活支出:基本生活支出的变化不会太大,设定以3000元和3500元为限,均匀分布
购物支出 :设定为以5000元为均值,500元为标准差的正态分布
娱乐支出:设定以400元和1200元为限,均匀分布
学习支出:某在线平台课程价格大概在100元到500元不等。所以,这个也可以设定个均匀分布的模型
其他支出:每个月总会有些意外的,比如出门掉了个钱包等等。所以设定500元为均值,40元为标准差的正态分布模型
总支出 = 基本生活 + 购物 + 娱乐 + 学习 + 其他

# 基本生活支出

general_expense = pd.Series(np.random.randint(3000,3500,size=120))

plt.title('基本生活支出')
plt.hist(general_expense, bins = 30)
plt.grid()

在这里插入图片描述

# 购物支出

shopping = pd.Series(np.random.normal(loc=5000,scale=500,size=120))

plt.title('购物支出')
plt.hist(shopping, bins = 30)
plt.grid()

在这里插入图片描述

# 娱乐支出

entertainment = pd.Series(np.random.randint(400,1200,size=120))

plt.title('娱乐支出')
plt.hist(entertainment, bins = 30)
plt.grid()

在这里插入图片描述

# 学习支出

study = pd.Series(np.random.randint(100,500,size=120))

plt.title('学习支出')
plt.hist(study,bins = 30)
plt.grid()

在这里插入图片描述

# 其他支出

other = pd.Series(np.random.normal(loc=500,scale=40,size=120))

plt.title('其他支出')
plt.hist(other,bins = 30)
plt.grid()

在这里插入图片描述

# 构建每月支出函数

def final_expense():
    df_i = pd.DataFrame({
            '基本生活支出':np.random.randint(3000,3500,size=120),
            '购物支出':np.random.normal(loc=5000,scale=500,size=120),
            '娱乐支出':np.random.randint(400,1200,size=120),
            '学习支出':np.random.randint(100,500,size=120),
            '其他支出':np.random.normal(loc=500,scale=40,size=120)
        })
    df_i['月总支出'] = df_i['基本生活支出'] + df_i['购物支出'] + df_i['娱乐支出'] + df_i['学习支出'] + df_i['其他支出']
    return df_i
    
result = final_expense()
result[['基本生活支出','购物支出','娱乐支出','学习支出','其他支出']].iloc[:12].plot(kind='bar',
                                                              figsize = (12,4),
                                                              stacked = True,                 # stacked 堆叠
                                                              colormap = 'Reds_r')
plt.title('月总支出情况 - 前12月')
plt.grid()

result.head()

在这里插入图片描述

3.每月花呗还款情况模拟

几个条件:

  • 每月先还花呗欠款,再消费。
  • 所有的支出除还款外,都可以使用花呗透支。
  • 花呗信用总额度为1.5万

当这月的收入小于等于需要还款的金额,就代表你要吃土了
(当月还需借贷花呗金额 = 月支出 + 本月需还花呗 - 月初余额 - 月收入 )> 15000 时

# 创建120个月每月的月收入,月支出,月初余额,本月需还花呗

income = final_income(10000,1500)['月净收入'].tolist()
expense = final_expense()['月总支出'].tolist()
saving = [0 for i in range(120)]
debt = [0 for i in range(120)]

(1)不分期

# 先推导一下第二个月
if income[0] >= expense[0]:
    '''
    第一个月收入大于等于支出时:
    第二个月月初余额 = 第一个月收入 - 第一个月支出
    第二个月需还花呗 = 0
    '''
    saving[1] = income[0] - expense[0]
    debt[1] = 0
else:
    '''
    第一个月收入小于支出时:
    第二个月月初余额 = 0
    第二个月需还花呗 = 第一个月支出 - 第一个月收入
    '''
    saving[1] = 0
    debt[1] = expense[0] - income[0]
# 构建不分期时的函数模拟

income = final_income(10000,1500)['月净收入'].tolist()
expense = final_expense()['月总支出'].tolist()
saving = [0 for i in range(120)]
debt = [0 for i in range(120)]

def case_a():
    month = []
    data = []
    # 创建两个空列表,用于存放月份和每月数据
    
    for i in range(120):
        money = expense[i] + debt[i] - saving[i] - income[i]      # 当月还需借贷花呗金额 = 月支出 + 本月需还花呗 - 月初余额 - 月收入
        #print(money)
        if money > 15000:
            # 当月还需借贷花呗金额大于15000元时 → 破(吃)产(土)
            print('第%i个月花呗也救不了我了,要破(吃)产(土)了!\n-------' % (i+1))
            break
        else:
            # 当月还需借贷花呗金额小于等于15000元时 → 继续浪
            if money >= 0:
                saving[i+1] = saving[i] + income[i] - expense[i] - debt[i]
                debt[i+1] = 0
            else:
                saving[i+1] = 0
                debt[i+1] = expense[i] + debt[i] - income[i] - saving[i]
        month.append(i+1)
        data.append([income[i],expense[i],debt[i],saving[i+1],debt[i+1]])
    
    result_a = pd.DataFrame(data,columns=['月收入','月支出','本月需还花呗','本月余钱','欠债'],index = month)
    result_a.index.name = '月份'
    
    return result_a
# 不使用分期情况下,进行1万次模拟,查看吃土月份

month_case_a = []    
for i in range(10000): 
    print('正在进行第%i次模拟' % (i+1))
    income = final_income(10000,1500)['月净收入'].tolist()
    expense = final_expense()['月总支出'].tolist()
    saving = [0 for i in range(120)]
    debt = [0 for i in range(120)]
    result_a = case_a().index.max()
    month_case_a.append(result_a)

result_a = pd.Series(month_case_a)

plt.figure(figsize = (12,4))
result_a.hist(bins=15)
plt.title('第一回合:不可分期 - 模拟结果')

在这里插入图片描述
在不使用分期的情况下,会在第11-14个月左右时就吃土了。
(2)分期
花呗分期期数有4种,花呗分期手续费见下图:
在这里插入图片描述
分期当月不用还款,是从下个月开始还的。
函数构建的话在上面不分期的基础上增加分期的计算就行了

# 构建函数模拟 - 分期三月

income = final_income(10000,1500)['月净收入'].tolist()
expense = final_expense()['月总支出'].tolist()
saving = [0 for i in range(120)]
debt = [0 for i in range(120)]

def case_b():
    month = []
    data = []
    
    for i in range(120):
        money = expense[i] + debt[i] - saving[i] - income[i]      # 当月还需借贷花呗金额 = 月支出 + 本月需还花呗 - 月初余额 - 月收入
        #print(money)
        if money > 15000:
            # 当月还需借贷花呗金额大于15000元时 → 破(吃)产(土)
            print('第%i个月花呗也救不了我了,要破(吃)产(土)了!\n-------' % (i+1))
            break
        else:
            if money >= 0:
                saving[i+1] = saving[i] + income[i] - expense[i] - debt[i]
                debt[i+1] = 0
            else:
                money_per = (abs(money) * (1+0.025))/3        # 分期三月
                saving[i+1] = 0
                debt[i+1] = debt[i+1] + money_per
                debt[i+2] = debt[i+2] + money_per
                debt[i+3] = debt[i+3] + money_per
        month.append(i+1)
        data.append([income[i],expense[i],debt[i],saving[i+1],debt[i+1]])

    result_b = pd.DataFrame(data,columns=['月收入','月支出','本月需还花呗','本月余钱','欠债'],index = month)
    result_b.index.name = '月份'
    
    return result_b
# 构建函数模拟 - 分期六月

income = final_income(10000,1500)['月净收入'].tolist()
expense = final_expense()['月总支出'].tolist()
saving = [0 for i in range(120)]
debt = [0 for i in range(120)]

def case_c():
    month = []
    data = []
    # 创建两个空列表,用于存放月份和每月数据
    
    for i in range(120):
        money = expense[i] + debt[i] - saving[i] - income[i]      # 当月还需借贷花呗金额 = 月支出 + 本月需还花呗 - 月初余额 - 月收入
        #print(money)
        if money > 15000:
            # 当月还需借贷花呗金额大于15000元时 → 破(吃)产(土)
            print('第%i个月花呗也救不了我了,要破(吃)产(土)了!\n-------' % (i+1))
            break
        else:
            if money >= 0:
                saving[i+1] = saving[i] + income[i] - expense[i] - debt[i]
                debt[i+1] = 0
            else:
                money_per = (abs(money) * (1+0.045))/6        # 分期六月
                saving[i+1] = 0
                debt[i+1] = debt[i+1] + money_per
                debt[i+2] = debt[i+2] + money_per
                debt[i+3] = debt[i+3] + money_per
                debt[i+4] = debt[i+4] + money_per
                debt[i+5] = debt[i+5] + money_per
                debt[i+6] = debt[i+6] + money_per
        month.append(i+1)
        data.append([income[i],expense[i],debt[i],saving[i+1],debt[i+1]])
    
    result_c = pd.DataFrame(data,columns=['月收入','月支出','本月需还花呗','本月余钱','欠债'],index = month)
    result_c.index.name = '月份'
    
	return result_c
# 构建函数模拟 - 分期九月

income = final_income(10000,1500)['月净收入'].tolist()
expense = final_expense()['月总支出'].tolist()
saving = [0 for i in range(120)]
debt = [0 for i in range(120)]

def case_d():
    month = []
    data = []
    # 创建两个空列表,用于存放月份和每月数据
    
    for i in range(120):
        money = expense[i] + debt[i] - saving[i] - income[i]      # 当月还需借贷花呗金额 = 月支出 + 本月需还花呗 - 月初余额 - 月收入
        #print(money)
        if money > 15000:
            # 当月还需借贷花呗金额大于15000元时 → 破(吃)产(土)
            print('第%i个月花呗也救不了我了,要破(吃)产(土)了!\n-------' % (i+1))
            break
        else:
            if money >= 0:
                saving[i+1] = saving[i] + income[i] - expense[i] - debt[i]
                debt[i+1] = 0
            else:
                money_per = (abs(money) * (1+0.065))/9         # 分期九月
                saving[i+1] = 0
                debt[i+1] = debt[i+1] + money_per
                debt[i+2] = debt[i+2] + money_per
                debt[i+3] = debt[i+3] + money_per
                debt[i+4] = debt[i+4] + money_per
                debt[i+5] = debt[i+5] + money_per
                debt[i+6] = debt[i+6] + money_per
                debt[i+7] = debt[i+7] + money_per
                debt[i+8] = debt[i+8] + money_per
                debt[i+9] = debt[i+9] + money_per
        month.append(i+1)
        data.append([income[i],expense[i],debt[i],saving[i+1],debt[i+1]])
    
    result_d = pd.DataFrame(data,columns=['月收入','月支出','本月需还花呗','本月余钱','欠债'],index = month)
    result_d.index.name = '月份'
    
    return result_d
# 构建函数模拟 - 分期十二月

income = final_income(10000,1500)['月净收入'].tolist()
expense = final_expense()['月总支出'].tolist()
saving = [0 for i in range(120)]
debt = [0 for i in range(120)]

def case_e():
    month = []
    data = []
    # 创建两个空列表,用于存放月份和每月数据
    
    for i in range(120):
        money = expense[i] + debt[i] - saving[i] - income[i]      # 当月还需借贷花呗金额 = 月支出 + 本月需还花呗 - 月初余额 - 月收入
        #print(money)
        if money > 15000:
            # 当月还需借贷花呗金额大于15000元时 → 破(吃)产(土)
            print('第%i个月花呗也救不了我了,要破(吃)产(土)了!\n-------' % (i+1))
            break
        else:
            if money >= 0:
                saving[i+1] = saving[i] + income[i] - expense[i] - debt[i]
                debt[i+1] = 0
            else:
                money_per = (abs(money) * (1+0.088))/12    # 分期十二月
                saving[i+1] = 0
                debt[i+1] = debt[i+1] + money_per
                debt[i+2] = debt[i+2] + money_per
                debt[i+3] = debt[i+3] + money_per
                debt[i+4] = debt[i+4] + money_per
                debt[i+5] = debt[i+5] + money_per
                debt[i+6] = debt[i+6] + money_per
                debt[i+7] = debt[i+7] + money_per
                debt[i+8] = debt[i+8] + money_per
                debt[i+9] = debt[i+9] + money_per
                debt[i+10] = debt[i+10] + money_per
                debt[i+11] = debt[i+11] + money_per
                debt[i+12] = debt[i+12] + money_per
        month.append(i+1)
        data.append([income[i],expense[i],debt[i],saving[i+1],debt[i+1]])
    
    result_e = pd.DataFrame(data,columns=['月收入','月支出','本月需还花呗','本月余钱','欠债'],index = month)
    result_e.index.name = '月份'
    
    return result_e

构建完函数,再分别进行1w次模拟,并且用直方图绘制出模拟结果

# 允许分期(分期三月)

month_case_b = []    
for i in range(10000): 
    print('正在进行第%i次模拟' % (i+1))
    income = final_income(10000,1500)['月净收入'].tolist()
    expense = final_expense()['月总支出'].tolist()
    saving = [0 for i in range(120)]
    debt = [0 for i in range(120)]
    result_b = case_b().index.max()
    month_case_b.append(result_b)

result_b = pd.Series(month_case_b)

plt.figure(figsize = (12,4))
result_b.hist(bins=18)
plt.title('第二回合:允许分期(分期三月) - 模拟结果')

在这里插入图片描述

# 允许分期(分期六月)

month_case_c = []    
for i in range(10000): 
    print('正在进行第%i次模拟' % (i+1))
    income = final_income(10000,1500)['月净收入'].tolist()
    expense = final_expense()['月总支出'].tolist()
    saving = [0 for i in range(120)]
    debt = [0 for i in range(120)]
    result_c = case_c().index.max()
    month_case_c.append(result_c)

result_c = pd.Series(month_case_c)

plt.figure(figsize = (12,4))
result_c.hist(bins=20)
plt.title('第二回合:允许分期(分期六月) - 模拟结果')

在这里插入图片描述

# 允许分期(分期九月)

month_case_d = []    
for i in range(10000): 
    print('正在进行第%i次模拟' % (i+1))
    income = final_income(10000,1500)['月净收入'].tolist()
    expense = final_expense()['月总支出'].tolist()
    saving = [0 for i in range(120)]
    debt = [0 for i in range(120)]
    result_d = case_d().index.max()
    month_case_d.append(result_d)

result_d = pd.Series(month_case_d)

plt.figure(figsize = (12,4))
result_d.hist(bins=20)
plt.title('第二回合:允许分期(分期九月) - 模拟结果')

在这里插入图片描述

# 允许分期(分期十二月)

month_case_e = []    
for i in range(10000): 
    print('正在进行第%i次模拟' % (i+1))
    income = final_income(10000,1500)['月净收入'].tolist()
    expense = final_expense()['月总支出'].tolist()
    saving = [0 for i in range(120)]
    debt = [0 for i in range(120)]
    result_e = case_e().index.max()
    month_case_e.append(result_e)

result_e = pd.Series(month_case_e)

plt.figure(figsize = (12,4))
result_e.hist(bins=20)
plt.title('第二回合:允许分期(分期十二月) - 模拟结果')

在这里插入图片描述
从进行的1w次模拟中可以知道,在使用3、6、9、12期分期时,分别会在第23、35、45、55个月左右就吃土了。

4.不同情况下(分期和不分期)花呗偿还额度的变化

income = final_income(10000,1500)['月净收入'].tolist()
expense = final_expense()['月总支出'].tolist()
saving = [0 for i in range(120)]
debt = [0 for i in range(120)]
r1 = case_a()['欠债']

income = final_income(10000,1500)['月净收入'].tolist()
expense = final_expense()['月总支出'].tolist()
saving = [0 for i in range(120)]
debt = [0 for i in range(120)]
r2 = case_b()['欠债']

income = final_income(10000,1500)['月净收入'].tolist()
expense = final_expense()['月总支出'].tolist()
saving = [0 for i in range(120)]
debt = [0 for i in range(120)]
r3 = case_c()['欠债']

income = final_income(10000,1500)['月净收入'].tolist()
expense = final_expense()['月总支出'].tolist()
saving = [0 for i in range(120)]
debt = [0 for i in range(120)]
r4 = case_d()['欠债']

income = final_income(10000,1500)['月净收入'].tolist()
expense = final_expense()['月总支出'].tolist()
saving = [0 for i in range(120)]
debt = [0 for i in range(120)]
r5 = case_e()['欠债']

# 将不同情况的数据连接进行合并
df = pd.DataFrame({'不分期':r1,'分期三月':r2,'分期六月':r3,'分期九月':r4,'分期十二月':r5},
                 columns = ['不分期','分期三月','分期六月','分期九月','分期十二月'])

# 制作折线图
df.plot(kind='line',style = '--.',alpha = 0.8,use_index = True,figsize = (12,4),legend = True,colormap = 'Accent')
plt.title('不同情况下负债积累')
plt.grid()

在这里插入图片描述
一些结论:
分期的时间越长,不吃土的时间就越长,说明借贷、分期还款可以延缓吃土;
分期时间越久,累积的负债(折线区域的面积)就越多;
应适当合理地使用花呗。钱不够花时,应努力提高收入。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值