• pandas 缺失值、重复值的处理与值的替换


    一、删除缺失值

    在进行数据分析和建模的过程中,我们80%的时间往往花在数据准备上:加载、清理、转换、处理和重新排列。为了提高这一过程的效率,Pandas提供了一系列的高级、灵活和快速的工具集,配合Python语言内置的处理功能,可以满足绝大多数场景下的使用需求。

    Pandas中,使用numpy.nan标识缺失值,在打印的时候,经常以空字符串、NA、NaN、NULL等形式出现。Python内置的None值也被当作缺失值处理。但合法的缺失值只有NaN和None,另外一些我们自己定义的缺失值不属于语法上的,比如你将-999看作缺失值。

    在Pandas中, None和NaN的区别:

    • None被看作一个object对象,需要消耗更多的资源,处理速度更慢。不支持一些数学操作,因为None+数字是错误的语法。很多时候None会自动转换成NaN。
    • NaN是float64类型,虽然名字叫做‘不是一个数’,但却属于数字类,可以进行数学运算不会报错,虽然所有和它进行计算的最终结果依然是NaN。它的运算速度更快,还支持全局性的操作。

    以下是主要的缺失值处理方法:

    • dropna:删除缺失值
    • fillna: 用某些值填充缺失的数据或使用插值方法(比如ffillfill)
    • isnull:判断哪些值是缺失值,返回布尔
    • notnull:isnull的反函数

    通常使用dropna方法滤删除缺失值,默认它不直接修改数据,而是返回一个新对象。如果想原地修改,举一反三,请尝试inplace参数:

    In [12]: from numpy import nan as NA  # 导入惯例
    In [13]: s = pd.Series([1, NA, 3.5, NA, 7])
    In [14]: s
    Out[14]:
    0    1.0
    1    NaN
    2    3.5
    3    NaN
    4    7.0
    dtype: float64
    In [15]: s.dropna()  # 本质上就是把缺失值删除
    Out[15]:
    0    1.0
    2    3.5
    4    7.0
    dtype: float64
    In [16]: s[s.notnull()]  # 等同于上面的操作
    Out[16]:
    0    1.0
    2    3.5
    4    7.0
    dtype: float64

    在处理DataFrame对象的缺失值的时候,可能会复杂点。无法删除df的单个元素,只能整行整列的删除,dropna默认情况下会删除包含缺失值的行!为什么呢?因为DataFrame对象的每一行数据,在实际中,相当于一个样本,大量的样本中删除了一条,关系不大。但DataFrame对象的每一列相当于大量样本中共同的某个特征的值,如果删除了一个特征,那么对整个样本集的影响非常大。

    In [20]: df = pd.DataFrame([[1, 6.5, 3],[1, NA, NA],[NA, NA, NA],[NA, 6.5,3]])
    In [21]: df
    Out[21]:
         0    1    2
    0  1.0  6.5  3.0
    1  1.0  NaN  NaN
    2  NaN  NaN  NaN
    3  NaN  6.5  3.0
    In [22]: df.dropna() # 只剩1行了
    Out[22]:
         0    1    2
    0  1.0  6.5  3.0
    In [23]: df.dropna(how='all') # 只将整行都是缺失值的删除
    Out[23]:
         0    1    2
    0  1.0  6.5  3.0
    1  1.0  NaN  NaN
    3  NaN  6.5  3.0
    In [24]: df[4] = NA  # 新增一列全是缺失值
    In [25]: df
    Out[25]:
         0    1    2   4
    0  1.0  6.5  3.0 NaN
    1  1.0  NaN  NaN NaN
    2  NaN  NaN  NaN NaN
    3  NaN  6.5  3.0 NaN
    In [26]: df.dropna(axis=1, how='all') # 指定以列的形式删除
    Out[26]:
         0    1    2
    0  1.0  6.5  3.0
    1  1.0  NaN  NaN
    2  NaN  NaN  NaN
    3  NaN  6.5  3.0

    注意上面axis和how参数的用法。

    还可以通过thresh参数设置行或列中非缺失值的最小数量,在此数量以下的将被删除。

    二、补全缺失值

    所有数据都是宝贵的,大多数时候,我们不希望丢弃原始数据,而是补全缺失值。

    fillna是补全缺失值的方法,为它提供一个固定值即可:

    In [31]: df = pd.DataFrame(np.random.randn(7,3))
    In [32]: df
    Out[32]:
              0         1         2
    0 -0.229682 -0.483246 -0.063835
    1  0.716649  1.593639 -1.364550
    2 -1.362614  1.628310 -1.617992
    3  1.128828 -1.120265 -0.657313
    4  1.078143  1.136835 -0.427125
    5  0.441696  0.219477  0.695700
    6 -0.501183  1.453678 -2.734985
    In [33]: df.iloc[:4, 1] = NA
    In [35]: df.iloc[:2, 2] = NA
    In [36]: df
    Out[36]:
              0         1         2
    0 -0.229682       NaN       NaN
    1  0.716649       NaN       NaN
    2 -1.362614       NaN -1.617992
    3  1.128828       NaN -0.657313
    4  1.078143  1.136835 -0.427125
    5  0.441696  0.219477  0.695700
    6 -0.501183  1.453678 -2.734985
    In [37]: df.fillna(0)
    Out[37]:
              0         1         2
    0 -0.229682  0.000000  0.000000
    1  0.716649  0.000000  0.000000
    2 -1.362614  0.000000 -1.617992
    3  1.128828  0.000000 -0.657313
    4  1.078143  1.136835 -0.427125
    5  0.441696  0.219477  0.695700
    6 -0.501183  1.453678 -2.734985

    也可以提供一个字典,为不同的列设定不同的填充值。

    In [38]: df.fillna({1:1, 2:2})
    Out[38]:
              0         1         2
    0 -0.229682  1.000000  2.000000
    1  0.716649  1.000000  2.000000
    2 -1.362614  1.000000 -1.617992
    3  1.128828  1.000000 -0.657313
    4  1.078143  1.136835 -0.427125
    5  0.441696  0.219477  0.695700
    6 -0.501183  1.453678 -2.734985

    当然,fillna也不会原地修改数据,如果你想,请使用inplace参数:

    In [39]: _ = df.fillna(0, inplace=True)
    In [40]: df
    Out[40]:
              0         1         2
    0 -0.229682  0.000000  0.000000
    1  0.716649  0.000000  0.000000
    2 -1.362614  0.000000 -1.617992
    3  1.128828  0.000000 -0.657313
    4  1.078143  1.136835 -0.427125
    5  0.441696  0.219477  0.695700
    6 -0.501183  1.453678 -2.734985

    也可以使用ffill和bfill这种插值法填充缺失值:

    In [41]: df = pd.DataFrame(np.random.randn(6,3))
    In [42]: df.iloc[2:, 1]=NA
    In [43]: df.iloc[4:, 2]=NA
    In [44]: df
    Out[44]:
              0         1         2
    0 -0.858762  0.083342 -0.315598
    1 -0.211846  0.076648  1.188298
    2 -0.513364       NaN  0.079216
    3  0.398399       NaN -0.290225
    4 -1.375898       NaN       NaN
    5  0.932812       NaN       NaN
    In [45]: df.fillna(method='ffill') # 使用前一个值进行填充
    Out[45]:
              0         1         2
    0 -0.858762  0.083342 -0.315598
    1 -0.211846  0.076648  1.188298
    2 -0.513364  0.076648  0.079216
    3  0.398399  0.076648 -0.290225
    4 -1.375898  0.076648 -0.290225
    5  0.932812  0.076648 -0.290225
    In [46]: df.fillna(method='ffill',limit=2)  # 限制填充次数
    Out[46]:
              0         1         2
    0 -0.858762  0.083342 -0.315598
    1 -0.211846  0.076648  1.188298
    2 -0.513364  0.076648  0.079216
    3  0.398399  0.076648 -0.290225
    4 -1.375898       NaN -0.290225
    5  0.932812       NaN -0.290225
    In [47]: df.fillna(method='bfill')  # 后向填充此时无效
    Out[47]:
              0         1         2
    0 -0.858762  0.083342 -0.315598
    1 -0.211846  0.076648  1.188298
    2 -0.513364       NaN  0.079216
    3  0.398399       NaN -0.290225
    4 -1.375898       NaN       NaN
    5  0.932812       NaN       NaN

    其实使用fillna有很多技巧,需要大家平时多收集多尝试,比如使用平均值来填充:

    In [48]: s = pd.Series([1, NA, 3.5, NA, 7])
    In [49]: s.fillna(s.mean())
    Out[49]:
    0    1.000000
    1    3.833333
    2    3.500000
    3    3.833333
    4    7.000000
    dtype: float64

    三、删除重复值

    原始数据中,往往包含大量重复的行,需要我们删除,让数据集更健康。

    In [51]: df = pd.DataFrame({'k1':['one','two']*3 + ['two'], 'k2':[1,1,2,3,3,4,4]})
    In [52]: df  # 最后一行是重复的
    Out[52]:
        k1  k2
    0  one   1
    1  two   1
    2  one   2
    3  two   3
    4  one   3
    5  two   4
    6  two   4
    In [53]: df.duplicated()  # 
    Out[53]:
    0    False
    1    False
    2    False
    3    False
    4    False
    5    False
    6     True
    dtype: bool
    In [54]: df.drop_duplicates()
    Out[54]:
        k1  k2
    0  one   1
    1  two   1
    2  one   2
    3  two   3
    4  one   3
    5  two   4
    In [55]: df # 并没有改变原数据
    Out[55]:
        k1  k2
    0  one   1
    1  two   1
    2  one   2
    3  two   3
    4  one   3
    5  two   4
    6  two   4

    上面,使用duplicated方法判断各行是否有重复,并返回一个布尔值Series。然后使用drop_duplicates方法将重复行删除,留下那些不重复的。

    如果想指定根据某列的数据进行去重判断和操作,可以指定列名:

    In [56]: df['v1'] = range(7)
    In [57]: df
    Out[57]:
        k1  k2  v1
    0  one   1   0
    1  two   1   1
    2  one   2   2
    3  two   3   3
    4  one   3   4
    5  two   4   5
    6  two   4   6
    In [58]: df.drop_duplicates(['k1'])
    Out[58]:
        k1  k2  v1
    0  one   1   0
    1  two   1   1

    默认情况下都是保留第一个观察到的值,如果想保留最后一个,可以使用参数keep='last':

    In [59]: df.drop_duplicates(['k1','k2'], keep='last')
    Out[59]:
        k1  k2  v1
    0  one   1   0
    1  two   1   1
    2  one   2   2
    3  two   3   3
    4  one   3   4
    6  two   4   6

    四、替换值

    可以使用replace将pandas对象中的指定值替换为别的值:

    In [77]: df = pd.DataFrame(np.random.randint(12,size=(4,3)))
    In [78]: df
    Out[78]:
       0  1   2
    0  4  5  10
    1  3  0   3
    2  7  7   4
    3  6  4   4
    In [79]: df.replace(4, NA)  # 将4替换为缺失值
    Out[79]:
         0    1     2
    0  NaN  5.0  10.0
    1  3.0  0.0   3.0
    2  7.0  7.0   NaN
    3  6.0  NaN   NaN
    In [80]: df.replace([3,4], NA) # 将3和4都替换为缺失值
    Out[80]:
         0    1     2
    0  NaN  5.0  10.0
    1  NaN  0.0   NaN
    2  7.0  7.0   NaN
    3  6.0  NaN   NaN
    In [81]: df.replace([3,4], [NA,0]) # 3和4分别替换为缺失值和0
    Out[81]:
         0    1     2
    0  0.0  5.0  10.0
    1  NaN  0.0   NaN
    2  7.0  7.0   0.0
    3  6.0  0.0   0.0
    In [82]: df.replace({3:NA,4:0})  # 参数的字典形式
    Out[82]:
         0    1     2
    0  0.0  5.0  10.0
    1  NaN  0.0   NaN
    2  7.0  7.0   0.0
    3  6.0  0.0   0.0
  • 相关阅读:
    对xml的操作使用的类XElement的使用
    在js和C#中split应用和去除字符串分组后的空值
    C# 预定义语言
    C# 中利用 Conditional 定义条件方法
    快速结束占用端口
    详解C++中命名空间的意义和用法
    Template、ItemsPanel、ItemContainerStyle、ItemTemplate
    C++入门(2)
    C++入门(1)
    VS中的配置管理器
  • 原文地址:https://www.cnblogs.com/lavender1221/p/12724186.html
Copyright © 2020-2023  润新知