python数据预处理之缺失值简单处理,特征选择

https://blog.csdn.net/amy_mm/article/details/79799629

我们在进行模型训练时,不可避免的会遇到某些特征出现空值的情况,下面整理了几种填充空值的方法

https://www.cnblogs.com/Allen-rg/p/9488249.html

1. 用固定值填充

对于特征值缺失的一种常见的方法就是可以用固定值来填充,例如0,9999, -9999, 例如下面对灰度分这个特征缺失值全部填充为-99

data['灰度分'] = data['灰度分'].fillna('-99')

2. 用均值填充

对于数值型的特征,其缺失值也可以用未缺失数据的均值填充,下面对灰度分这个特征缺失值进行均值填充

data['灰度分'] = data['灰度分'].fillna(data['灰度分'].mean()))

3. 用众数填充

与均值类似,可以用未缺失数据的众数来填充缺失值

data['灰度分'] = data['灰度分'].fillna(data['灰度分'].mode()))

4. 用上下数据进行填充

用前一个数据进行填充

data['灰度分'] = data['灰度分'].fillna(method='pad')

用后一个数据进行填充

data['灰度分'] = data['灰度分'].fillna(method='bfill')

5. 用插值法填充

data['灰度分'] = data['灰度分'].interpolate()

6. 用KNN进行填充

from fancyimpute import BiScaler, KNN, NuclearNormMinimization, SoftImpute
dataset = KNN(k=3).complete(dataset)

书籍:《python machine learning》

推荐kaggel 上大神的数据预处理文章:

https://www.kaggle.com/pmarcelino/comprehensive-data-exploration-with-python


自己之前也学习过这篇文章对一些代码进行了注释,博文如下:

https://blog.csdn.net/Amy_mm/article/details/79538083


本文是学习《python machine learning》第四章的学习记录~~~


本文数据预处理源码git 地址:https://github.com/xuman-Amy/preprocessing

本文数据预处理主要步骤:

(1)删除和估算缺失值 (removing and imputing missing values)

(2)获取分类数据 (Getting  categorical data into shape for machine learning)

(3)为模型构建选择相关特征 (Selecting relevant features for the module construction)
【创建CSV数据集】

    #build a csv dataset
    import numpy as np
    import pandas as pd
    from io import StringIO
    import sys
    #数据不要打空格,IO流会读入空格
    csv_data = \
    '''A,B,C,D
    1.0,2.0,3.0,4.0
    5.0,6.0,,8.0
    10.0,11.0,12.0,
    '''
    df = pd.read_csv(StringIO(csv_data))

如图,有两个空值~
【统计空值情况】

    #using isnull() function to check NaN value
    df.isnull().sum()

【访问数组元素】

在放入sklearn的预估器之前,可以通过value属性访问numpy数组的底层数据


【消除缺失值 dropna() 函数】

一个最简单的处理缺失值的方法就是直接删掉相关的特征值(一列数据)或者相关的样本(一行数据)。

利用dropna()函数实现。

dropna( axis = 0 /1 )参数axis表示轴选择,axis=0 代表行,axis=1 代表列。

df.dropna(axis = 1)


df.dropna(axis = 0)

dropna( how = all) how参数选择删除行列数据(any / all)

df.dropna(how = 'all')

dropna(thresh = int) 删除值少于int个数的值

df.dropna(thresh = 4)

dropna( subset = [' '])  删除指定列中有空值的一行数据(整个样本)

df.dropna(subset = ['C'])

删除C列中有空值的那一行数据


虽然直接删除很是简单啦~但是天下没有免费的午餐,直接删除会带来很多弊端。比如样本值删除太多导致不能进行可靠预测;或者特征值删除太多(列数据),可能失去很多有价值的信息。

所以下面介绍一个更为通用的缺失值处理技巧——插值技术。我们可以根据样本集中的其他数据,运用不同的插值技术,来估计 样本的缺失值。
【插值】interpolation techniques
【imputing missing values】

比较常用的一种估值是平均值估计(mean imputation)。可以直接使用sklearn库中的imputer类实现。

