日常分析使用的小工具函数

一、模块导入

import findspark
#初始化spark会话
findspark.init()
frompyspark.sqlimport SparkSession
import warnings
warnings.filterwarnings("ignore")
import time
import datetime
from collections import namedtuple
import concurrent.futures
import pandas as pd
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
from concurrent.futures import ThreadPoolExecutor
from concurrent.futures import ProcessPoolExecutor 
import os
import calendar
import sklearn
from sklearn.model_selection import train_test_spllit
from sklearn.metrics import classification_report
frompyecharts.charts import Sankey
from pyecharts import options as opts
plt.rcParams['font.sans-serif']=['SimHei']#用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False
#用来正常显示负号

二、时间日期转换

#获取sql数据,转成pandas.DataFrame
def get_date(sql):
    spark = SparkSession.builder.appName('PythonPi').getorCreate
    df_base = spark.sql(sql)
    df_base = df_base.toPandas
    spark.stop()
    return df_base

#传入两个str的日期时间格式,返回两个日期时间的时间差,单位移>。t_min < t_max
def get_datetimediff_second(t_min, t_max):
    t_min = str(t_min)
    t_max = str(t_max)
    t_min = datetime.datetime.strptime(t_min, '%Y-%m-%d %H:%M:%S')
    t_max = datetime.datetime.strptime(t_max, '%Y-%m-%o%H:%M:%S')
    time_diff = t_max - t_min
    return int(time_diff.seconds)

