数据分析03 /基于pandas的数据清洗、级联、合并

Norsaa 2019-12-12

目录

数据分析03 /基于pandas的数据清洗、级联、合并

1. 处理丢失的数据

  • 两种丢失的数据:

    1. 种类

      None:None是对象类型,type(None):NoneType

      np.nan(NaN):是浮点型,type(np.nan):float

    2. 两种丢失数据的区别:

      object类型比float在进行运算耗时

  • 测试两种耗时时间:

    import numpy as np
    %timeit np.arange(1000,dtype=object).sum()
    # 结果:
    63.4 μs ± 1.02 μs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    
    %timeit np.arange(1000,dtype=float).sum()
    # 结果:
    6.45 μs ± 84.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

2. pandas处理空值操作

  • pandas中的None和NAN

    df = DataFrame(np.random.randint(0,100,size=(8,6)))
    df.iloc[2,3] = np.nan
    df.iloc[5,5] = None   # 在内部会强转成浮点型
    df.iloc[5,3] = np.nan
    df.iloc[7,2] = np.nan
    df
    012345
    008160.092.0991.0
    1626798.041.04380.0
    282776.0NaN4264.0
    3633063.022.09924.0
    4976068.085.02435.0
    5445950.0NaN29NaN
    66504.074.03583.0
    71778NaN33.0616.0
  • 对空值对应的行数据进行删除

    # 实现:Series、DataFrame都可以用isnull()
    df.isnull()   # 判断哪些元素为空值
    012345
    0FalseFalseFalseFalseFalseFalse
    1FalseFalseFalseFalseFalseFalse
    2FalseFalseFalseTrueFalseFalse
    3FalseFalseFalseFalseFalseFalse
    4FalseFalseFalseFalseFalseFalse
    5FalseFalseFalseTrueFalseTrue
    6FalseFalseFalseFalseFalseFalse
    7FalseFalseTrueFalseFalseFalse

    1.清洗有空值的行

    # 查看哪些行存在空值数据
    
    df.isnull().all(axis=1)   # 一般结合notnull()使用
    # 结果:
    # 0    False
    # 1    False
    # 2    False
    # 3    False
    # 4    False
    # 5    False
    # 6    False
    # 7    False
    # dtype: bool
    
    df.isnull().any(axis=1)
    # 结果:
    # 0    False
    # 1    False
    # 2     True
    # 3    False
    # 4    False
    # 5     True
    # 6    False
    # 7     True
    # dtype: bool
    
    df.notnull().all(axis=1)
    # 结果:
    # 0     True
    # 1     True
    # 2    False
    # 3     True
    # 4     True
    # 5    False
    # 6     True
    # 7    False
    # dtype: bool
    
    # 清洗有空值的行
    df.loc[df.notnull().all(axis=1)]
    
    # isnull()   --> any:true表示其对应的行中存在空值
    # notnull()  --> all:False表示其对应的行中存在空值
    012345
    0459841.065.09050.0
    1658799.034.09771.0
    3351938.054.09124.0
    4628662.054.08738.0
    6609915.032.05416.0

    2.直接使用dropna函数过滤空值对应的行数据

    # drop系列:行用axis=0,列用axis=1
    df.dropna(axis=0)
    012345
    0459841.065.09050.0
    1658799.034.09771.0
    3351938.054.09124.0
    4628662.054.08738.0
    6609915.032.05416.0
  • 将空值进行填充

    # 任意填充
    df.fillna(value=666)   # 将空值都填充成value值
    
    # 推荐使用空值近邻的值进行填充
    df.fillna(method='ffill',axis=1)  # axis轴向,method=ffill(向前),bfill(向后填充)
    
    # 如果发现还是有空值
    df.fillna(method='bfill',axis=1).fillna(method='ffill',axis=1)
    012345
    00.081.060.092.099.01.0
    162.067.098.041.043.080.0
    282.077.06.06.042.064.0
    363.030.063.022.099.024.0
    497.060.068.085.024.035.0
    544.059.050.050.029.029.0
    665.00.04.074.035.083.0
    717.078.078.033.061.06.0

