处理丢失数据
有两种丢失数据:
- None
- np.nan(NaN)
1. None
None是Python自带的,其类型为python object。因此,None不能参与到任何计算中。
In [1]:
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
In [2]:
n1 = np.array([1,2,None])
n2 = np.array([1,2,np.nan])
In [3]:
n1.sum() #不能求和
Out[3]:
报错 TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'
In [4]:
#nan not a number可以进行计算
n2.sum()
Out[4]:
nan
object类型的运算要比int类型的运算慢得多
计算不同数据类型求和时间
%timeit np.arange(1e5,dtype=xxx).sum()
In [5]:
print('0至10000,int类型数据(1次)运行时间:')
intc = %time np.arange(0,10000,dtype = int).sum()
display(intc)
print('\n0至10000,float类型数据(1次)运行时间:')
floatc = %time np.arange(0,10000,dtype = float).sum()
display(floatc)
print('\n0至10000,object类型数据(1次)运行时间:')
objectc = %time np.arange(0,10000,dtype = object).sum()
display(objectc)
Out[5]:
0至10000,int类型数据(1次)运行时间:
CPU times: user 60 µs, sys: 37 µs, total: 97 µs
Wall time: 110 µs
49995000
0至10000,float类型数据(1次)运行时间:
CPU times: user 114 µs, sys: 70 µs, total: 184 µs
Wall time: 229 µs
49995000.0
0至10000,object类型数据(1次)运行时间:
CPU times: user 435 µs, sys: 0 ns, total: 435 µs
Wall time: 423 µs
49995000
In [6]:
#通过(平均)运行时间的对比,object类型数据相对要慢很多
print('0至10000,int类型数据(平均)运行时间:')
intc = %timeit np.arange(0,10000,dtype = int).sum()
display(intc)
print('\n0至10000,float类型数据(平均)运行时间:')
floatc = %timeit np.arange(0,10000,dtype = float).sum()
display(floatc)
print('\n0至10000,object类型数据(平均)运行时间:')
objectc = %timeit np.arange(0,10000,dtype = object).sum()
display(objectc)
Out[6]:
0至10000,int类型数据(平均)运行时间:
14.7 µs ± 33.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
None
0至10000,float类型数据(平均)运行时间:
14.5 µs ± 1.02 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)
None
0至10000,object类型数据(平均)运行时间:
412 µs ± 2.18 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
None
2. np.nan(NaN)
np.nan是浮点类型,能参与到计算中。但计算的结果总是NaN。
但可以使用np.nan*()函数来计算nan,此时视nan为0。
In [ ]:
#fill_values = 0
3. pandas中的None与NaN
1) pandas中None与np.nan都视作np.nan
创建DataFrame
In [8]:
df = DataFrame({'age':[22,33,18,19,20],
'sex':['male','female','male','female','female'],
'salary':[10000,11000,9900,8500,15000]},
index = ['张三','李四','小赵','小郭','小齐'],
columns = ['age','sex','salary','work'])
df
Out[8]:
| age | sex | salary | work |
张三 | 22 | male | 10000 | NaN |
李四 | 33 | female | 11000 | NaN |
小赵 | 18 | male | 9900 | NaN |
小郭 | 19 | female | 8500 | NaN |
小齐 | 20 | female | 15000 | NaN |
In [9]:
df.work['李四':'小郭'] = 'Pyhton'
In [10]:
df
Out[10]:
| age | sex | salary | work |
张三 | 22 | male | 10000 | NaN |
李四 | 33 | female | 11000 | Pyhton |
小赵 | 18 | male | 9900 | Pyhton |
小郭 | 19 | female | 8500 | Pyhton |
小齐 | 20 | female | 15000 | NaN |
使用DataFrame行索引与列索引修改DataFrame数据
2) pandas中None与np.nan的操作
- isnull()
- notnull()
- dropna(): 过滤丢失数据
- fillna(): 填充丢失数据
(1)判断函数
- isnull()
- notnull()
In [32]:
#根据获得的数据去除原来数据的空数据
df.isnull()
Out[32]:
| age | sex | salary | work |
张三 | False | False | False | True |
李四 | False | False | False | False |
小赵 | False | False | False | False |
小郭 | False | False | False | False |
小齐 | False | False | False | True |
In [33]:
df.isnull().any() #得到一个Series,确定work里面有空值
Out[33]:
age False
sex False
salary False
work True
dtype: bool
In [34]:
df.isnull().any(axis = 1) #得到具体的空值,空值所在的列
Out[34]:
张三 True
李四 False
小赵 False
小郭 False
小齐 True
dtype: bool
In [35]:
#返回有空值的行
s1 = df.isnull().any(axis = 1)
df[s1]
Out[10]:
| age | sex | salary | work |
张三 | 22 | male | 10000 | NaN |
小齐 | 20 | female | 15000 | NaN |
In [37]:
#notnull(),all(axis = 1) 配合索引,就可以获取不为空的数据(要求:所有的数据都不为空)
s2 = df.notnull().all(axis = 1)
df[s2]
Out[37]:
| age | sex | salary | work |
李四 | 33 | female | 11000 | Pyhton |
小赵 | 18 | male | 9900 | Pyhton |
小郭 | 19 | female | 8500 | Pyhton |
(2) 过滤函数
- dropna()
可以选择过滤的是行还是列(默认为行)
In [10]:
df.dropna(axis = 1) #默认为行,axis = 0
Out[10]:
| age | sex | salary |
张三 | 22 | male | 10000 |
李四 | 33 | female | 11000 |
小赵 | 18 | male | 9900 |
小郭 | 19 | female | 8500 |
小齐 | 20 | female | 15000 |
也可以选择过滤的方式 how = 'all'
In [40]:
df.loc['张三'] = np.nan
df
Out[40]:
| age | sex | salary | work |
张三 | NaN | NaN | NaN | NaN |
李四 | 33.0 | female | 11000.0 | Pyhton |
小赵 | 18.0 | male | 9900.0 | Pyhton |
小郭 | 19.0 | female | 8500.0 | Pyhton |
小齐 | 20.0 | female | 15000.0 | NaN |
In [41]:
df.dropna(how = 'all') #必须一行的所有数据为空,才会被去除
Out[41]:
| age | sex | salary | work |
李四 | 33.0 | female | 11000.0 | Pyhton |
小赵 | 18.0 | male | 9900.0 | Pyhton |
小郭 | 19.0 | female | 8500.0 | Pyhton |
小齐 | 20.0 | female | 15000.0 | NaN |
In [42]:
df #执行df.dropna(how = 'all') 之后,并没有删除
Out[42]:
| age | sex | salary | work |
张三 | NaN | NaN | NaN | NaN |
李四 | 33.0 | female | 11000.0 | Pyhton |
小赵 | 18.0 | male | 9900.0 | Pyhton |
小郭 | 19.0 | female | 8500.0 | Pyhton |
小齐 | 20.0 | female | 15000.0 | NaN |
(3) 填充函数 Series/DataFrame
- fillna()
In [43]:
#对所有的空数据进行替换
df.fillna('Java')
Out[43]:
| age | sex | salary | work |
张三 | Java | Java | Java | Java |
李四 | 33.0 | female | 11000.0 | Pyhton |
小赵 | 18.0 | male | 9900.0 | Pyhton |
小郭 | 19.0 | female | 8500.0 | Pyhton |
小齐 | 20.0 | female | 15000.0 | Java |
可以选择前向填充还是后向填充
对于DataFrame来说,还要选择填充的轴axis。记住,对于DataFrame来说:
- axis=0:index/行
- axis=1:columns/列
In [44]:
#{'backfill', 'bfill', 'pad', 'ffill'
df.fillna(method='backfill')
Out[44]:
| age | sex | salary | work |
张三 | 33.0 | female | 11000.0 | Pyhton |
李四 | 33.0 | female | 11000.0 | Pyhton |
小赵 | 18.0 | male | 9900.0 | Pyhton |
小郭 | 19.0 | female | 8500.0 | Pyhton |
小齐 | 20.0 | female | 15000.0 | NaN |
In [10]:
#forward-->ffill
df.fillna(method='ffill',inplace = True) #使用inplace = True,原来的数据会发生改变
df
Out[10]:
| age | sex | salary | work |
张三 | NaN | NaN | NaN | NaN |
李四 | 33.0 | female | 11000.0 | Pyhton |
小赵 | 18.0 | male | 9900.0 | Pyhton |
小郭 | 19.0 | female | 8500.0 | Pyhton |
小齐 | 20.0 | female | 15000.0 | Pyhton |
============================================
练习7:
1、简述None与NaN的区别
2、假设张三李四参加模拟考试,但张三因为突然想明白人生放弃了英语考试,因此记为None,请据此创建一个DataFrame,命名为ddd3
3、老师决定根据用数学的分数填充张三的英语成绩,如何实现? 用李四的英语成绩填充张三的英语成绩?
============================================
仅供参考学习,严禁转载!