相关文章推荐
有腹肌的扁豆  ·  visual ...·  1 年前    · 
含蓄的显示器  ·  webassembly - How can ...·  2 年前    · 

本文主要介绍一下 Pandas 数据清洗,处理缺失值。更多 Python 进阶系列文章,请参考 Python 进阶学习 玩转数据系列

内容提要:

  1. 数据缺失的现实场景
  2. Python 中表示缺失值的对象
    ● None
    ● NaN
    ● NA
    ● 正负无穷 inf and -inf
  3. 处理缺失值
    ● 了解数据
    ● 定位缺失数据
    ● 处理缺失数据

数据缺失的现实场景

  1. 数据应用类别
    比如,患者生日,对女性来说是这个数据比较有参考意义,没有值提供的被认为是男性患者。
  2. 数据来源缺失
    比如用户调查数据,有部分用户拒绝提供数据,数据录入系统时由于数据转换被删除一部分数据。
  3. 数据无效
    输入格式不正确,或错误的数据(如,年龄 250 或 -5), 对这类数据就要处理成缺失数据

Python 中表示缺失值的对象

对象 描述
NA Not Available
NaN Not a Number
None Pythonic missing data, a Python object that can be used in arrays with data type object
inf positive infinity
-inf negative infinity
  1. None 一个 Python 对象
  2. 不可以用在任意的 NumPy 或 Pandas 数组里,只用于列表且数据类型是 Object。
  3. 默认 Pandas 会将 None 转换成 NAN
  4. 对包含 None 元素的数组进行计算(如: sum, min, max)会抛出 TypeError 异常。
  1. NaN 是一个特殊的浮点型值
  2. 带有 NaN 的值进行算术运算的结果是 NaN
  3. 可以用特殊的函数忽略 NaN: 如 np.nansum()

在这里插入图片描述
注意:NaN 是浮点型类型,如果用其它类型去访问它会抛出异常。
在这里插入图片描述

  1. Pandas 遇到缺失对象会视为 NaN
  2. NumPy数组不能处理缺失对象,但能处理 NaN 值
import pandas as pd
import io
data_pd_na = '''Gender|Age|Weight
    M | 22 | 72.0
    F | 29 | 55.0
    M | 24 |
    F || 57.0
df_na = pd.read_table (io.StringIO(data_pd_na), sep = '|')
# NumPy: Can NOT handle NA values
d2 = '''M  22  72.0
        F  29  
        M  24  78.0
        F  25  57.0
data_np_na = io.StringIO(d2)
# Should produce a ValueError
np.loadtxt(data_np_na, 
           dtype={'names': ('Gender', 'Age', 'Color'), 
                  'formats': ('S1', 'i4', 'f4')})

在这里插入图片描述
NumPy能处理 NaN的值

# Missing values as NaN
d3 = '''M  22  72.0
        F  29  NaN
        M  24  78.0
        F  25  57.0
data_np_nan = io.StringIO(d3)
# Should work with NaN missing values
np_array_nan = np.loadtxt(data_np_nan, 
                          dtype={'names': ('Gender', 'Age', 'Color'), 
                      'formats': ('S1', 'i4', 'f4')})
# an array of tuples
np.reshape (np.array (np_array_nan), (4,1))
# Missing values as NaN
d3 = '''1  22  1
        1  29  NaN
        1  24  1
        1  25  1
data_np_nan = io.StringIO(d3)
# state explicitly to treat nan as floating point
np_array_nan = np.loadtxt(data_np_nan, dtype=np.float)
print (np_array_nan)
print (np_array_nan.shape) # 4-by-3 array

在这里插入图片描述
NaN 必须是浮点型类型,不然会抛错

# should fail if try to treat nan as int:
d4 = '''1  22  1
        1  29  NaN
        1  24  1
        1  25  1
data_np_nan = io.StringIO(d4)
np_array_nan_int = np.loadtxt(data_np_nan, dtype=np.int)

正负无穷 inf and -inf

  1. 正负无穷的表示:
    ● float(“inf”) or float(“-inf”)
    ● np.inf, np.PINF, -np.inf, np.NINF
  2. 判断数字是否是正负无穷
    ● math 包的 math.isinf() 函数
    ● numpy 包的 np.isinf(), np.isposinf(), np.isneginf(), np.isfinite() 函数

正负无穷表示

import numpy as np
# positive infinity
p_inf = float("inf")
np_posinf = np.inf
np_posinf_1 = np.PINF
# negative infinity
n_inf = float("-inf")
np_neginf = -np.inf
np_neginf_1 = np.NINF
print("p_inf:{}".format(p_inf))
print("np_posinf:{}".format(np_posinf))
print("np_posinf_1:{}".format(np_posinf_1))
print("n_inf:{}".format(n_inf))
print("np_neginf:{}".format(np_neginf))
print("np_neginf_1:{}".format(np_neginf_1))
p_inf:inf
np_posinf:inf
np_posinf_1:inf
n_inf:-inf
np_neginf:-inf
np_neginf_1:-inf

判断是否是正负无穷:

import numpy as np
import pandas as pd
import io
x = np.array([-np.inf, 0., np.inf])
print("x:\n{}".format(np.isinf (x)))
data_pd_na = '''Gender|Age|Weight
    M | 22 | 72.0
    F || 55.0
    M | 24 |-inf
    F |inf| 57.0