class sklearn.preprocessing .Imputer

(missing_values = 'NaN', strategy = 'mean', axis = 0, verbose = 0, copy = True)

参考:http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.Imputer.html

参数说明:

missing_values : int或者'NaN',默认NaN(string类型)

strategy:默认mean。平均值填补。

可选项: mean(平均值)

              median(中位数)

              most_frequent(众数)

axis: 指定轴向。axis= 0,列向(默认);axis= 1,行向。

verbose : int 默认值为0

copy:默认True,创建数据集的副本。

          False:在任何合适的地方都可能进行插值。

以下四种情况,即使copy设为False,也会进行创建副本:

                    1. X不是浮点型数组

                    2.X是稀疏矩阵,且missing_values= 0

                    3.axis=0,X被编码为CSR矩阵(Compressed Sparse Row 行压缩)

                    4.axis=1,X被编码为CSC矩阵(Copressed Sparse Column 列压缩)


    #mean imputation
    #axis = 0,表示列向,采用每一列的平均值填补空值
     
    from sklearn.preprocessing import Imputer
    imr = Imputer(missing_values = 'NaN', strategy = 'mean', axis = 0 )
    imr = imr.fit(df.values)
    imputed_data = imr.transform(df.values)
    imputed_data

【处理分类数据】

handling categorical data

分类数据一般分为nominal(名词性,不可排序)和ordinal(可排序数据)

 【创建分类数据集】

    #create categorical dataset
    import pandas as pd
    df = pd.DataFrame([
        ['green', 'M', 10.1, 'class1'],
        ['red', 'L', 13.5, 'class2'],
        ['blue', 'XL', 15.3, 'class1']
    ])
    df.columns = ['color', 'size', 'price', 'classlabel']
    df


nominal data : color

ordinal data : size

numerical data : price

 【映射可排序特征】

为确保学习算法能够正确识别可排序特征值,需要将分类数据转换为数值型数据。

    #converting categorical string values into integers
    size_mapping = {
        'XL': 3,
        'L' : 2,
        'M' : 1}
    df['size'] = df['size'].map(size_mapping)
    df

也可以反向映射回分类值

    #reverse mapping
    inv_size_mapping = {
        v : k for k ,v in size_mapping.items()
    }
    df['size'] = df['size'].map(inv_size_mapping)
    df


【编码分类标签】

Encoding class label

    import numpy as n
    class_mapping = {label : idx for idx, label in enumerate(np.unique(df['classlabel']))}
    class_mapping

利用上述class_mapping将classlabel转换为integer

    df['classlabel'] = df['classlabel'].map(class_mapping)
    df

同样可以转换回去

    inv_class_mapping = {v : k for k, v in class_mapping.items()}
    df['classlabel'] = df['classlabel'].map(inv_class_mapping)
    df

也可以直接调用sklearn库中的LabelEncoder 类进行类标签转换

    #直接采用sklearn库中的LabelEncoder进行编码
    from sklearn.preprocessing import LabelEncoder
    class_le = LabelEncoder()
    y = class_le.fit_transform(df['classlabel'].values)
    y

利用inverse_transform转换回去

class_le.inverse_transform(y)

【one-hot encoding for nominal features】

get_doommies()

使用one-hot编码时,容易引起共线性问题,在使用其他算法时容易出现bug,例如矩阵的求逆。

为避免这种问题,降低变量间的相关性,可以简单的删除one-hot编码数组中特征值的第一列,这样也不会丢失重要信息。

例如删除color_blue这一列,如果color_red=0,color_green=0,则可以判断color_blue=1.

pd.get_dummies(df[['size','color','price']],drop_first = True)

删除color_blue这一列,令drop_firt=True即可

    #为避免共线性问题,降低变量间的相关性,删除one-hot数组中特征值的第一列
    pd.get_dummies(df[['size','color','price']],drop_first = True)

【数据特征选择】

利用wine dataset 学习特征选择,以及L1,L2Z正则化数据。

