• 数据清洗之数据预处理 重复值 缺失值 异常值 数据离散化


    数据清洗之数据预处理

     

    摩托车的销售情况数据

    • Condition:摩托车新旧情况(new:新的 和used:使用过的)
    • Condition_Desc:对当前状况的描述
    • Price:价格
    • Location:发获地址
    • Model_Year:购买年份
    • Mileage:里程
    • Exterior_Color:车的颜色
    • Make:制造商(牌子)
    • Warranty:保修
    • Model:类型
    • Sub_Model:车辆类型
    • Type:种类
    • Vehicle_Title:车辆主题
    • OBO:车辆仪表盘
    • Watch_Count:表数
    • N_Reviews:评测次数
    • Seller_Status:卖家身份
    • Auction:拍卖(Ture或者False)
    • Buy_Now:现买
    • Bid_Count:出价计数
    In [ ]:
    import numpy as np
    import pandas as pd
    import os
    
    In [ ]:
    os.chdir(r'F:CSDN课程内容代码和数据')
    
    In [ ]:
    df = pd.read_csv('MotorcycleData.csv',encoding = 'gbk',na_values='Na')
    
     na_values='Na'   对所有的空字符串做缺失值填充
    na_values='used'  对所有的‘used’的数据写成缺失值

    1. 重复值处理

    In [ ]:
    df.head(5)
    
     
    • 对价格和里程数数据进行处理
    In [ ]:
    # 自定义一个函数
    def f(x):
        if '$' in str(x):
            x = str(x).strip('$')           # 去除
            x = str(x).replace(',','')      # 替换
        else:
            x = str(x).replace(',','')
        return float(x)
    
    In [ ]:
    df['Price'] =  df['Price'] .apply(f)
    
    In [ ]:
    df['Mileage'] = df['Mileage'].apply(f)
    
    In [ ]:
    print ('数据集是否存在重复观测: 
    ', any(df.duplicated()))
    
    In [ ]:
    df[df.duplicated()] #查看那些数据重复(全部)
    
    In [ ]:
    np.sum(df.duplicated()) #计算重复数量
    
    In [ ]:
    df.drop_duplicates() #删除所有变量都重复的行, 注意没有加inplace = True,只会是视图上删除,只有加了才对原始数据改动
    
    In [ ]:
    df.drop_duplicates(subset= ['Condition','Condition_Desc','Price','Location'],inplace=True) #按照两个变量重复 来 来去重
    
    In [ ]:
    df.info()
    
     

    2. 缺失值处理

    In [ ]:
    df.apply(lambda x: sum(x.isnull())/len(x),axis= 0) #缺失比例,超过90%或95%就可以扔了
    
    In [ ]:
    #删除法
    df.dropna() #直接删除法
    
    In [ ]:
    df.dropna(how='any',axis = 1 ) #只要有缺失,就删除这一列
    df.dropna(how='all',axis = 1 ) #只有全部缺失,才删除这一列
    In [ ]:
    df.dropna(how='any',axis = 0) #只要有缺失,就删除这一行,等价于df.dropna()
    
     
    • axis = 0 或者 1代表的函数在数据集作用的方向,0代表沿着行的方向,1代表沿着列的方向
    In [ ]:
    df.dropna(axis = 0,how='any',subset=['Condition','Price','Mileage']) # 1代表列,0代表行,只要有缺失,就删除这一行,基于三个变量
    
     

    在数据分析中,实际上大部分时候都是按照行来进行删除的,很少会基于列来进行删除 列代表的是变量,是否删除删除列很多时候主要取决于缺失比例

    使用替换法进行缺失值的填补

     
    • 替换法
    In [ ]:
    df.head(10)
    
    In [ ]:
    df.Mileage.fillna(df.Mileage.mean()) # 年龄这里列 用均值填补
    
    In [ ]:
    df.Mileage.fillna(df.Mileage.median()) #中位数填补
    
    In [ ]:
    df[df['Exterior_Color'].isnull()]
    
    In [ ]:
    df.Exterior_Color.fillna(df.Exterior_Color.mode()[0]) #众数填补mode()[0],众数可能有好几个,后面表示取第一个
    In [ ]:
    df.fillna(20) # 所有缺失用20填补
    
    In [ ]:
    # 车的颜色使用众数,里程树使用均值
    df.fillna(value = {'Exterior_Color':df.Exterior_Color.mode()[0],'Mileage':df.Mileage.mean()})

    这里还是没有加inplace=True,所以数据本身没变,只是视图变化了

    In [ ]:
    df['Exterior_Color'].fillna(method='ffill') #前向填补
    
    In [ ]:
    df['Exterior_Color'].fillna(method='bfill') #后向填补
    
     

    3.异常值处理

    df.Price和df['Price']的作用应该是一样的
     
    • 异常值检测可以使用均值的2倍标准差范围,也可以使用上下4分位数差方法
    In [ ]:
    # 判断年龄有什么异常值
    # 剔除户主姓名,户主身份证号和年龄有缺失的样本
    df.dropna(axis = 0,how='any',subset=['户主姓名','户主身份证号','age'],inplace = True) #1代表列,0代表行,只要有缺失,就删除这一行,基于三个变量
    
    In [ ]:
    # 异常值检测之标准差法
    xbar = df.Price.mean()     均值
    xstd = df.Price.std()      标准差
    print('标准差法异常值上限检测:
    ',any(df.Price> xbar + 2.5 * xstd))
    print('标准差法异常值下限检测:
    ',any(df.Price< xbar - 2.5 * xstd))
    
    In [ ]:
    # 异常值检测之箱线图法
    Q1 = df.Price.quantile(q = 0.25)      取25%为分位数
    Q3 = df.Price.quantile(q = 0.75)
    IQR = Q3 - Q1                         分位差
    
    In [ ]:
    print('箱线图法异常值上限检测:
    ',any(df.Price > Q3 + 1.5 * IQR))
    print('箱线图法异常值下限检测:
    ',any(df.Price < Q1 - 1.5 * IQR))
    
    In [ ]:
    df.Price.describe()# 对价格进行描述性统计
    
    In [ ]:
     
    import matplotlib.pyplot as plt
    %matplotlib inline
    
    In [ ]:
    df.Price.plot(kind ='box')
    
    In [ ]:
    # 导入绘图模块
    import matplotlib.pyplot as plt
    # 设置绘图风格
    plt.style.use('seaborn')
    # 绘制直方图(30条柱子,密度以概率密度)
    df.Price.plot(kind = 'hist', bins = 30, density = True)
    # 绘制核密度图
    df.Price.plot(kind = 'kde')
    # 图形展现
    plt.show()
    
    In [ ]:
    # 用99分位数和1分位数替换
    #计算P1和P99
    P1 =df.Price.quantile(0.01); P99 = df.Price.quantile(0.99)
    #先创建一个新变量,进行赋值,然后将满足条件的数据进行替换
    df['Price_new'] = df['Price']
    df.loc[df['Price'] > P99,'Price_new']  = P99
    df.loc[df['Price'] < P1,'Price_new']  = P1

    回忆:
    #注意loc是标签 #注意iloc是位置


    In [ ]:
    df[['Price','Price_new']].describe()
    
     

    4.数据离散化

     
    • pandas.cut(x, bins, right=True, labels=None, retbins=False, precision=3, include_lowest=False)

    • 参数:

    • x,类array对象,且必须为一维,待切割的原形式
    • bins, 整数、序列尺度、或间隔索引。如果bins是一个整数,它定义了x宽度范围内的等宽面元数量,但是在这种情况下,x的范围在每个边上被延长1%,以保证包括x的最小值或最大值。如果bin是序列,它定义了允许非均匀bin宽度的bin边缘。在这种情况下没有x的范围的扩展。
    • right,布尔值。是否是左开右闭区间,right=True,左开右闭,right=False,左闭右开
    • labels,用作结果箱的标签。必须与结果箱相同长度。如果FALSE,只返回整数指标面元。
    • retbins,布尔值。是否返回面元
    • precision,整数。返回面元的小数点几位
    • include_lowest,布尔值。第一个区间的左端点是否包含
    In [ ]:
    df.head(5)
    
    In [ ]:
    df['Price_bin'] =  pd.cut(df['Price_new'],5,labels=range(5))
    #切分五大类,把这五份分别取0~5的标签 df['Price_bin'].hist()
     
    • 自定义分段标准和标签
    In [ ]:
    df['Price_new'].describe()
    
    In [ ]:
    w = [100,1000,5000,10000,20000,50000]
    
    In [ ]:
    df['Price_bin'] =  pd.cut(df['Price_new'], bins =w,labels=['低','便宜','划算','中等','高'],right=False)
    
    In [ ]:
    df['Price_bin'].value_counts()
    
     
     
    cut的样本是不平均的
    q cu t的样本划分下来基本是平均的
     
     
     
    • pandas.qcut(x, q, labels=None, retbins=False, precision=3, duplicates=’raise’)
    • 参数:
    • q,整数或分位数组成的数组。
    • q, 整数 或分位数数组 整数比如 4 代表 按照4分位数 进行切割 
    • labels, 用作结果箱的标签。必须与结果箱相同长度。如果FALSE,只返回整数指标面元。
     
    • 原理都是基于分位数来进行离散化
    In [ ]:
    k = 5
    w = [1.0*i/k for i in range(k+1)] 
    w

    这里w的作用就是分位
    值为[0.0,0.2,0.4,0.6,0.8,1.0]
    也就是“等频”

    In [ ]:等频分段
    df['Price_bin'] = pd.qcut(df['Price_new'],w,labels=range(k))
    # 这里的w赋值的是q这个变量
    In [ ]:
    df['Price_bin'].hist()
    
     
    • 或者先计算分位数的值
    In [ ]:
    k = 5
    w1 = df['Price_new'].quantile([1.0*i/k for i in range(k+1)])#先计算分位数,在进行分段
    w1[0] = w1[0]* 0.95 # 最小值缩小一点
    w[-1] = w1[1]* 1.05 # 将最大值增大一点, 目的是为了确保数据在这个范围
    In [ ]:
    w1
    
    In [ ]:
    df['Price_bin'] = pd.cut(df['Price_new'],w1,labels=range(k))
    df['Price_bin'].hist()



    #在上面这个例子中,有两种分的方法,其中w啊是先划分一个等频段,w1是先计算了数据本身的等频区间。

  • 相关阅读:
    《Twinkle Twinkle Little Star》
    《牛客IOI周赛24-普及组B》
    You have to remove (or rename) that container to be able to reuse that name.
    MySQL查看服务器状态、数据库、表的命令
    【用户不在sudoers文件中】的两种解决方式
    Ubuntu20.04安装Docker时摊上的那些事儿
    Ubuntu20.04安装Docker以后设置阿里云镜像加速
    Ubuntu20.04默认更新源sources.list和第三方源推荐(干货!)
    Ubuntu必备软件之搜狗输入法
    Ubuntu20.04必备软件之截图工具
  • 原文地址:https://www.cnblogs.com/xingnie/p/12264505.html
Copyright © 2020-2023  润新知