df = pd.read_table (io.StringIO(data_pd_na), sep = '|')
inf_df = df.isin ([np.inf, -np.inf])
# Remove rows with inf
no_inf_df = df[ ~df.isin([np.inf, -np.inf]).any(1) ]
print("inf_df:\n{}".format(inf_df))
print("no_inf_df:\n{}".format(no_inf_df))

Pandas: pd.set_options() to 处理 inf, -inf

通过 pd.set_option (‘mode.use_inf_as_na’, True) 将 inf 和 -inf 用 NaN 代替

import pandas as pd
import io
#pd.set_option?
# default is False
pd.set_option ('mode.use_inf_as_na', False)
pd_option = pd.get_option ('mode.use_inf_as_na')
data_pd_inf = '''Gender|Age|Weight
    M | 22 | 72.0
    F || 55.0
    M | 24 |-inf
    F |inf| 57.0
df_inf = pd.read_table (io.StringIO(data_pd_inf), sep = '|')
print("options mode.use_inf_as_na:{}".format(pd_option))
print("df_inf:\n{}".format(df_inf))
# set mode.use_inf_as_na as true
pd.set_option ('mode.use_inf_as_na', True)
pd_option = pd.get_option ('mode.use_inf_as_na')
print("options mode.use_inf_as_na:{}".format(pd_option))
print("df_inf:\n{}".format(df_inf))

处理缺失值

  1. 了解数据
  2. 定位缺失数据
  3. 处理缺失数据

下面通过一个例子来实战一把。

通过 shape,columns,head() 等大概了解一下数据
在这里插入图片描述
在这里插入图片描述
describe() 了解一下统计信息,只支持数字类的统计,但是没有缺失数据的报告。
在这里插入图片描述

定位缺失数据

df.isin([np.nan, np.inf, -np.inf]) 判断数据是否缺失
在这里插入图片描述
df.info() 用来了解非缺失数据的数量
在这里插入图片描述
还可以通过下面几种方式更直观的了解缺失数据的数量。
df.isnull().sum()len(df.index) - df.count()
df.isnull().sum().sum() 和 *df.isnull().sum()/len(df)100
在这里插入图片描述

处理缺失数据

方法1:用 mask (Boolean) 数组过滤

● 用 df.isin([np.nan, np.inf, -np.inf]) 方法
● 用 df.any() 方法只要包含任意一个缺失的值
● 最后,用 布尔数组来进行切分

df [ ~df.isin([np.nan, np.inf, -np.inf]).any(1) ].head(5)
在这里插入图片描述

方法2:替换 inf 和 -inf 成 NaN, 然后选择 non-null 的行数据

df [ df.replace([np.inf, -np.inf], np.nan).notnull().all(axis=1) ].head(5)
在这里插入图片描述

方法3:替换 inf 和 -inf 成 NaN, 然后用 .dropna() 方法删除为空的数据

df.replace([np.inf, -np.inf], np.nan).dropna(axis=1).head(5)
在这里插入图片描述

方法4:用df.fillna(value=values) 将缺失的数据进行填充

values = {“NonD”:111, “Dream”:222, “Span”:333}
df.fillna(value = values).head()

df.fillna(555).head()
在这里插入图片描述

方法一:用一个样本统计量的值代替缺失值,通常用样本平均值和中位数。 方法二:用一个统计模型计算的值代替缺失值,通常用回归模型、判别模型等。 方法三:将有缺失值的记录删除。 这里仅展示方法一的Python实... np.nan是一个float类型的数据 None是一个NoneType类型 1、在ndarray中显示时 np.nan会显示nan,如果进行计算 结果会显示为NAN. None显示为None 并且对象为object类型,如果进行计算 结果会报错 2在pandas中, 如果其他的数据都是数值类型, pandas会把None自动替换成NaN, 甚至能将s[s.isnull()]= ... 我们获取的数据往往会存在一些重复数据,重复数据会对统计结果产生影响,也会误导决策人员的决策。 那么对DataFrame的重复项判断及删除重复项是对数据整理的基本要求。 判断数据是否有重复项 df.duplicated() df.duplicated(self,subset=None,keep='first') 可通过 drop_duplicates() 移除重复项 df.drop_duplicates(subset=['A','B'],keep='fir... df.isnull().sum(): 查看具体每个字段的缺失值个数 df.loc[df[col].isnull().values==True,:]:查看col字段存在缺失的数据 df.columns[df.isnull().any()].tolist():输出缺失字段的列表 2.删除缺失值 dropna... 顾名思义,any()一个序列中满足一个True,则返回True;all()一个序列中所有值为True时,返回True,否则为False。这点可从Series的any()和all()的例子中看出。 >>>pd.Series([False, False]).any() False >>>pd.Series([True, False]).any() >>>pd.Series([]).any() False >>>pd... 一个机器的运行周期内,内部有两个内机(不会同时运行),判断这个运行周期内,单独只运行某一个内机的情况下,该周期保留,如果该周期内,出现两个内机都有运行的阶段时,或者都没有运行的阶段时,该周期剔除。 构造一组数据说明情况,0表示关机,1表示开机 import pandas as pd df = pd.DataFrame({ '内机1': [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], '内机2': [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1] INFInfinity,代表的是无穷大的意思,也是属于浮点类型。np.inf表示正无穷大,-np.inf表示负无穷大,一般在出现除数为0的时候为无穷大。比如2/0。 NAN一些特点: NANNAN