数据预处理方式合集

2023-09-20 11:44:58

删除空行

#del all None value
data_all.dropna(axis=1, how='all', inplace=True)

删除空列

#del all None value
data_all.dropna(axis=0, how='all', inplace=True)

缺失值处理

观测缺失值

        观测数据缺失值有一个比较好用的工具包——missingno,直接传入DataFrame,会将所有的列缺失比例可视化,是一个比较方便的工具。

        将观测的缺失值数据统计成为一个数据表,并将数据表可视化,

# 统计缺失值数量
missing=data_all.isnull().sum().reset_index().rename(columns={0:'missNum'})
# 计算缺失比例
missing['missRate']=missing['missNum']/data_all.shape[0]
# 按照缺失率排序显示
miss_analy=missing[missing.missRate>0].sort_values(by='missRate',ascending=False)
# miss_analy 存储的是每个变量缺失情况的数据框

         然后将缺失值数据miss_analy可视化

import matplotlib.pyplot as plt
import pylab as pl
fig = plt.figure(figsize=(18,6))
plt.bar(np.arange(miss_analy.shape[0]), list(miss_analy.missRate.values), align = 'center',color=['red','green','yellow','steelblue'])
plt.title('Histogram of missing value of variables')
plt.xlabel('variables names')
plt.ylabel('missing rate')# 添加x轴标签,并旋转90度
plt.xticks(np.arange(miss_analy.shape[0]),list(miss_analy['index']))
plt.xticks(rotation=90)
# 添加数值显示
for x,y in enumerate(list(miss_analy.missRate.values)):    
    plt.text(x,y+0.12,'{:.2%}'.format(y),ha='center',rotation=90)    
    plt.ylim([0,1.2])
plt.show()

         当然有些画图的技巧,需要每个人根据各自的需求去探索,笔者画图功底也比较差,可以参考Sklearn里面的sample,也可以查阅Seaborn中的技术文档。以上数据可视化后可以看到每一列的缺失值比例,然后可以自己设定缺失值阈值α,如果缺失值比例大于α则删除该列,或者其他却缺失值处理策略。当然笔者任务是建立高精度的预测模型,而且,数据量还可以。所以就没有用填充策略。

删除缺失严重特征

alpha = 0.2
need_delete_cols = []
for index,row in miss_analy.iterrows():
    if row['missRate'] > alpha:
        need_delete_cols.append(row['index'])
        
#delete most empty col
data_all = data_all.drop(columns=need_delete_cols, axis=0, inplace=True)

        有的人可能觉得这种方法比较麻烦,又要可视化又要单独删除,如果不需要可视化或者探索缺失值的具体情况,我这里也提供一个非常简单粗暴的缺失值删除办法

data_all=data_all.dropna(thresh=len(data_all)*alpha, axis=1)

        以上一行代码完成了,前述的所有删除工作。

删除单值特征

        单值特征是指某一列只有一个值,不存在变化的情况,这种特征是没有任何意义的,需要直接删除

desc = data_all.astype('str').describe()
mask = desc.loc['unique',:] == 1
data_all.drop(labels=desc.columns[mask],axis=1,inplace=True)

异常数据处理

        这里我说的异常数据一般是指每个特征中的离群数据,因为我的任务是建立一个通用的,泛化能力较强的模型,所以这里对每个特征的离群数据进行删除操作,避免后续模型为了拟合离群点,导致过拟合的现象。那如何判断某个数据点是否离群或者异常呢?这里提供两种方法,每个方法都有优劣势,后续我再细说。

3σ方式

        用传统意义上的统计方法实现,3σ我就不细说了,正态分布3σ之外的数据为异常

