从数据预处理到特征工程

本文详细介绍了数据预处理的各个环节,包括数值型数据的缺失值和离群点处理,以及名义型变量的处理。接着,文章深入探讨了特征工程的各个方面,如特征生成、特征选择和降维,涉及了多种方法和技术,如标准化、归一化、二值化、哑编码、One-hotEncoder、特征选择策略和降维算法PCA与t-SNE。数据预处理和特征工程在机器学习中至关重要,对模型性能有着决定性影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前一直在研究数据特征工程,看了一些资料,也自己写了通用的代码,现在将这些内容整理一下。机器学习里有一句名言:数据和特征决定了机器学习的上限,而模型和算法的应用只是让我们逼近这个上限。整个数据挖掘全流程60%以上的时间和精力去做建模前期的数据处理和特征分析,那么面对参差不齐的数据,n多的特征,我们要做的就是step by step抽丝剥茧。首先我们要对数据做清洗,预处理,然后是特征工程。

1.数据预处理

在python中,常用的数据格式是DataFrame,我们将一个DataFrame作为输入,可先将数据框按照数据的类型进行分离,分割成数值型数据框和名义型数据框,然后对这两个数据框分别做不同的处理:

import pandas as pd
def split_dt(dt):
numeric_dt = pd.DataFrame()
nomial_dt = pd.DataFrame()
for i in dt.columns:
    if type(dt[i][0]) != str:
        numeric_dt[i] = dt[i]
    else:
        nomial_dt[i] = dt[i]
return numeric_dt, nomial_dt

这一步骤,我将一个输入的DataFrame分割成了numeric_dt和nomial_dt,接下来我们分别对这两个数据框进行处理。

1.1数值型数据预处理

首先我们看看数据涨什么样子,当然这一步也可以在分割之前做,总之就是什么时候看一下都是可以的:

def data_ndes(dt):
samples, features = dt.shape
# ld = dt.iloc[:, 0].size
# vd = dt.columns.size
ds = dt.describe()
return samples, features, dt.head(), ds

返回的是数据的样本及特征数量,数据的前5行做个大概的预览,还有数据的describe,一般就是每个数值型变量的总数(通过这个也可以看出来特征是不是有缺失值)、最小值、1/4分位数,中位数、均值、3/4分位数。之后我们可以用data.drop_duplicate()来删除重复的数据。如果这个数据中有时间类型的数据,我们还可以对时间类型的数据做些规范,这其中也考虑了时间戳的情况:

# datetime standard
def transform_date(dt_col, format="%Y-%m-%d %H:%M:%S"):
if not type(dt_col[0]) is str:
    return pd.to_datetime(pd.to_datetime(round(dt_col), unit='s'), format=format)
else:
    return pd.to_datetime(dt_col, format=format)

浮点型数据的规整:包括四舍五入、向上、向下取整、保留n位小数,输入数据的一列,返回规范后的一列

def numerical_round(dt_col):
return round(dt_col)

def numerical_int(dt_col):
return [int(x) for x in dt_col]

def numerical_ceil(dt_col):
return [math.ceil(x) for x in dt_col]

def numerical_round2(dt_col, n):
return round(dt_col, ndigits=n)

接下来我们要做的是离群点和缺失值的检测及处理:

1.1.1缺失值的检测及处理

对于一个数据框检测每一列是否有缺失值,我期望的到的结果是每一列缺失值的个数、缺失值的比例,然后将这些含有缺失值的数据取出来进行观察。

def num_missing(dt):
# isNull = lambda x : any(pd.isnull(x))
# return dt.apply(function=isNull, axis=0)
is_null = []
null_num = []
null_ratio = []
for i in dt.columns:
    is_null.append(any(pd.isnull(dt[i])))
    null_num.append(sum(pd.isnull(dt[i])))
    null_ratio.append(float(round(sum(pd.isnull(dt[i]))/dt.shape[0], 4)))
