缺失值与空值

**缺省值:**数据集中数值为空的值, pandas使用Nan / NaT 表示

**空值:**空字符串 ""

1
2
3
4
s1 = [10, 10.5, None, 11]
s2 = [7, 6.9,7.5,None]
pdata = pd.DataFrame({'s1':s1, 's2':s2})
pdata
s1 s2
0 10.0 7.0
1 10.5 6.9
2 NaN 7.5
3 11.0 NaN

缺失值判断

判断方法:

  • pd.isnull():缺省值对应的值为True,返回值为Boolean的Series或者DataFrame对象
  • pd.notnull():缺省值对应的值为False,返回值为Boolean的Series或者DataFrame对象
  • pdata.isnull() / pdata.notnull() :同上
1
2
sdata = pd.Series([1,2,3, np.NaN])
pd.isnull(sdata)

输出:

1
2
3
4
5
0    False
1 False
2 False
3 True
dtype: bool
1
2
3
4
s1 = [10, 10.5, None, 11]
s2 = [7, 6.9,7.5,None]
pdata = pd.DataFrame({'s1':s1, 's2':s2})
pd.isnull(pdata)
s1 s2
0 False False
1 False False
2 True False
3 False True

判断是否有缺失值

方式1:np.allpd.notnull结合

1
2
3
4
5
6
7
s1 = [10, 10.5, None, 11]
s2 = [7, 6.9,7.5,None]
pdata = pd.DataFrame({'s1':s1, 's2':s2})
# pd.notnull,若包含缺省值,缺省值对应值为False
# np.all:若对象中包含假,返回False, 否则返回真
np.all(pd.notnull(pdata))
# 返回False, 说明包含缺省值,否则不包含缺省值

输出:

1
False
1
2
3
4
s1 = [10, 10.5, 11]
s2 = [7, 6.9,7.5]
pdata = pd.DataFrame({'s1':s1, 's2':s2})
np.all(pd.notnull(pdata))

输出:

1
True

方式2:np.anypd.isnull结合

1
2
3
4
5
6
7
s1 = [10, 10.5, 11]
s2 = [7, 6.9,7.5]
pdata = pd.DataFrame({'s1':s1, 's2':s2})
# isnull:缺省值对应值为True
# any:对象中包含真,返回True
np.any(pd.isnull(pdata))
# 返回False,说明不含缺省值,返回True说明包括缺省值

输出:

1
False

缺省值处理方式

缺省值处理:

  • 过滤缺省值(按行列)
  • 删除缺省值(按行列)
  • 填充值,填充值方式:
  • 插入均值,中位数,最大值,最小值等
  • 插入特殊值
  • 插入前(后)值入前(后)值

缺省值过滤

举例:某两只股票1周收盘值,None表示当前停盘

需求:获取两只股票都没有停牌的数据

1
2
3
4
5
# 数据:某两只股票1周收盘值,None表示当前停盘
s1 = [10, 10.5, None, 11]
s2 = [7, 6.9,7.5,None]
pdata = pd.DataFrame({'s1':s1, 's2':s2})
pdata
s1 s2
0 10.0 7.0
1 10.5 6.9
2 NaN 7.5
3 11.0 NaN
1
2
3
4
# 需求:获取两只股票都没有停牌的数据
# 获取boolean索引
bindex = np.all(pdata.notnull(), axis=1)
bindex

输出:

1
2
3
4
5
0     True
1 True
2 False
3 False
dtype: bool
1
2
# 获取没有停牌数据
pdata[bindex]
s1 s2
0 10.0 7.0
1 10.5 6.9

删除缺省值

pdata.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)

主要参数:

参数 说明
axis 0 或 ‘index’:按行操作,1 或 ‘columns’:按列操作
how 根据 axis 指定操作方式,any:只要有一个 Na 就删除,all:全部为 Na 才删除
thresh 指定非 Na 值的数量,非 Na 数量大于等于 thresh 时不删除
subset 指定操作的列子集
inplace True:在原始数据中进行修改

准备数据:

1
2
3
4
5
6
s1 = [10, 10.5, None, 11]
s2 = [7, 6.9,7.5,None]
s3 = [7, 6.9,7.5,7]
s4 = [None, 6.9,None,7.2]
pdata = pd.DataFrame({'s1':s1, 's2':s2, 's3':s3,'s4':s4})
pdata
s1 s2 s3 s4
0 10.0 7.0 7.0 NaN
1 10.5 6.9 6.9 6.9
2 NaN 7.5 7.5 NaN
3 11.0 NaN 7.0 7.2

需求:

  1. 删除包含缺省值的行
  2. 删除包含2个缺省值行
  3. 删除指定列包含缺省值
  4. 删除包含缺省值的列
1
2
# 删除包含缺省值行
pdata.dropna()
s1 s2 s3 s4
1 10.5 6.9 6.9 6.9
1
2
3
# 缺省值数量大于1,thresh设置为3
# thresh:指定非Na数量(非Na数量>=thresh,不删除)
pdata.dropna(thresh=3)
s1 s2 s3 s4
0 10.0 7.0 7.0 NaN
1 10.5 6.9 6.9 6.9
3 11.0 NaN 7.0 7.2
1
2
# 指定列:['s1','s4']
pdata.dropna(subset=['s1','s4'])
s3
0 7.0
1 6.9
2 7.5
3 7.0

注意:

  • 以上数据删除都不对原始数据进行修改
  • 指定inplace为True,在原始数据中进行修改

缺失值填充

填充方法:

pdata.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None, **kwargs)

参数 说明
value 填充值
method 填充方式:{'backfill', 'bfill', 'pad', 'ffill', None}
axis 指定行列:0'index' 表示按行,1'columns' 表示按列
limit 插入数量限制
1
pdata
s1 s2 s3 s4
0 10.0 7.0 7.0 NaN
1 10.5 6.9 6.9 6.9
2 NaN 7.5 7.5 NaN
3 11.0 NaN 7.0 7.2

需求:

  • 缺省值填充固定值0
  • 使用前/后面数据填充
  • 使用均值填充
  • 插入均值插入均值
1
2
# 固定值0
pdata.fillna(0)
s1 s2 s3 s4
0 10.0 7.0 7.0 0.0
1 10.5 6.9 6.9 6.9
2 0.0 7.5 7.5 0.0
3 11.0 0.0 7.0 7.2
1
2
3
4
# 使用前一行数据填充
pdata.fillna(method='ffill')
# 使用向前填充 (ffill) 替代 fillna
pdata.ffill()
1
2
3
4
# 使用后一行数据填充
pdata.fillna(method='bfill')
# 使用向后填充 (bfill) 替代 fillna
pdata.bfill()
1
2
3
4
# 使用后一列数据填充
pdata.fillna(axis=1,method='bfill')
# 使用向后填充 (bfill) 替代 fillna
pdata.bfill(axis=1)

对于股票缺省值,我们倾向于,使用前一天数据填充缺失值

插入均值,中位数,最大值,最小值

pdata.mean/max/min/median(axis=None, skipna=None, level=None, numeric_only=None, **kwargs)

主要参数:

参数 说明
axis 方向,0 表示按列,1 表示按行
skipna 是否忽略 NaN,True 表示不计算 NaN,默认为 True
1
2
#插入均值
pdata.fillna(pdata.mean())
1
2
#插入中位数
pdata.fillna(pdata.median())