利用随机森林等模型进行企业纳税合规判断

 介绍

此项目利用机器学习的方法,进行智能地判断企业纳税是否合规

样本集为汽车行业门店相关财务数据

 

数据介绍:

目标变量:

label:是否税务合规存疑。1是,0否。

特征:

tax_num:纳税人编号

sale_type:销售类型

sale_mode:销售模式

sales_profit:汽车销售平均毛利

maintenance_profit:维修毛利

maintenance_revenue_rate:企业维修收入占销售收入比重

vat_burden:增值税税负

inventory_turnover:存货周转率

cost_profit_rate:成本费用利润率

theoretical_tax_burden:整体理论税负

total_tax_control:整体税负控制数

licensing_rate:办牌率

single_station_fee:单台办牌手续费收入

agent_insurance_rate:代办保险率

premium_return_rate:保费返还率

数据处理

数据导入

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import copy
import seaborn as sns
from scipy.stats import chi
import scipy
from scipy.stats import chi2
np.seterr(divide='ignore',invalid='ignore')
df=pd.read_csv('tax.csv')

标签导入及处理

df['label']=df['label'].apply(lambda x:0 if x=='正常' else 1)

分箱

由于各特征为连续变量,为了更好判断各特征与纳税的关系,将各连续变量分箱处理,采用卡方分箱。

def chi3(arr):
    '''
   计算卡方值
   arr:频数统计表,二维numpy数组。
   '''
    assert (arr.ndim == 2)
    # 计算每行总频数
    R_N = arr.sum(axis = 1)
    # 每列总频数
    C_N = arr.sum(axis = 0)
    # 总频数
    N = arr.sum()
    # 计算期望频数 C_i * R_j / N。
    E = np.ones(arr.shape) * C_N / N
    E = (E.T * R_N).T
    square = (arr - E) ** 2 / E
    # 期望频数为0时,做除数没有意义,不计入卡方值
    square[ E == 0 ] = 0
    # 卡方值
    v = square.sum()
    return v

def chiMerge(df, col, target, max_groups=None, threshold=None):
    '''
   卡方分箱
   df: pandas dataframe数据集
   col: 需要分箱的变量名(数值型)
   target: 类标签
   max_groups: 最大分组数。
   threshold: 卡方阈值,如果未指定max_groups,默认使用置信度95%设置threshold。
   return: 包括各组的起始值的列表.
   '''

    freq_tab = pd.crosstab(df[ col ], df[ target ])

    # 转成numpy数组用于计算。
    freq = freq_tab.values

    # 初始分组切分点,每个变量值都是切分点。每组中只包含一个变量值.

    # 分组区间是左闭右开的,如cutoffs = [1,2,3],则表示区间 [1,2) , [2,3) ,[3,3+)。
    cutoffs = freq_tab.index.values

    # 如果没有指定最大分组
    if max_groups is None:
        # 如果没有指定卡方阈值,就以95%的置信度(自由度为类数目-1)设定阈值。
        if threshold is None:
            # 类数目
            cls_num = freq.shape[ -1 ]
            threshold = chi2.isf(0.05, df = cls_num - 1)

    while True:
        minvalue = None
        minidx = None
        # 从第1组开始,依次取两组计算卡方值,并判断是否小于当前最小的卡方
        for i in range(len(freq) - 1):
            v = chi3(freq[ i:i + 2 ])
            if minvalue is None or (minvalue > v):  # 小于当前最小卡方,更新最小值
                minvalue = v
                minidx = i

        # 如果最小卡方值小于阈值,则合并最小卡方值的相邻两组,并继续循环
        if (max_groups is not None and max_groups < len(freq)) or (threshold is not None and minvalue < threshold):
            # minidx后一行合并到minidx
            tmp = freq[ minidx ] + freq[ minidx + 1 ]
            freq[ minidx ] = tmp
            # 删除minidx后一行
            freq = np.delete(freq, minidx + 1, 0)
            # 删除对应的切分点
            cutoffs = np.delete(cutoffs, minidx + 1, 0)

        else:  # 最小卡方值不小于阈值,停止合并。
            break
    return cutoffs

def value2group(x, cutoffs):
    '''
   将变量的值转换成相应的组。
   x: 需要转换到分组的值
   cutoffs: 各组的起始值。
   return: x对应的组,如group1。从group1开始。
   '''

    # 切分点从小到大排序。
    cutoffs = sorted(cutoffs)
    num_groups = len(cutoffs)

    # 异常情况:小于第一组的起始值。这里直接放到第一组。
    # 异常值建议在分组之前先处理妥善。
    if x < cutoffs[ 0 ]
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值