return is_null, null_num, null_ratio

缺失值的处理我主要用了以下几种方法,一是删除含有缺失值的样本:

def null_drop(dt):
return dt.dropna()

得到的就是不含缺失值的样本,这是我们想到了一个问题,如果某一列含有很多的缺失值,那么就会删除了太多的样本,所以在这一步骤之前,我们通过之前的缺失值检测的结果先将含有很多缺失值的列进行处理,一般情况下如果缺失值超过了30%,那么删除这个特征有时候比做一些填补的效果要好,如果缺失值不多,那我们可以采取均值、中位数、众数(一般是名义型数据处理方式)进行填补,或者如果数据有明显的规则和连续型,那么也可以采用向前或者向后填补 :

# 众数
def dt_mod(dt_col):
a = mode(dt_col, nan_policy='omit')[0][0]
return a

2.mean,median,mod
def null_fill(dt_col, va):
return dt_col.fillna(value=va)

#fill forward / backward number
def null_fillfb(dt_col, way):
return dt_col.fillna(method=way)

1.1.2离群点的检测及处理

1.1.2.1 1.5倍IQR离群点的检测及处理

离群点这部分我主要用了常用的三种检测方法,一是1.5倍IQR,具体看下面的代码就能理解:

import scipy
import numpy as np
def outlier_detect_iqr(dt_col):
outlier_value = []
outlier_index = []
outlier_count = 0
detect_range = scipy.stats.iqr(dt_col, nan_policy='omit')
Q1 = dt_col.quantile(q=0.25)
Q3 = dt_col.quantile(q=0.75)
for ids, values in enumerate(dt_col):
    if (values >= Q3+1.5 * detect_range) | (values <= Q1-1.5 * detect_range):
        outlier_count += 1
        outlier_value.append(values)
        outlier_index.append(ids)
return outlier_index, outlier_value, outlier_count

函数的输入的进行检查的数据框的一列,返回离群点的index,离群值以及离群点的总数。对于离群点的处理方式一般有取值的自然对数,为什么要取值的自然对数,下面的例子直观的展示了log的作用:
这里写图片描述

离群点的处理我采用了三种常用的方式,第二种方法是,输入数据框的一列,输出不含缺失值的一列:

def outlier_iqr_delete(dt_col):
new_value = []
new_index = []
ids = outlier_detect_iqr(dt_col)[0]
for i, vas in enumerate(dt_col):
    if i not in ids:
        new_value.append(vas)
        new_index.append(i)
return new_index, new_value

第三种方法是补均值、中位数、众数:

def outlier_iqr_fillmean(dt_col):
new_value = []
new_index = []
ids = outlier_detect_iqr(dt_col)[0]
for i, vas in enumerate(dt_col):
    if i in ids:
        new_value.append(dt_col.mean())
        new_index.append(i)
    else:
        new_value.append(vas)
        new_index.append(i)
return new_index, new_value

def outlier_iqr_fillmedian(dt_col):
new_value = []
new_index = []
ids = outlier_detect_iqr(dt_col)[0]
for i, vas in enumerate(dt_col):
    if i in ids:
        new_value.append(dt_col.median())
        new_index.append(i)
    else:
        new_value.append(vas)
        new_index.append(i)
return new_index, new_value

def outlier_iqr_fillmode(dt_col):
new_value = []
new_index = []
ids = outlier_detect_iqr(dt_col)[0]
for i, vas in enumerate(dt_col):
    if i in ids:
        new_value.append(mode(dt_col, nan_policy='omit')[0][0])
        new_index.append(i)
    else:
        new_value.append(vas)
        new_index.append(i)
return new_index, new_value

因为我们想要输入一列然后得到不含缺失值的一列,所以函数写起来规范了输入输出比较麻烦。后面根据不同的检测方式会得到不同的离群点,但是处理的方式都是相同的,后面不再赘述。当然

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值