3. 数据清洗案例

  • 需求:

    • 数据说明:
      • 数据是1个冷库的温度数据,1-7对应7个温度采集设备,1分钟采集一次。
    • 数据处理目标:
      • 用1-4对应的4个必须设备,通过建立冷库的温度场关系模型,预估出5-7对应的数据。
      • 最后每个冷库中仅需放置4个设备,取代放置7个设备。
      • f(1-4) --> y(5-7)
    • 数据处理过程:
      • 1、原始数据中有丢帧现象,需要做预处理;
      • 2、matplotlib 绘图;
      • 3、建立逻辑回归模型。
    • 无标准答案,按个人理解操作即可,请把自己的操作过程以文字形式简单描述一下,谢谢配合。
    • 测试数据为testData.xlsx
  • 代码实现:

    timenone1234none1567
    2019/1/27 17:00-24.8-18.2-20.8-18.8NULLNULLNULL
    2019/1/27 17:01-23.5-18.8-20.5-19.8-15.2-14.5-16
    2019/1/27 17:02-23.2-19.2NULLNULL-13NULL-14
    2019/1/27 17:03-22.8-19.2-20-20.5NULL-12.2-9.8
    2019/1/27 17:04-23.2-18.5-20-18.8-10.2-10.8-8.8
    # 预处理,将excel数据读取出来,将空列none、none1删除
    df = pd.read_excel('./data/testData.xlsx')
    df.drop(labels=['none','none1'],axis=1,inplace=True)
    df
    
    # 删除空值所在的行,如果删除的代价较大,选择填充
    df.dropna(axis=0)
    
    # 填充
    new_df = df.fillna(axis=0,method='ffill').fillna(axis=0,method='bfill')
    # 检车空值填充的情况
    new_df.isnull().any(axis=0)
    
    # 结果:
    # time    False
    # 1       False
    # 2       False
    # 3       False
    # 4       False
    # 5       False
    # 6       False
    # 7       False
    # dtype: bool

4. 处理重复的数据

  • 准备数据:

    df = DataFrame(data=np.random.randint(0,100,size=(10,8)))
    df.iloc[1] = [1,1,1,1,1,1,1,1]
    df.iloc[3] = [1,1,1,1,1,1,1,1]
    df.iloc[5] = [1,1,1,1,1,1,1,1]
    df.iloc[7] = [1,1,1,1,1,1,1,1]
    df
    01234567
    08527598114658617
    111111111
    2652694499127537
    311111111
    4476362977361590
    511111111
    6738259386492
    711111111
    82212459329429659
    91110496045582353
  • 填充重复的数据

    df.drop_duplicates(keep='last')
    
    # keep = 'first'  表示第一行保留
    # keep = 'last'  表示最后一行保留
    # keep = 'False'  表示全部都进行填充
    01234567
    08527598114658617
    2652694499127537
    4476362977361590
    6738259386492
    711111111
    82212459329429659
    91110496045582353

5. 处理异常的数据

  • 需求:自定义一个1000行3列(A,B,C)取值范围为0-1的数据源,然后将C列中的值大于其两倍标准差的异常值进行清洗

  • 实现:

    # 一个1000行3列(A,B,C)取值范围为0-1的数据源
    df = DataFrame(data=np.random.random(size=(1000,3)),columns=['A','B','C'])
    df.head()
    ABC
    00.4831950.7861520.169980
    10.0002270.5935950.378660
    20.8599770.1908640.885891
    30.7903370.8981240.244129
    40.2129190.6876660.827701
    # 计算两倍标准差
    std_twice = df['C'].std() * 2
    
    #判定异常值的条件
    df.loc[~(df['C'] > std_twice)]

6. 级联

  • pd.concat:pandas使用pd.concat函数,与np.concatenate函数类似

    参数说明:
        objs
        axis=0
        keys
        join='outer' / 'inner':表示的是级联的方式,outer会将所有的项进行级联(忽略匹配和不匹配),而inner只会将匹配的项级联到一起,不匹配的不级联
        ignore_index=False
  • 匹配级联

    df1 = DataFrame({'employee':['Bobs','Linda','Bill'],
                    'group':['Accounting','Product','Marketing'],
                   'hire_date':[1998,2017,2018]})
    pd.concat((df1,df1),axis=0)
    employeegrouphire_date
    0BobsAccounting1998
    1LindaProduct2017
    2BillMarketing2018
    0BobsAccounting1998
    1LindaProduct2017
    2BillMarketing2018
  • 不匹配级联

    • 不匹配指的是级联的维度的索引不一致。纵向级联时列索引不一致,横向级联时行索引不一致
    • 有2种连接方式:
      • 外连接:补NaN(默认模式)
      • 内连接:只连接匹配的项
    df2 = df1.copy()
    df2.columns = ['employee','groupps','hire_date']
    
    """
      employee    groupps      hire_date
    0  Bobs       Accounting     1998
    1  Linda      Product        2017
    2  Bill       Marketing      2018
    """
    
    pd.concat((df1,df2),axis=0)
    employeegroupgrouppshire_date
    0BobsAccountingNaN1998
    1LindaProductNaN2017
    2BillMarketingNaN2018
    0BobsNaNAccounting1998
    1LindaNaNProduct2017
    2BillNaNMarketing2018
  • join

    inner:只对可以匹配的项进行级联

    outer:可以级联所有的项

    pd.concat((df1,df2),axis=0,join='inner')
    employeehire_date
    0Bobs1998
    1Linda2017
    2Bill2018
    0Bobs1998
    1Linda2017
    2Bill2018
  • append函数的使用

    append只可以进行纵向的级联

    df1.append(df2)