【读数据】

    # read wine dataset
    df_wine = pd.read_csv("G:\Machine Learning\python machine learning\python machine learning code\code\ch04\wine.data")
    df_wine.columns = ['Class label', 'Alcohol', 'Malic acid', 'Ash',
                       'Alcalinity of ash', 'Magnesium', 'Total phenols',
                       'Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins',
                       'Color intensity', 'Hue', 'OD280/OD315 of diluted wines',
                       'Proline']
     
    print('Class labels', np.unique(df_wine['Class label']))
    df_wine.head()

【划分数据 ——训练集和测试集】

    #seperate train and test data
    from sklearn.model_selection import train_test_split
    X,y = df_wine.iloc[:,1:].values,df_wine.iloc[:,0].values
    X_train, X_test, y_train, y_test = \
                    train_test_split(X,
                                     y,
                                     test_size = 0.3,
                                     random_state = 0,
                                     stratify = y)

【feature scaling】

特征缩放在数据预处理中是及其重要的一步,除了决策树和随机森林中不需要特征缩放,其余大部分学习和优化算法都需要特征缩放,保证所有特征在同一范围内。

两个进行特征缩放的方法:normalization(规范化) and standardization(标准化)

Normalization:将数据重新规范到范围[0,1]之间,是min-max缩放中的一种。

计算公式:


 sklearn.preprocessing.MinMaxScaler 实现

    #sklearn normalization
    from sklearn.preprocessing import MinMaxScaler
    mms = MinMaxScaler()
    X_train_norm = mms.fit_transform(X_train)
    X_test_norm = mms.transform(X_test)

Standardization:将数据标准化为均值为0 方差为1

计算公式:


sklearn.preprocessing. StandardScaler实现

    #sklearn standardization
    from sklearn.preprocessing import StandardScaler
    stdsc = StandardScaler()
    X_train_std = stdsc.fit_transform(X_train)
    X_test_std = stdsc.transform(X_test)

只需要在训练集上使用fit函数,然后使用这些参数去标准化测试集或者其他新的数据集。这样就可以使得所有标准化后的数据在同一scale上,是课相互比较的数据集。

【避免过拟合的方法】

(1)收集尽可能多的训练数据

(2)通过正则化引入对于模型负责度的惩罚系数

(3)选择参数较少的简单模型

(4)降级数据维度

方法(1)一般不太可行

本文讲述通过特征选择实现的正则化和降低纬度的方法使得模型简单化。

【L1 L2正则化】

L1正则化通常会生成稀疏特征向量,大部分特征值为0。

如果数据集是高维度且有很多不相关的特征值,尤其是当不相关的维度多于样本时,L1是很好的选择。

sklearn 实现L1 L2

    # sklearn实现L1
    from sklearn.linear_model import LogisticRegression
    lr = LogisticRegression(penalty = 'l1', C = 1.0)
    lr.fit(X_train_std,y_train)
    print('Training accuracy:', lr.score(X_train_std, y_train))

SBS(Sequential Backward Selection) 序列后向选择

从特征全集开始,每次从特征集中删除一个特征x,使得删除特征x后评价函数值达到最优。

算法:定义一个判别函数J,目的是是J最小化

(1)初始化 k=d,d是数据集的维数

(2)选择使得判别函数最大的特征,

(3)从特征集中删除特征

