在我们分析数据以及建立模型的过程中,需要花很多时间进行数据的预处理:数据加载、数据过滤、数据类型转换或者排序等等。这些处理占了80%甚至是更多的分析时间。有的时候,储存在文件里或者数据库里的数据格式并不能直接拿来分析。许多研究人员需要将数据进行处理,使用python, perl, R或者Java等一系列工具。其中,Python为我们提供了一个高效、灵活的、快捷的工具,使得我们可以对数据进行操作。这一章节,作者将讲解数据处理过程里的几个步骤,包括处理缺失值,重复值,字符串处理等等。
这一篇笔记记录的是如何处理缺失值NaN。
丢失数据在许多数据分析应用程序中经常发生。其中一个目标是使处理丢失数据的工作尽可能的方便快捷。例如,默认情况下,有关pandas对象的所有描述性统计信息都会排除丢失的数据。缺失数据在panda对象中表示的方式并不完美,但它对很多使用者都很有用。对于数值数据,pandas使用浮点值NaN(非数字)来表示丢失的数据。
In [1]: import pandas as pd
In [3]: import numpy as np
In [4]: string_data = pd.Series(['aardvark', 'artichoke', np.nan, 'avocado'])
In [5]: string_data
Out[5]:
0 aardvark
1 artichoke
2 NaN
3 avocado
dtype: object
In [6]: string_data.isnull() #判断是否为缺失值
Out[6]:
0 False
1 False
2 True
3 False
dtype: bool
你可以把某一个值手动的赋一个缺失值:
In [7]: string_data[0] = None #None与NA是一样的
In [8]: string_data.isnull()
Out[8]:
0 True
1 False
2 True
3 False
dtype: bool
判断是否不为缺失值:
In [9]: string_data.notnull()
Out[9]:
0 False
1 True
2 False
3 True
dtype: bool
Filtering Out Missing Data
过滤缺失值:
In [11]: from numpy import nan as NA
In [12]: data = pd.Series([1, NA, 3.5, NA, 7])
In [13]: data
Out[13]:
0 1.0
1 NaN
2 3.5
3 NaN
4 7.0
dtype: float64
In [15]: data.dropna() #把NaN去掉
Out[15]:
0 1.0
2 3.5
4 7.0
dtype: float64
In [16]: data[data.notnull()] #第二种方法去掉NaN
Out[16]:
0 1.0
2 3.5
4 7.0
dtype: float64
上面是对Series数据结构的处理方法,下面看一下对于dataframe的过滤方法:
In [17]: data = pd.DataFrame([[1., 6.5, 3.], [1., NA, NA],
...: [NA, NA, NA], [NA, 6.5, 3.]])
In [18]: data
Out[18]:
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 [19]: data.dropna()
Out[19]:
0 1 2
0 1.0 6.5 3.0
这里你会发现,对于dataframe,使用dropna
来过滤缺失值的时候,只要你的dataframe里只要有一行含有NaN,那么它会把整行都去掉。如果你只想去掉那些一整行都是NaN的数据,可以使用下面的方法:
In [20]: data.dropna(how='all')
Out[20]:
0 1 2
0 1.0 6.5 3.0
1 1.0 NaN NaN
3 NaN 6.5 3.0
这个方法只去掉了索引是2的那一行,因为整行都是NaN。
那么怎么按照列来过滤数据呢?
In [21]: data[4] =NA #先加都是NA的列
In [22]: data
Out[22]:
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 [23]: data.dropna(axis=1,how='all') #把都是NA的列去掉
Out[23]:
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
同样,你可以把dataframe其中的一些值变成NaN:
In [24]: df = pd.DataFrame(np.random.randn(7, 3)) #先生成一个dataframe
In [25]: df
Out[25]:
0 1 2
0 0.794614 -1.122838 -1.192451
1 0.309446 1.966428 -0.008502
2 -2.513006 -0.083181 1.092009
3 0.319553 0.148365 0.251443
4 -0.028759 0.223592 -0.757231
5 1.154804 1.139824 -0.140732
6 -0.407429 0.523816 -0.619919
In [26]: df.iloc[:4, 1] = NA #把索引为1的列,索引从0-4(不包含4)的行的值变成NaN
In [27]: df
Out[27]:
0 1 2
0 0.794614 NaN -1.192451
1 0.309446 NaN -0.008502
2 -2.513006 NaN 1.092009
3 0.319553 NaN 0.251443
4 -0.028759 0.223592 -0.757231
5 1.154804 1.139824 -0.140732
6 -0.407429 0.523816 -0.619919
In [28]: df.iloc[:2, 2] = NA #把索引为2的列,索引从0-2(不包含2)的行的值变成NaN
In [29]: df
Out[29]:
0 1 2
0 0.794614 NaN NaN
1 0.309446 NaN NaN
2 -2.513006 NaN 1.092009
3 0.319553 NaN 0.251443
4 -0.028759 0.223592 -0.757231
5 1.154804 1.139824 -0.140732
6 -0.407429 0.523816 -0.619919
In [30]: df.dropna() #只要有NaN的行都删除
Out[30]:
0 1 2
4 -0.028759 0.223592 -0.757231
5 1.154804 1.139824 -0.140732
6 -0.407429 0.523816 -0.619919
In [31]: df.dropna(thresh=2) #删除那些包含2个NaN的行
Out[31]:
0 1 2
2 -2.513006 NaN 1.092009
3 0.319553 NaN 0.251443
4 -0.028759 0.223592 -0.757231
5 1.154804 1.139824 -0.140732
6 -0.407429 0.523816 -0.619919
Filling In Missing Data
相比于去掉缺失值,有时你会想把缺失值填补上:
In [32]: df.fillna(0) #把所有缺失值都用0填补
Out[32]:
0 1 2
0 0.794614 0.000000 0.000000
1 0.309446 0.000000 0.000000
2 -2.513006 0.000000 1.092009
3 0.319553 0.000000 0.251443
4 -0.028759 0.223592 -0.757231
5 1.154804 1.139824 -0.140732
6 -0.407429 0.523816 -0.619919
In [33]: df.fillna({1: 0.5, 2: 0}) #针对不同列的缺失值,补充不同的值
Out[33]:
0 1 2
0 0.794614 0.500000 0.000000
1 0.309446 0.500000 0.000000
2 -2.513006 0.500000 1.092009
3 0.319553 0.500000 0.251443
4 -0.028759 0.223592 -0.757231
5 1.154804 1.139824 -0.140732
6 -0.407429 0.523816 -0.619919
fillna
功能返回的是一个新的对象,你可以改变参数,使得返回值代替原来的dataframe:
In [34]: _ = df.fillna(0, inplace=True)
In [35]: df
Out[35]:
0 1 2
0 0.794614 0.000000 0.000000
1 0.309446 0.000000 0.000000
2 -2.513006 0.000000 1.092009
3 0.319553 0.000000 0.251443
4 -0.028759 0.223592 -0.757231
5 1.154804 1.139824 -0.140732
6 -0.407429 0.523816 -0.619919
除了 fillna
功能可以对缺失值进行填充,还有一种方法是ffill
:
In [36]: df = pd.DataFrame(np.random.randn(6, 3)) #构建一个dataframe
In [37]: df.iloc[2:, 1] = NA #加入NaN值
In [38]: df.iloc[4:, 2] = NA #加入NaN值
In [39]: df
Out[39]:
0 1 2
0 -1.387958 0.550978 0.864804
1 0.486326 0.664703 -0.259249
2 -0.745425 NaN -1.389911
3 -0.532680 NaN 0.212723
4 1.530230 NaN NaN
5 0.880760 NaN NaN
In [40]: df.fillna(method='ffill') #ffill是指用缺失值的上面一个值来填充缺失值
Out[40]:
0 1 2
0 -1.387958 0.550978 0.864804
1 0.486326 0.664703 -0.259249
2 -0.745425 0.664703 -1.389911
3 -0.532680 0.664703 0.212723
4 1.530230 0.664703 0.212723
5 0.880760 0.664703 0.212723
In [41]: df.fillna(method='ffill', limit=2) #也可以规定只填充几个缺失值,剩下的依旧保留
Out[41]:
0 1 2
0 -1.387958 0.550978 0.864804
1 0.486326 0.664703 -0.259249
2 -0.745425 0.664703 -1.389911
3 -0.532680 0.664703 0.212723
4 1.530230 NaN 0.212723
5 0.880760 NaN 0.212723
fillna
还有其他的一些用法,比如说:
In [42]: data = pd.Series([1., NA, 3.5, NA, 7])
In [43]: data
Out[43]:
0 1.0
1 NaN
2 3.5
3 NaN
4 7.0
dtype: float64
In [44]: data.fillna(data.mean()) #填补的值是其他3个值的平均值
Out[44]:
0 1.000000
1 3.833333
2 3.500000
3 3.833333
4 7.000000
dtype: float64