#传入一个str的日期时间格式,一个时间差秒,日期时间-时间差的日期时间
def get_start_datetime(end_time, seconds):
    end_time = datetime.datetime.strptime(str(end_tiime), '%Y-%m-%d %H:%M:%S')
    timediff = datetime.timedelta(seconds=int(secconds)
    start_time = end_time - timediff
    return str(start_time)

#传入一个str的日期时间格式,返回时间戳,int格式
def datetime_2_stamp(date_time):
    date_time = datetime.datetime.strptime(str(date_time), '%Y-%m-%d %H:%M:%S')
    stamp = datetime.datetime.timestamp(date_time)
    return int(stamp)

三、假设检验    

两个独立样本的t检验

率值检验

#假设检验
def ind_t_test_twoside_rate(x1, n1, x2, n2):
    p1 = x1 / n1
    p2 = x2 / n2
    p_ba = (x1 + x2) / (n1 + n2)
    z = (p1 - p2) / (np.sqrt(p_ba*(1-p_ba)*(1/n1 + 1/n2)))
    p = stats.norm.sf(abs(z))*2
    # 计算双尾
    ind_z_test = namedtuple('ind_z_test', 'p1, p2, p_value'
    ind_z_test = ind_z_test(p1=round(p1, 3), p2=round(p52,3),p_value=round(p, 5))
    return ind_z_test

#双独立样本t检验。其中data_old, data_new作为两个不同的母体数据
def t_test(data_old, data_new):
    # 判断样本是否为大样本,若为大样本则无需判断样本是否服从正态分布
    if len(data_old)>=50 and len(data_new)>=50:
        statistic, pvalue = stats.levene(data_old, data_new)
        #两个总体的方差齐性检验
        if pvalue >= 0.05:
            # 方差齐性,equal_val=True
            t, p = stats.ttest_ind(data_old, data_new, equa1_var=True) 
        else:
            #方差不齐性,equal_val=False
            t, p = stats.ttest_ind(data_old, data_new, equal_var=False) 
    小样本则检验两组数据是否都服从正态分布。若有一个不服从,则用非参数检验
    else:
        # 小样本的正态分布检验方法
        data_old_norm_test = stats.shapiro(data_old)
        data_new_norm_test = stats.shapiro(data_new)
        if data_old_norm_test[1] >= 0.05 and data_new_norm_tesst[1] >= 0.05:
        # 两组数据均服从正态分布
            statistic, pvalue = stats.levene(data_old, data_new)
            #两个总体的方差齐性检验
            if pvalue >= 0.05:
                # 方差齐性,equal_val=True
                t, p = stats.ttest_ind(data_old, data_new, equa1_var=True) 
            else:
                #方差不齐性,equal_val=False
                t, p = stats.ttest_ind(data_old, data_new, equal_var=False) 
        #两组数据中,至少有一组不服从正态分布,这里改成秩和检验
        else:
            t, p = stats.mannwhitneyu(data_old, data_new, aIternative='two-sided')
    mean_data_old = round(np.mean(data_old), 1)
    mean_data_new = round(np.mean(data_new), 1)
    if p >= 0.05:
        result="没有显著变化"
    elif p < 0.05:
        if mean_data_old > mean_data_new:
            result="显著下降"
        else:
            result="显著提升"
    else:
        p = 1
        result="没有显著变化"
    ttest_info = namedtuple('ttest_info', 'mean_data_old, mean_data_new, p_value, result')
    ttest_result = ttest_info(mean_data_old=mean_data_old, mean_data_new=mean_data_new,         p_value=round(p, 4), result=result)
    return ttest_result

def chi2_contingency(table):
'''
    卡方检验
    :param table:是一个观测频数的二维数组
    :return 卡方统计量和p值
'''
    stat, p, dof, expected = stats.chi2_contingency(table)
    return stat, p

def fisher_exact(table):
'''
    Fisher精确检验
    只能用于2x2列联表
    :param table:2x2列联表数组
    :return OR值和p值
'''
    odds_ratio, p = stats.fisher_exact(table)
    return odds_ratio, p

def t_test_ind(v1, v2):
'''
    独立样本t检验
    检验两个独立样本的均值是否有显著差异
    :param v1:样本1的数组
    :param v2:样本2的数组
    :returnt统计量和p值
    :v1、v2来源于同一个母体(ABTest的实验组、对照组)
'''
    #先检验方差齐性
    _, var_p = stats.levene(v1, v2)
    equal_var = var_p > 0.05
    stat, p = stats.ttest_ind(v1, v2, equal_var=equal_var)
    return stat, p

def t_test_rel(v1, v2):
'''
    配对或相关样本t检验
    检验两个相关样本的均值是否有显著差异

    :param v1:样本1的数组
    :param v2:样本2的数组
    :returnt统计量和p值
'''
    stat, p = stats.ttest_rel(v1, v2)
    return stat, p

def oneway_anova(*args):
'''
    单因素方差分析
    检验两个或多个独立样本的均值是否有显著差异
    :param sample1, sample2, ... : array_like

    :return F统计量和p值
'''
    stat, p = stats.f_oneway(*args)
    return stat, p

def mannwhitneyu(v1, v2):
'''
    Mann-Whitney U检验
    检验两个独立样本的分布是否相等
    独立样本t检验的非参数替代版本
    :param v1:样本1的数组
    :param v2:样本2的数组
    :return Mann-WhitneyU统计量和p值
'''
    stat, p = stats.mannwhitneyu(v1, v2)
    return stat, p

def wilcoxon(v1, v2):
'''
    Wilcoxon符号秩检验
    检验两个成对样本的分布是否相等
    配对样本t检验的非参数替代版本
    :param v1:样本1的数组
    :param v2:样本2的数组

    :return Wilcoxon统计量和p值
'''
    stat, p = stats.wilcoxon(v1, v2)
    return stat, p

def kruskal(v1, v2):
'''
    Kruskal-WallisH检验
    检验两个或多个独立样本的分布是否相等
    单因素方差分析的非参数替代版本
    :param v1:样本1的数组
    :param v2:样本2的数组
    :return Kruskal-Wallis H统计量和p值
'''
    stat, p = stats.kruskal(v1, v2)
    return stat, p

def friedmanchisquare(*args):
'''
    Friedman 检验
    检验两个或多个成对样本的分布是否相等,适用于重复测量资料
    Wilcoxon符号秩检验的多样本扩展
    :param v1: 样本1的数组
    :param v2:样本2的数组
    :return Kruskal-Wallis H统计量和p值
'''
    stat, p = stats.friedmanchisquare(*args)
    return stat, p

#某个特征对结果是否有因果关系
def chi2_test(data):
    #要求探索两个变量之间的关系,则样本量至少需要在500个以上,如果寻找因果关系,建议各1000个以上样本
    #data=[[d1,d2],[d3,d4]],2x2的array。以红名单为例。d1表示红名单投诉的量、d2表示红名单不投诉的量、d3表示非红名单投诉的量、d4表示非红名单不投诉的量
    d1 = data[0][0][0]
    d2 = data[0][1]
    d3 = data[1][0]
    d4 = data[1][1]
    n = d1 + d2 + d3 + d4
    #当n>=40且所有的T>5时,用卡方检验的基本公式;当P~α时,改用四格表的Fisher确切概率法。
    alpha = 0.05
    # 列联表的期望值
    T1 = (d1+d2)*(d1+d3) / n
    T2 = (d2+d1)*(d2+d4) / n
    T3 = (d3+d1)*(d3+d4) / n
    T4 = (d4+d2)*(d4+d3) / n

    if n>=40 and T1>=5 and T2>=5 and T3>=5 and T4>=5:
        stastistic = stats.chi2_contingency(data, correction=False)
        p = stastistic[1]
        #若p值与alpha很接近
        if alpha*(1-0.05) <= p <= alpha*(1+0.05):
            oddsr, p=stats.fisher_exact(data, alternative='two-sided')
    #当n240但又1sTs5时,用四格表资料卡方检验的校正公式
    elif n>=40 and (1<=T1<5 or 1<=T2<5 or 1<=T3<5 or 1<=T4<5):
        stastistic = stats.chi2_contingency(data, correction=True)
        p = stastistic[1]
    # 当n<40或T<1时,用四格表资料的Fisher确切概率法。
    else:
        oddsr, p=stats.fisher_exact(data, alternative='two-sided')
    chi_info = namedtuple('chi_info', 'p_value, result')
    if p<= 0.05:
        chi_result=chi_info(p_value=p, result='具备相关性|因果关系'
    else:
        chi_result=chi_info(p_value=p,result='不具备相关性因果关系'
    return chi_result

四、相关系数

def pearsonr(v1, v2):
'''
    皮尔逊相关系数和显著性检验。
    适用条件:连续变量,正态分布
    :param v1:样本1的数组
    :param v2:样本2的数组
    :return皮尔逊相关系数和p值
'''
    r, p = stats.pearsonr(v1, v2)
    return r, p

def spearmanr(v1, v2):
'''
    斯皮尔曼秩相关系数。
    适用条件:可用于连续资料或等级资料,无正态分布假设
    :param v1:样本1的数组
    :param v2:样本2的数组
    :return斯皮尔曼秩相关系数和p值
'''
    r, p = stats.spearmanr(v1, v2)
    return r, p

def kendalltau(v1, v2):
'''
    Kendall秩相关系数。
    衡量有序分类数据的序数相关性。相关系数1为极度相关、-1不极度不相关
    适用条件:有序分类变量,无正态分布假设
    :param v1:样本1的数组
    :param v2:样本2的数组
    :return Kendall tau相关系数和p值
'''
    r, p = stats.kendalltau(v1, v2)
    return r, p

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值