添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

20. Pandas的数据清洗-删除NaN

数据清洗(Tidy Data),是对数据进行重新审查和校验的过程,目的在于删除重复信息、纠正存在的错误,并提供数据一致性。 Pandas提供了很多的工具和函数可以对缺失、重复的数据进行相应的数据的处理。

20.1 构造缺失数据

在Pandas的各类数据Series和DataFrame里字段值为NaN的为缺失数据,不代表0而是说没有赋值数据。数据的缺失有很多原因,缺失不是错误、无效,需要对缺失的数据进行必要的技术处理,以便后续的计算、统计。

  • 构造缺失数据的DataFrame
  • import pandas as pd
    import numpy as np
    val = np.arange(10, 38).reshape(7, 4)
    col = list("abcd")
    idx = "cake make fake sake wake lake take".split()
    df = pd.DataFrame(val, columns = col, index = idx)
    print df
    df["e"] = np.nan
    df.at["make", "e"] = 100
    df.at["wake", "e"] = 300
    df.loc["jake"] = np.nan
    df.at["jake", "c"] = 200
    df["f"] = np.nan
    print df
    

    执行结果:

           a   b   c   d
    cake  10  11  12  13
    make  14  15  16  17
    fake  18  19  20  21
    sake  22  23  24  25
    wake  26  27  28  29
    lake  30  31  32  33
    take  34  35  36  37
           a   b    c   d    e   f
    cake  10  11   12  13  NaN NaN
    make  14  15   16  17  100 NaN
    fake  18  19   20  21  NaN NaN
    sake  22  23   24  25  NaN NaN
    wake  26  27   28  29  300 NaN
    lake  30  31   32  33  NaN NaN
    take  34  35   36  37  NaN NaN
    jake NaN NaN  200 NaN  NaN NaN
    

    20.2 查看缺失数据

    查看缺失数据的情况可以用pandas的isnull函数看看有那些字段上的数据缺失,可以用sum进行统计。也可使用notnull和count函数统计非NaN数据量。

    import pandas as pd
    import numpy as np
    val = np.arange(10, 38).reshape(7, 4)
    col = list("abcd")
    idx = "cake make fake sake wake lake take".split()
    df = pd.DataFrame(val, columns = col, index = idx)
    print df
    df["e"] = np.nan
    df.at["make", "e"] = 100
    df.at["wake", "e"] = 300
    df.loc["jake"] = np.nan
    df.at["jake", "c"] = 200
    df["f"] = np.nan
    print df
    print "which has Nan?\n", df.isnull(),"\n"
    print "each column has NaN\n", df.isnull().sum(),"\n"
    print "total has NaN\n", df.isnull().sum().sum(),"\n"
    print "each column values\n", df.count(),"\n"
    print "which column values\n", df.notnull(),"\n"
    

    执行结果如下:

           a   b   c   d
    cake  10  11  12  13
    take  34  35  36  37
           a   b    c   d    e   f
    cake  10  11   12  13  NaN NaN
    make  14  15   16  17  100 NaN
    fake  18  19   20  21  NaN NaN
    sake  22  23   24  25  NaN NaN
    wake  26  27   28  29  300 NaN
    lake  30  31   32  33  NaN NaN
    take  34  35   36  37  NaN NaN
    jake NaN NaN  200 NaN  NaN NaN
    which has Nan?
              a      b      c      d      e     f
    cake  False  False  False  False   True  True
    make  False  False  False  False  False  True
    fake  False  False  False  False   True  True
    sake  False  False  False  False   True  True
    wake  False  False  False  False  False  True
    lake  False  False  False  False   True  True
    take  False  False  False  False   True  True
    jake   True   True  False   True   True  True 
    each column has NaN
    a    1
    b    1
    c    0
    d    1
    e    6
    f    8
    dtype: int64 
    total has NaN
    each column values
    a    7
    b    7
    c    8
    d    7
    e    2
    f    0
    dtype: int64 
    which column values
              a      b     c      d      e      f
    cake   True   True  True   True  False  False
    make   True   True  True   True   True  False
    fake   True   True  True   True  False  False
    sake   True   True  True   True  False  False
    wake   True   True  True   True   True  False
    lake   True   True  True   True  False  False
    take   True   True  True   True  False  False
    jake  False  False  True  False  False  False 
    

    20.3 布尔选择删除

    删除NaN(主要针对列Series),在pandas里可以使用布尔选择或者dropna函数删除DataFrame的某Series列里的数据,但不会影响DataFrame本身。

    import pandas as pd
    import numpy as np
    val = np.arange(10, 38).reshape(7, 4)
    col = list("abcd")
    idx = "cake make fake sake wake lake take".split()
    df = pd.DataFrame(val, columns = col, index = idx)
    df["e"] = np.nan
    df.at["make", "e"] = 100
    df.at["wake", "e"] = 300
    df.loc["jake"] = np.nan
    df.at["jake", "c"] = 200
    df["f"] = np.nan
    print df
    print df.e[df.e.notnull()]
    print df.e.dropna()
    print df
    

    执行结果:

           a   b    c   d    e   f
    cake  10  11   12  13  NaN NaN
    make  14  15   16  17  100 NaN
    fake  18  19   20  21  NaN NaN
    sake  22  23   24  25  NaN NaN
    wake  26  27   28  29  300 NaN
    lake  30  31   32  33  NaN NaN
    take  34  35   36  37  NaN NaN
    jake NaN NaN  200 NaN  NaN NaN # print df
    make    100
    wake    300
    Name: e, dtype: float64 # print df.e[df.e.notnull()]
    make    100
    wake    300
    Name: e, dtype: float64 # print df.e.dropna()
           a   b    c   d    e   f
    cake  10  11   12  13  NaN NaN
    make  14  15   16  17  100 NaN
    fake  18  19   20  21  NaN NaN
    sake  22  23   24  25  NaN NaN
    wake  26  27   28  29  300 NaN
    lake  30  31   32  33  NaN NaN
    take  34  35   36  37  NaN NaN
    jake NaN NaN  200 NaN  NaN NaN # print df
    

    20.4 使用dropna函数删除

    如果对DataFrame使用了dropna那么行上有NaN的会被删除这行得到结果不直接会影响DataFrame本身。

    import pandas as pd
    import numpy as np
    val = np.arange(10, 38).reshape(7, 4)
    col = list("abcd")
    idx = "cake make fake sake wake lake take".split()
    df = pd.DataFrame(val, columns = col, index = idx)
    print df
    df["e"] = np.nan
    df.at["make", "e"] = 100
    print df
    print df.dropna()
    print df
    

    执行结果:

           a   b   c   d
    cake  10  11  12  13
    make  14  15  16  17
    fake  18  19  20  21
    sake  22  23  24  25
    wake  26  27  28  29
    lake  30  31  32  33
    take  34  35  36  37# print df
           a   b   c   d    e
    cake  10  11  12  13  NaN
    make  14  15  16  17  100
    fake  18  19  20  21  NaN
    sake  22  23  24  25  NaN
    wake  26  27  28  29  NaN
    lake  30  31  32  33  NaN
    take  34  35  36  37  NaN # print df
           a   b   c   d    e
    make  14  15  16  17  100 # print df.dropna()
           a   b   c   d    e
    cake  10  11  12  13  NaN
    make  14  15  16  17  100
    fake  18  19  20  21  NaN
    sake  22  23  24  25  NaN
    wake  26  27  28  29  NaN
    lake  30  31  32  33  NaN
    take  34  35  36  37  NaN # print df
    

    20.5 行删除NaN

    如果仅想删除行里全都是NaN的行,可以在dropna函数里使用how= 'all'参数。

    import pandas as pd
    import numpy as np
    val = np.arange(10, 38).reshape(7, 4)
    col = list("abcd")
    idx = "cake make fake sake wake lake take".split()
    df = pd.DataFrame(val, columns = col, index = idx)
    df["e"] = np.nan
    df.at["make", "e"] = 100
    df["f"] = np.nan
    df.loc["gake"] = np.nan 
    print df
    print "del cols is all NaN\n", df.dropna(axis = 'columns', how='all')
    print df
    print "del rows is all NaN\n", df.dropna(axis = 'rows', how='all')
    print df
    

    执行结果:

           a   b   c   d    e   f
    cake  10  11  12  13  NaN NaN
    make  14  15  16  17  100 NaN
    fake  18  19  20  21  NaN NaN
    sake  22  23  24  25  NaN NaN
    wake  26  27  28  29  NaN NaN
    lake  30  31  32  33  NaN NaN
    take  34  35  36  37  NaN NaN
    gake NaN NaN NaN NaN  NaN NaN
    del cols is all NaN
           a   b   c   d    e
    cake  10  11  12  13  NaN
    make  14  15  16  17  100
    fake  18  19  20  21  NaN
    sake  22  23  24  25  NaN
    wake  26  27  28  29  NaN
    lake  30  31  32  33  NaN
    take  34  35  36  37  NaN
    gake NaN NaN NaN NaN  NaN
           a   b   c   d    e   f
    cake  10  11  12  13  NaN NaN
    make  14  15  16  17  100 NaN
    fake  18  19  20  21  NaN NaN
    sake  22  23  24  25  NaN NaN
    wake  26  27  28  29  NaN NaN
    lake  30  31  32  33  NaN NaN
    take  34  35  36  37  NaN NaN
    gake NaN NaN NaN NaN  NaN NaN
    del rows is all NaN
           a   b   c   d    e   f
    cake  10  11  12  13  NaN NaN
    make  14  15  16  17  100 NaN
    fake  18  19  20  21  NaN NaN
    sake  22  23  24  25  NaN NaN
    wake  26  27  28  29  NaN NaN
    lake  30  31  32  33  NaN NaN
    take  34  35  36  37  NaN NaN
           a   b   c   d    e   f
    cake  10  11  12  13  NaN NaN
    make  14  15  16  17  100 NaN
    fake  18  19  20  21  NaN NaN
    sake  22  23  24  25  NaN NaN
    wake  26  27  28  29  NaN NaN
    lake  30  31  32  33  NaN NaN
    take  34  35  36  37  NaN NaN
    gake NaN NaN NaN NaN  NaN NaN
    

    20.6 设定阈值删除

    如果想保留含有若干非空值的行或者列可以使用thresh参数。

    import pandas as pd
    import numpy as np
    val = np.arange(10, 38).reshape(7, 4)
    col = list("abcd")
    idx = "cake make fake sake wake lake take".split()
    df = pd.DataFrame(val, columns = col, index = idx)
    df["e"] = np.nan
    df.at["make", "e"] = 100
    df["f"] = np.nan
    df.loc["gake"] = np.nan 
    print df
    print df.dropna(axis = 1, thresh = 2)
    

    程序里axis = 1, thresh = 2是说列上至少有两个非NaN的列留下。

           a   b   c   d    e   f
    cake  10  11  12  13  NaN NaN
    make  14  15  16  17  100 NaN
    fake  18  19  20  21  NaN NaN
    sake  22  23  24  25  NaN NaN
    wake  26  27  28  29  NaN NaN
    lake  30  31  32  33  NaN NaN
    take  34  35  36  37  NaN NaN
    gake NaN NaN NaN NaN  NaN NaN
           a   b   c   d
    cake  10  11  12  13
    make  14  15  16  17
    fake  18  19  20  21
    sake  22  23  24  25
    wake  26  27  28  29
    lake  30  31  32  33
    take  34  35  36  37
    gake NaN NaN NaN NaN
           a   b   c   d    e   f
    cake  10  11  12  13  NaN NaN
    make  14  15  16  17  100 NaN
    fake  18  19  20  21  NaN NaN
    sake  22  23  24  25  NaN NaN
    wake  26  27  28  29  NaN NaN
    lake  30  31  32  33  NaN NaN
    take  34  35  36  37  NaN NaN
    gake NaN NaN NaN NaN  NaN NaN
    

    20.7 影响DataFrame参数

    如果想dropna函数想直接影响dataframe本身可以使用参数inplace=True

    感谢Klang(金浪)智能数据看板klang.org.cn鼎力支持!