Python Pandas中缺失值NaN的判断,删除及替换

目录
  • 前言
  • 1. 检查缺失值NaN
  • 2. Pandas中NaN的类型
  • 3. NaN的删除 dropna()
    • 3.1 删除所有值均缺失的行/列
    • 3.2 删除至少包含一个缺失值的行/列
    • 3.3 根据不缺少值的元素数量删除行/列
    • 3.4 删除特定行/列中缺少值的列/行
  • 4. 缺失值NaN的替换(填充) fillna()
    • 4.1 用通用值统一替换
    • 4.2 为每列替换不同的值
    • 4.3 用每列的平均值,中位数,众数等替换
    • 4.4 替换为上一个或下一个值
  • 总结

    前言

    当使用pandas读取csv文件时,如果元素为空,则将其视为缺失值NaN(Not a Number, 非数字)。

    使用dropna()方法删除缺失值,使用fillna()方法用其他值替换(填充)缺失值。

    如果要提取包含缺失值的行或列,使用isnull()方法确定元素是否缺失。

    1. 检查缺失值NaN

    例如,读取并使用包含带read_csv的空格的csv文件。

    import pandas as pd
    import numpy as np
    import math
    
    df = pd.read_csv('./data/05/sample_pandas_normal_nan.csv')
    print(df)
    #       name   age state  point  other
    # 0    Alice  24.0    NY    NaN    NaN
    # 1      NaN   NaN   NaN    NaN    NaN
    # 2  Charlie   NaN    CA    NaN    NaN
    # 3     Dave  68.0    TX   70.0    NaN
    # 4    Ellen   NaN    CA   88.0    NaN
    # 5    Frank  30.0   NaN    NaN    NaN
    

    使用pandas.isnull() 检查所有缺失的值:

    print(df.isnull())
    # 或者 
    print(pd.isnull(df))
    #     name    age  state  point  other
    # 0  False  False  False   True   True
    # 1   True   True   True   True   True
    # 2  False   True  False   True   True
    # 3  False  False  False  False   True
    # 4  False   True  False  False   True
    # 5  False  False   True   True   True
    

    检查 ‘name’ 列缺失的值:

    print(df['name'].isnull())
    # 0    False
    # 1     True
    # 2    False
    # 3    False
    # 4    False
    # 5    False
    Name: name, dtype: bool
    

    也可以使用numpy.isnan() 和math.isnan() (但是需要分别导入NumPy和math):

    print(pd.isnull(df.at[0, 'point']))
    print(np.isnan(df.at[0, 'point']))
    print(math.isnan(df.at[0, 'point']))
    # True
    # True
    # True
    

    2. Pandas中NaN的类型

    在Pandas中,将None,np.nan,math.nan和pd.np.nan视为缺失值NaN

    s_nan = pd.Series([None, np.nan, math.nan, pd.np.nan])
    print(s_nan)
    # 0   NaN
    # 1   NaN
    # 2   NaN
    # 3   NaN
    # dtype: float64
    
    print(s_nan[0])
    print(type(s_nan[0]))
    # nan
    # <class 'numpy.float64'>
    
    print(s_nan.isnull())
    # 0    True
    # 1    True
    # 2    True
    # 3    True
    # dtype: bool
    

    3. NaN的删除 dropna()

    使用dropna()方法删除缺失值。

    默认情况下,将返回新对象,并且不会更改原始对象,但是参数inplace = True会更改原始对象本身。

    print(df)
    #       name   age state  point  other
    # 0    Alice  24.0    NY    NaN    NaN
    # 1      NaN   NaN   NaN    NaN    NaN
    # 2  Charlie   NaN    CA    NaN    NaN
    # 3     Dave  68.0    TX   70.0    NaN
    # 4    Ellen   NaN    CA   88.0    NaN
    # 5    Frank  30.0   NaN    NaN    NaN
    

    3.1 删除所有值均缺失的行/列

    如果指定了参数how =‘all’,则将删除所有缺少值的行。

    print(df.dropna(how='all'))
    #       name   age state  point  other
    # 0    Alice  24.0    NY    NaN    NaN
    # 2  Charlie   NaN    CA    NaN    NaN
    # 3     Dave  68.0    TX   70.0    NaN
    # 4    Ellen   NaN    CA   88.0    NaN
    # 5    Frank  30.0   NaN    NaN    NaN
    

    如果设置axis = 1,则将删除所有缺少值的列。

    print(df.dropna(how='all', axis=1))
    #       name   age state  point
    # 0    Alice  24.0    NY    NaN
    # 1      NaN   NaN   NaN    NaN
    # 2  Charlie   NaN    CA    NaN
    # 3     Dave  68.0    TX   70.0
    # 4    Ellen   NaN    CA   88.0
    # 5    Frank  30.0   NaN    NaN
    

    删除所有缺少值的行和列的数据:

    df2 = df.dropna(how='all').dropna(how='all', axis=1)
    print(df2)
    #       name   age state  point
    # 0    Alice  24.0    NY    NaN
    # 2  Charlie   NaN    CA    NaN
    # 3     Dave  68.0    TX   70.0
    # 4    Ellen   NaN    CA   88.0
    # 5    Frank  30.0   NaN    NaN
    

    3.2 删除至少包含一个缺失值的行/列

    基于上面删除所有缺少值的行和列的数据df2 :

    print(df2)
    #       name   age state  point
    # 0    Alice  24.0    NY    NaN
    # 2  Charlie   NaN    CA    NaN
    # 3     Dave  68.0    TX   70.0
    # 4    Ellen   NaN    CA   88.0
    # 5    Frank  30.0   NaN    NaN
    

    如果指定了参数how =‘any’,则将删除至少包含一个缺失值的行。默认值为how =‘any’。

    print(df2.dropna(how='any'))
    #    name   age state  point
    # 3  Dave  68.0    TX   70.0
    
    print(df2.dropna())
    #    name   age state  point
    # 3  Dave  68.0    TX   70.0
    

    如果设置axis = 1,则将删除包含至少一个缺失值的列将被删除。

    print(df2.dropna(how='any', axis=1))
    #       name
    # 0    Alice
    # 2  Charlie
    # 3     Dave
    # 4    Ellen
    # 5    Frank
    

    3.3 根据不缺少值的元素数量删除行/列

    通过在参数thresh中指定数字,可以根据不缺少值的元素数量删除行和列。

    例如,如果thresh = 3,则保留包含三个或更多个不丢失值的元素的行,并删除其他行(包含两个或更多个不丢失值的元素的行)。

    print(df.dropna(thresh=3))
    #     name   age state  point  other
    # 0  Alice  24.0    NY    NaN    NaN
    # 3   Dave  68.0    TX   70.0    NaN
    # 4  Ellen   NaN    CA   88.0    NaN
    

    如果axis= 1,则应用于列。

    print(df.dropna(thresh=3, axis=1))
    #       name   age state
    # 0    Alice  24.0    NY
    # 1      NaN   NaN   NaN
    # 2  Charlie   NaN    CA
    # 3     Dave  68.0    TX
    # 4    Ellen   NaN    CA
    # 5    Frank  30.0   NaN
    

    3.4 删除特定行/列中缺少值的列/行

    如果要基于特定的行/列删除,请在列表的参数子集中指定要定位的行/列标签。由于它必须是列表,因此请至少指定一个目标,例如subset = [‘name’]。 默认情况下,子集指定的列中缺少值的行将被删除。

    print(df.dropna(subset=['age']))
    #     name   age state  point  other
    # 0  Alice  24.0    NY    NaN    NaN
    # 3   Dave  68.0    TX   70.0    NaN
    # 5  Frank  30.0   NaN    NaN    NaN
    

    如果指定了多列,则默认为删除所有缺少指定值的行。

    print(df.dropna(subset=['age', 'state']))
    #     name   age state  point  other
    # 0  Alice  24.0    NY    NaN    NaN
    # 3   Dave  68.0    TX   70.0    NaN
    

    如果参数how =‘all’,则仅删除所有指定列均缺少值的行。

    print(df.dropna(subset=['age', 'state'], how='all'))
    #       name   age state  point  other
    # 0    Alice  24.0    NY    NaN    NaN
    # 2  Charlie   NaN    CA    NaN    NaN
    # 3     Dave  68.0    TX   70.0    NaN
    # 4    Ellen   NaN    CA   88.0    NaN
    # 5    Frank  30.0   NaN    NaN    NaN
    

    4. 缺失值NaN的替换(填充) fillna()

    可以使用fillna()方法将缺失值替换为任意值。

    默认情况下,将返回新对象,并且不会更改原始对象,但是参数inplace = True会更改原始对象本身。

    print(df)
    #       name   age state  point  other
    # 0    Alice  24.0    NY    NaN    NaN
    # 1      NaN   NaN   NaN    NaN    NaN
    # 2  Charlie   NaN    CA    NaN    NaN
    # 3     Dave  68.0    TX   70.0    NaN
    # 4    Ellen   NaN    CA   88.0    NaN
    # 5    Frank  30.0   NaN    NaN    NaN
    

    4.1 用通用值统一替换

    如果指定要用参数替换的值,则所有缺少的值NaN都将替换为该值。

    print(df.fillna(0))
    #       name   age state  point  other
    # 0    Alice  24.0    NY    0.0    0.0
    # 1        0   0.0     0    0.0    0.0
    # 2  Charlie   0.0    CA    0.0    0.0
    # 3     Dave  68.0    TX   70.0    0.0
    # 4    Ellen   0.0    CA   88.0    0.0
    # 5    Frank  30.0     0    0.0    0.0
    

    4.2 为每列替换不同的值

    将字典指定为参数时,每列将替换一个不同的值。字典键是列标签(列名),而值是要替换的值。未指定的列仍缺少值NaN。

    print(df.fillna({'name': 'XXX', 'age': 20, 'point': 0}))
    #       name   age state  point  other
    # 0    Alice  24.0    NY    0.0    NaN
    # 1      XXX  20.0   NaN    0.0    NaN
    # 2  Charlie  20.0    CA    0.0    NaN
    # 3     Dave  68.0    TX   70.0    NaN
    # 4    Ellen  20.0    CA   88.0    NaN
    # 5    Frank  30.0   NaN    0.0    NaN
    

    不仅可以指定字典,还可以指定pandas.Series。具有与pandas.Series中的标签匹配的列标签(列名)的列中缺少的值将替换为pandas.Series值。与pandas.Series标签不对应的列仍然缺少值。

    s_for_fill = pd.Series(['ZZZ', 100], index=['name', 'age'])
    print(s_for_fill)
    # name    ZZZ
    # age     100
    # dtype: object
    
    print(df.fillna(s_for_fill))
    #       name    age state  point  other
    # 0    Alice   24.0    NY    NaN    NaN
    # 1      ZZZ  100.0   NaN    NaN    NaN
    # 2  Charlie  100.0    CA    NaN    NaN
    # 3     Dave   68.0    TX   70.0    NaN
    # 4    Ellen  100.0    CA   88.0    NaN
    # 5    Frank   30.0   NaN    NaN    NaN
    

    4.3 用每列的平均值,中位数,众数等替换

    可以使用mean()方法计算每列的平均值。结果是pandas.Series。缺失值将被排除并计算。

    print(df.mean())
    # age      40.666667
    # point    79.000000
    # other          NaN
    # dtype: float64
    

    如果将此pandas.Series指定为fillna()的参数,则如上所述,将相应列中的缺失值替换为平均值。

    print(df.fillna(df.mean()))
    #       name        age state  point  other
    # 0    Alice  24.000000    NY   79.0    NaN
    # 1      NaN  40.666667   NaN   79.0    NaN
    # 2  Charlie  40.666667    CA   79.0    NaN
    # 3     Dave  68.000000    TX   70.0    NaN
    # 4    Ellen  40.666667    CA   88.0    NaN
    # 5    Frank  30.000000   NaN   79.0    NaN
    

    同样,如果要替换中位数,请使用中位数()方法。在偶数的情况下,两个中心值的平均值是中值。

    print(df.fillna(df.median()))
    #       name   age state  point  other
    # 0    Alice  24.0    NY   79.0    NaN
    # 1      NaN  30.0   NaN   79.0    NaN
    # 2  Charlie  30.0    CA   79.0    NaN
    # 3     Dave  68.0    TX   70.0    NaN
    # 4    Ellen  30.0    CA   88.0    NaN
    # 5    Frank  30.0   NaN   79.0    NaN
    

    4.4 替换为上一个或下一个值

    通过使用method参数,可以替换之前和之后的值,而不是指定的值。 如果method =‘ffill’,它将被以前的值替换;如果method =‘bfill’,将被后面的值替换。对于时间序列数据很有用。

    print(df.fillna(method='ffill'))
    #       name   age state  point  other
    # 0    Alice  24.0    NY    NaN    NaN
    # 1    Alice  24.0    NY    NaN    NaN
    # 2  Charlie  24.0    CA    NaN    NaN
    # 3     Dave  68.0    TX   70.0    NaN
    # 4    Ellen  68.0    CA   88.0    NaN
    # 5    Frank  30.0    CA   88.0    NaN
    
    print(df.fillna(method='bfill'))
    #       name   age state  point  other
    # 0    Alice  24.0    NY   70.0    NaN
    # 1  Charlie  68.0    CA   70.0    NaN
    # 2  Charlie  68.0    CA   70.0    NaN
    # 3     Dave  68.0    TX   70.0    NaN
    # 4    Ellen  30.0    CA   88.0    NaN
    # 5    Frank  30.0   NaN    NaN    NaN

    使用参数limit,可以指定连续替换的最大数量。

    print(df.fillna(method='bfill', limit=1))
    #       name   age state  point  other
    # 0    Alice  24.0    NY    NaN    NaN
    # 1  Charlie   NaN    CA    NaN    NaN
    # 2  Charlie  68.0    CA   70.0    NaN
    # 3     Dave  68.0    TX   70.0    NaN
    # 4    Ellen  30.0    CA   88.0    NaN
    # 5    Frank  30.0   NaN    NaN    NaN
    

    参考博客:

    Pandas删除,替换并提取其中的缺失值NaN(dropna,fillna,isnull): https://www./article/233846.htm

    总结

    本文转自网络,如有侵权请联系客服删除。