(4)如果k达到了期望值,结束;否则返回(2)

    #SBS select features
    from sklearn.base import clone
    from itertools import combinations
    import numpy as np
    from sklearn.metrics import accuracy_score
    from sklearn.model_selection import train_test_split
    class SBS():
        def __init__(self,
                     estimator, #评估器 比如LR,KNN
                     k_features, #想要的特征个数
                     scoring = accuracy_score,#对模型的预测评分
                     test_size=0.25,
                     random_state=1):
            
            self.scoring = scoring
            self.estimator = clone(estimator)
            self.k_features = k_features
            self.test_size = test_size
            self.random_state = random_state
            
        def fit(self, X, y):
            #seperete train data and test data
            X_train, X_test, y_train, y_test = train_test_split(X, y,
                                                                test_size = self.test_size,
                                                                random_state = self.random_state)
            # dimension
            dim = X_train.shape[1]
            self.indices_ = tuple(range(dim))
            self.subsets_ = [self.indices_] #特征子集
            score = self._calc_score(X_train, y_train, X_test, y_test, self.indices_)
            self.scores_ = [score]
            
            
            while dim > self.k_features:
                scores = [] #分数
                subsets = [] #子集
                
                for p in combinations(self.indices_, r = dim - 1):
                    
                    score = self._calc_score(X_train,
                                             y_train,
                                             X_test,
                                             y_test,
                                             p)
                    
                    print(p, score)
                    
                    scores.append(score)
                    subsets.append(p)
                
                best = np.argmax(scores)
                self.indices_ = subsets[best]
                self.subsets_.append(self.indices_)
                dim -= 1
                
                self.scores_.append(scores[best])
            self.k_score_ = self.scores_[-1]
            return self
        
        def transform(self, X):
            return X[:, self.indices_]
     
        def _calc_score(self, X_train, y_train, X_test, y_test, indices):
            self.estimator.fit(X_train[:, indices], y_train)
            y_pred = self.estimator.predict(X_test[:, indices])
            score = self.scoring(y_test, y_pred)
            return score

    import matplotlib.pyplot as plt
    from sklearn.neighbors import KNeighborsClassifier
     
    knn = KNeighborsClassifier(n_neighbors=5)
     
    # selecting features
    sbs = SBS(knn, k_features=1)
    sbs.fit(X_train_std, y_train)
     
    # plotting performance of feature subsets
    k_feat = [len(k) for k in sbs.subsets_]
     
    plt.plot(k_feat, sbs.scores_, marker='o')
    plt.ylim([0.7, 1.02])
    plt.ylabel('Accuracy')
    plt.xlabel('Number of features')
    plt.grid()
    plt.tight_layout()
    # plt.savefig('images/04_08.png', dpi=300)
    plt.show()

【随机森林评估特征值的重要性】

    #随机森林选择特征值
    from sklearn.ensemble import RandomForestClassifier
     
    feat_labels = df_wine.columns[1:]
    forest = RandomForestClassifier(n_estimators=500, random_state=1)
     
    forest.fit(X_train, y_train)
    #
    importances = forest.feature_importances_
     
    indices = np.argsort(importances)[::-1]
     
    for f in range(X_train.shape[1]):
        print("%2d) %-*s %f" % (f + 1, 30,
                                feat_labels[indices[f]],
                                importances[indices[f]]))
     
    plt.title('Feature Importance')
    plt.bar(range(X_train.shape[1]),
            importances[indices],
            align='center')
     
    plt.xticks(range(X_train.shape[1]),
               feat_labels[indices], rotation=90)
    plt.xlim([-1, X_train.shape[1]])
    plt.tight_layout()
    plt.show()

【SelectFromModel 实现特征提取】

    #SelectFromModel
    from sklearn.feature_selection import SelectFromModel
    sfm = SelectFromModel(forest, threshold = 0.1, prefit = True) #threshold阈值
    X_selected = sfm.transform(X_train)
    print('Number of samples that meet this criterion:',X_selected.shape[0]

    for f in range(X_selected.shape[1]):
        print("%2d) %-*s %f" % (f + 1, 30,                  #%-*s ,其中*表示输出string间隔
                                feat_labels[indices[f]],
                                importances[indices[f]]))


想对作者说点什么?
利用Python Pandas进行数据预处理-数据清洗

4.9万

数据缺失、检测和过滤异常值、移除重复数据 数据缺失 数据缺失在大部分数据分析应用中都很常见,Pandas使用浮点值NaN表示浮点和非浮点数组中的缺失数据,他只是一个便于被检测出来的数据而已。from... 来自: YEN_CSDN的博客
python数据预处理 缺失值,指标统计
-

猜你喜欢

转载自blog.csdn.net/qq_27997957/article/details/83182036