7. 合并操作

  • 合并概述:

    • merge与concat的区别在于,merge需要依据某一共同列来进行合并
    • 使用pd.merge()合并时,会自动根据两者相同column名称的那一列,作为key来进行合并。
    • 注意每一列元素的顺序不要求一致
  • 一对一合并

    df1 = DataFrame({'employee':['Bob','Jake','Lisa'],
                    'group':['Accounting','Engineering','Engineering'],
                    })
    
    df2 = DataFrame({'employee':['Lisa','Bob','Jake'],
                    'hire_date':[2004,2008,2012],
                    })
    
    pd.merge(df1,df2,on='employee')

    df表格如下:

    employeegrouphire_date
    0LisaAccounting2004
    1JakeEngineering2016

    df2表格如下:

    groupsupervisor
    0AccountingCarly
    1EngineeringGuido
    2EngineeringSteve

    合并表格如下:

    employeegrouphire_date
    0BobAccounting2008
    1JakeEngineering2012
    2LisaEngineering2004
  • 多对多合并

    df1 = DataFrame({'employee':['Bob','Jake','Lisa'],
                     'group':['Accounting','Engineering','Engineering']})
    
    df5 = DataFrame({'group':['Engineering','Engineering','HR'],
                    'supervisor':['Carly','Guido','Steve']
                    })
    pd.merge(df1,df5,how='outer')

    df1表格如下:

    employeegroup
    0BobAccounting
    1JakeEngineering
    2LisaEngineering

    df5表格如下:

    groupsupervisor
    0EngineeringCarly
    1EngineeringGuido
    2HRSteve

    合并表格如下:

    employeegroupsupervisor
    0BobAccountingNaN
    1JakeEngineeringCarly
    2JakeEngineeringGuido
    3LisaEngineeringCarly
    4LisaEngineeringGuido
    5NaNHRSteve
  • key的规范化

    1.当列冲突时,即有多个列名称相同时,需要使用on=来指定哪一个列作为key,配合suffixes指定冲突列名

    df1 = DataFrame({'employee':['Jack',"Summer","Steve"],
                     'group':['Accounting','Finance','Marketing']})
    
    df2 = DataFrame({'employee':['Jack','Bob',"Jake"],
                     'hire_date':[2003,2009,2012],
                    'group':['Accounting','sell','ceo']})
    
    pd.merge(df1,df2,on='group')

    df1表格如下:

    employeegroup
    0JackAccounting
    1SummerFinance
    2SteveMarketing

    df2表格如下:

    employeegrouphire_date
    0JackAccounting2003
    1Bobsell2009
    2Jakeceo2012

    合并表格如下:

    employee_xgroupemployee_yhire_date
    0JackAccountingJack2003

    2.当两张表没有可进行连接的列时,可使用left_on和right_on手动指定merge中左右两边的哪一列列作为连接的列

    df1 = DataFrame({'employee':['Bobs','Linda','Bill'],
                    'group':['Accounting','Product','Marketing'],
                   'hire_date':[1998,2017,2018]})
    
    df5 = DataFrame({'name':['Lisa','Bobs','Bill'],
                    'hire_dates':[1998,2016,2007]})
    
    pd.merge(df1,df5,left_on='employee',right_on='name',how='outer')

    df1表格如下:

    employeegrouphire_date
    0BobsAccounting1998
    1LindaProduct2017
    2BillMarketing2018

    df5表格如下:

    hire_datesname
    01998Lisa
    12016Bobs
    22007Bill

    合并表格如下:

    employeegrouphire_datehire_datesname
    0BobsAccounting1998.02016.0Bobs
    1LindaProduct2017.0NaNNaN
    2BillMarketing2018.02007.0Bill
    3NaNNaNNaN1998.0Lisa

相关推荐