def del_outlier(dataset):
    temp = dataset.copy()
    for each in temp.columns:
        std = np.std(temp[each])
        mean = np.mean(temp[each])
        
        sigma = 4 * std
        limit_up = mean + sigma 
        limit_bottom = mean - sigma 
         
        temp = temp.query('({} > {}) and ({} <{})'.format(each,limit_bottom,each,limit_up))
        
        print(limit_up,limit_bottom)
        print(each,temp.shape)
        
    return temp

        这个方式比较通用,最适合看起来服从正太分布的特征。 

分位数方式

        首先我放个连接(https://www.itl.nist.gov/div898/handbook/prc/section1/prc16.htm),里面描述了什么是离群点。

def del_outlier(dataset):
    temp = dataset.copy()
    for each in temp.columns:       
         first_quartile = temp[each].describe()['25%']
         third_quartile = temp[each].describe()['75%']
        
         iqr = third_quartile - first_quartile
         limit_up = third_quartile + 3 * iqr
         limit_bottom = first_quartile - 3 * iqr     
         temp = temp.query('({} > {}) and ({}<{})'.format(each,limit_bottom,each,limit_up))
        
        print(limit_up,limit_bottom)
        print(each,temp.shape)
        
    return temp

        分位数方式存在一个问题,如果离群点非常少,导致3/4和1/4分位数相等,就无法执行下去。

个人还是比较推荐σ的方法。

特征信息量

        特诊信息量是描述的某一特征的数据是否有足够的信息熵去辅助建模,如果一个特诊的信息熵很低,那说明该特诊基本上不存在什么波动,蕴含的信息量极少(当然可能要做完归一化后观测起来会比较明显),那该特诊就可以直接删除。

        以下为计算信息熵的Python代码:

from scipy.stats import entropy
from math import log, e
import pandas as pd   

##""" Usage: pandas_entropy(df['column1']) """

def pandas_entropy(column, base=None):
    vc = pd.Series(column).value_counts(normalize=True, sort=False)
    base = e if base is None else base
    return -(vc * np.log(vc)/np.log(base)).sum()

执行删除信息熵小的特诊:

for each in feature_list:
#     print(each,pandas_entropy(data_all[each]))
    if pandas_entropy(data_all[each]) < 1:
        print(each,pandas_entropy(data_all[each]))
        data_all.drop(columns=[each],axis=1,inplace=True)

处理不同数据类型特诊(时间特征为例)

        DataFrame数据类型通常包含Object,int64,float64,,对于后两者我们没必要可以去改变,但是对于Object类型的数据,不同含义的Object数据做不同处理。笔者这里举例时间格式的Object数据处理。

        数据类型查看与统计

data_all.dtypes.values_counts()

        将时间的Object数据进行转换。

data_all[key] = pd.to_datetime(data_all[key])

        如果存在类似开始时间-结束时间的时间对数据,可以将两者相减,得到时间片段数据,例如:

data_all[time_gap] = pd.to_datetime(data_all['end']) - pd.to_datetime(data_all['start'])

        然后将时间段数据转为小时,或者分钟,或者秒:

data_all[key] = data_all[key].apply(lambda x: x.total_seconds() / 60 / 60)

以上为个人通常来讲的数据预处理过程,建议在每执行一步后数据重新命名,并保存一份备份。

以上。

        如有什么建议或者错误,大家随时拍砖。

更多推荐

面试中的情商考察:如何展示你的人际理解能力

🌷🍁博主猫头虎(🐅🐾)带您GotoNewWorld✨🍁🦄博客首页——🐅🐾猫头虎的博客🎐🐳《面试题大全专栏》🦕文章图文并茂🦖生动形象🐅简单易学!欢迎大家来踩踩~🌺🌊《IDEA开发秘籍专栏》🐾学会IDEA常用操作,工作效率翻倍~💐🌊《100天精通Golang(基础入门篇)》🐅学会Gol

淘宝分布式文件存储系统( 三 ) -TFS

淘宝分布式文件存储系统(三)->>TFS目录:文件重新映射的接口介绍文件映射mmap_file.cpp的实现进行测试文件重新映射(增加或者减少文件映射区域的大小)mremap()函数的原型如下#include<sys/mman.h>void*mremap(void*old_address,size_told_size,

如何在面试中展示跨领域的能力

🌷🍁博主猫头虎(🐅🐾)带您GotoNewWorld✨🍁🦄博客首页——🐅🐾猫头虎的博客🎐🐳《面试题大全专栏》🦕文章图文并茂🦖生动形象🐅简单易学!欢迎大家来踩踩~🌺🌊《IDEA开发秘籍专栏》🐾学会IDEA常用操作,工作效率翻倍~💐🌊《100天精通Golang(基础入门篇)》🐅学会Gol

嵌入式笔试面试刷题(day15)

文章目录前言一、Linux中的主设备号和次设备号1.查看方法2.主设备号和次设备号的作用二、软件IIC和硬件IIC的区别三、变量的声明和定义区别四、static在C和C++中的区别五、串口总线空闲时候的电平状态总结前言本篇文章继续讲解嵌入式笔试面试刷题,希望大家坚持跟着我的脚步一起加油冲击大厂offer。一、Linux

Pytest单元测试框架 —— Pytest+Allure+Jenkins的应用

一、简介pytest+allure+jenkins进行接口测试、生成测试报告、结合jenkins进行集成。pytest是python的一种单元测试框架,与python自带的unittest测试框架类似,但是比unittest框架使用起来更简洁,效率更高allure-pytest是python的一个第三方库。用于连接py

开始使用Filebeat

认识BeatsBeats是用于单用途数据托运人的平台。它们以轻量级代理的形式安装,并将来自成百上千台机器的数据发送到Logstash或Elasticsearch。(画外音:通俗地理解,就是采集数据,并上报到Logstash或Elasticsearch)Beats对于收集数据非常有用。它们位于你的服务器上,将数据集中在E

嵌入式笔试面试刷题(day12)

文章目录前言一、SDK是什么二、内存分配最小单位三、内联函数和宏函数的区别四、空指针和野指针的区别五、访问野指针和空指针会发生什么六、C++面向对象的三要素七、if(0==x)和if(x==0)八、二维数组地址是否连续总结前言本篇文章继续带大家来刷题,秋招也快到了大家坚持刷题,相信大家都可以找到好工作。一、SDK是什么

RabbitMQ - 死信、TTL原理、延迟队列安装和配置

目录一、死信交换机1.1、什么是死信交换机1.2、TTL1.2.1、什么是TTL1.2.2、通过TTL模拟触发死信二、延迟队列2.1、什么是延迟队列2.2、配置延迟队列插件2.2.1、延迟队列配置a)下载镜像b)运行容器c)刚刚设定的RabbitMQ的数据卷名称为`mq-plugins`,所以我们使用下面命令查看数据卷

多线程知识汇总

IntentService多线程的应用在Android开发中是非常常见的,常用方法主要有:集成Thread类实现Runnable接口AsyncTaskHandlerHandlerThreadIntentServiceIntentService定义:Android里的一个封装类,继承四大组件之一service作用:处理异

Go的sync.Mutex互斥锁

我们使用了一个bufferedchannel作为一个计数信号量,来保证最多只有20个goroutine会同时执行HTTP请求。同理,我们可以用一个容量只有1的channel来保证最多只有一个goroutine在同一时刻访问一个共享变量。一个只能为1和0的信号量叫做二元信号量(binarysemaphore)。gopl.

函数式编程------JDK8新特性

函数式编程式jdk8中的语法糖,在许多地方都有用到,以下是一些优点.能够看懂公司里的代码大数量下处理集合效率高代码可读性高消灭嵌套地狱Lamda表达式lamda表达式是函数是编程的基础,先看一个列子新建一个线程,参数是匿名类内部类(匿名内部类是一个匿名子类对象。这里使用匿名内部类的)并且重写了类的抽象方法newThre

热文推荐