pandas库是本书后续内容的首选库。它含有使数据分析工作变得更快更简单的高级数据结构和操作工具。pandas是基于NumPy构建的。让以NumPy为中心的应用变得更加简单
要使用pandas, 首先得熟悉它的两个主要数据结构:Series和DataFrame,虽然它们不能解决所有问题,但它们为大多数应用提供了一种可靠的、易于使用的基础
本文摘要
- Series
- DataFrame
- 可以输入给DataFrame构造器的数据
- 索引对象
- 基本功能
- 重新索引
- 丢弃指定轴上的项
- 索引、选取和过滤
- 对DataFrame的索引选项(重要)
- 算数运算和数据对齐
- 在算数方法中填充值
- DataFrame和Series之前的运算
- 函数应用和映射
- 1.NumPy的ufuncs(元素级数组方法)也可用于操作pandas对象:
- 2.行列级自定义函数
- 3.使用 applymap 而非 apply 就可以采用元素级别的方法
- 排序和排名
- Series排序
- DataFrame排序
- 对 Series 值的排序
- 对DataFrame的行依据某个列的值进行排序
- 排名
- 带重复值的轴索引
- 汇总和计算描述统计
- 相关系数与协方差
- 唯一值、值计数以及成员资格
- 1.唯一值
- 2.计数
- 3.成员资格
- 处理缺失数据
- 1.滤除缺失数据
- 2.填充缺失数据
- 层次化索引
首先是常用和必要的引入
from pandas import Series, DataFrame
import pandas as pd
Series
Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及以一组与之相关的数据标签(即索引)组成。仅由一组数据即可产生最简单的Series
obj = Series([4, 7, -5, 3])
obj
Out[4]:
0 4
1 7
2 -5
3 3
dtype: int64
它拥有一些性质
obj.values
Out[5]: array([ 4, 7, -5, 3], dtype=int64)
obj.index
Out[6]: RangeIndex(start=0, stop=4, step=1)
如果希望指定各个数据点的索引,可以将这个索引的数据作为第二个参数传入series函数中
obj2 = Series([4, 7, -5, 3], index = ['d', 'b', 'a', 'c'])
obj2
Out[8]:
d 4
b 7
a -5
c 3
dtype: int64
这样就可以通过指定的索引值来访问具体数据
obj2['a']
Out[9]: -5
还可以将Series看成一个定长的有序字典,因为它是索引值映射到数据值的一个映射。它可以用在许多原来需要字典参数的函数中
如下
'b' in obj2
Out[10]: True
既然如此,也可以通过字典来创建Series
sdata = {'hello':1000, 'bye':200}
obj3 = Series(sdata)
obj3
Out[13]:
bye 200
hello 1000
dtype: int64
已经建好一个Series之后,如果再次对这个Series调用Series方法,就可以从原来的内容中筛选出部分需要的数据
如下
states = ['hello', 'hi']
obj4 = Series(sdata, index=states)
obj4
Out[16]:
hello 1000.0
hi NaN
dtype: float64
pd 中的 isnul 和 notnull 可以直接用于检测Series中值是否为NULL
pd.isnull(obj4)
Out[17]:
hello False
hi True
dtype: bool
pd.notnull(obj4)
Out[18]:
hello True
hi False
dtype: bool
对于许多应用而言,Series的最重要的一个功能是:它在算术运算中会自动对齐不同索引的数据
obj3 + obj4
Out[21]:
bye NaN
hello 2000.0
hi NaN
dtype: float64
此外,Serie对象本身及其索引都有一个name的属性,该属性跟pandas的其他关键功能的关系非常密切
obj4.name = 'population'
obj4.index.name
obj4.index.name = 'state'
obj4
Out[25]:
state
hello 1000.0
hi NaN
Name: population, dtype: float64
Series的索引可以通过赋值的方式直接修改
obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan']
DataFrame
DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引、它可以被看做由Series组成的字典(共用同一个索引)
构建DataFrame的方法有很多,最常用的一种是直接传入一个由等长列表或NumPy数组组成的字典
data = {'state':['Beijing', 'Hangzhou', 'Shanghai', 'Shenzhen'],
'year':[2000, 2001, 2002, 2001],
'pop':[1.4, 1.2, 2.3, 3.1]}
frame = DataFrame(data)
结果DataFrame会自动加上索引,并且全部列会被有序排列
frame
Out[36]:
pop state year
0 1.4 Beijing 2000
1 1.2 Hangzhou 2001
2 2.3 Shanghai 2002
3 3.1 Shenzhen 2001
如果指定了列序列,则DataFrame的列就会按照指定的顺序进行排列
DataFrame(data, columns=['year', 'state', 'pop'])
Out[37]:
year state pop
0 2000 Beijing 1.4
1 2001 Hangzhou 1.2
2 2002 Shanghai 2.3
3 2001 Shenzhen 3.1
跟Series一样,如果传入的列在数据中找不到,就会产生NA值
frame2 = DataFrame(data, columns = ['year', 'state', 'pop', 'debt'],
index = ['one', 'two', 'three','four'])
frame2
Out[40]:
year state pop debt
one 2000 Beijing 1.4 NaN
two 2001 Hangzhou 1.2 NaN
three 2002 Shanghai 2.3 NaN
four 2001 Shenzhen 3.1 NaN
类似于字典标记的方法或属性的方式,可以将DataFrame的列获取为一个Series
如下
frame2['state']
Out[7]:
one Beijing
two Hangzhou
three Shanghai
four Shenzhen
Name: state, dtype: object
frame2.year
Out[8]:
one 2000
two 2001
three 2002
four 2001
Name: year, dtype: int64
对DataFrame的行也可以进行索引,比如用索引字段 ix
frame2.ix['three']
__main__:1: DeprecationWarning:
.ix is deprecated. Please use
.loc for label based indexing or
.iloc for positional indexing
See the documentation here:
http://pandas.pydata.org/pandas-docs/stable/indexing.html#ix-indexer-is-deprecated
Out[9]:
year 2002
state Shanghai
pop 2.3
debt NaN
Name: three, dtype: object
类似NumPy数组,也可以将列以赋值的方式进行修改
frame2['debt'] = 16.5
frame2
Out[11]:
year state pop debt
one 2000 Beijing 1.4 16.5
two 2001 Hangzhou 1.2 16.5
three 2002 Shanghai 2.3 16.5
four 2001 Shenzhen 3.1 16.5
或者
frame2['debt'] = np.arange(4)
frame2
Out[15]:
year state pop debt
one 2000 Beijing 1.4 0
two 2001 Hangzhou 1.2 1
three 2002 Shanghai 2.3 2
four 2001 Shenzhen 3.1 3
将列表或者数组赋值给某个列时,其长度必须跟DataFrame的长度相等。如果赋值的是一个Series,就会精确匹配DataFrame的索引,所有的空位都会被填上缺失值
val = Series([-1.2, -1.5, -.17], index=['two', 'four', 'one'])
frame2['debt'] = val
frame2
Out[19]:
year state pop debt
one 2000 Beijing 1.4 -0.17
two 2001 Hangzhou 1.2 -1.20
three 2002 Shanghai 2.3 NaN
four 2001 Shenzhen 3.1 -1.50
为不存在的列赋值将会创建出一个新列。关键字del用于删除列
frame2['Beijing'] = frame2.state == 'Beijing'
frame2
Out[22]:
year state pop debt Beijing
one 2000 Beijing 1.4 -0.17 True
two 2001 Hangzhou 1.2 -1.20 False
three 2002 Shanghai 2.3 NaN False
four 2001 Shenzhen 3.1 -1.50 False
del frame2['Beijing']
frame2
Out[24]:
year state pop debt
one 2000 Beijing 1.4 -0.17
two 2001 Hangzhou 1.2 -1.20
three 2002 Shanghai 2.3 NaN
four 2001 Shenzhen 3.1 -1.50
注意,以索引的方式返回的列只是相应数据的视图而已,不是副本。对返回的Series的任何就地修改全都会反映到源DataFrame上
另外一种创建DataFrame的方式是通过嵌套字典。这会被解释为:外层字典的键作为列,内层键作为索引
pop = {'Nevada':{2001: 2.4, 2002:2.9},
'Ohio':{2000:1.5, 2002:3.6}}
frame3 = DataFrame(pop)
frame3
Out[27]:
Nevada Ohio
2000 NaN 1.5
2001 2.4 NaN
2002 2.9 3.6
对已经建好的DataFrame的处理又多种多样了
frame3.T
Out[29]:
2000 2001 2002
Nevada NaN 2.4 2.9
Ohio 1.5 NaN 3.6
DataFrame(pop, index=[2001, 2002, 2003])
Out[30]:
Nevada Ohio
2001 2.4 NaN
2002 2.9 3.6
2003 NaN NaN
由Series组成的字典类似
pdata = {'Ohio':frame3['Ohio'][:-1],
'Nevada':frame3['Nevada'][:2]}
DataFrame(pdata)
Out[41]:
Nevada Ohio
2000 NaN 1.5
2001 2.4 NaN
可以输入给DataFrame构造器的数据
- 二维ndarray
- 由数组、列表或元组组成的字典,每个序列变成DataFrame的一列。所有序列程度必须相同
- NumPy的结构化/记录数组
- 由Series组成的字典
- 由字典组成的字典(前文中的嵌套字典)
- …
-
如果设置了DataFrame的index和columns 的name属性,这些信息也会显示处理
frame3.index.name = 'year'; frame3.columns.name = 'state'
frame3
Out[44]:
state Nevada Ohio
year
2000 NaN 1.5
2001 2.4 NaN
2002 2.9 3.6
跟Series一样,values属性会以二维ndarray形式返回DataFrame中的数据
frame3.values
Out[45]:
array([[ nan, 1.5],
[ 2.4, nan],
[ 2.9, 3.6]])
frame2.values
Out[48]:
array([[2000, 'Beijing', 1.4, -0.17],
[2001, 'Hangzhou', 1.2, -1.2],
[2002, 'Shanghai', 2.3, nan],
[2001, 'Shenzhen', 3.1, -1.5]], dtype=object)
索引对象
Pandas的索引对象负责管理轴标签和其他元数据(比如轴名称等)。构建Series或DataFrame时,所用到的任何数组或其他序列的标签都会被转换成一个Index
obj = Series(range(3), index = ['a', 'b', 'c'])
obj
Out[3]:
a 0
b 1
c 2
dtype: int32
index = obj.index
index
Out[5]: Index(['a', 'b', 'c'], dtype='object')
访问方法与Series相似
index[1:]
Out[6]: Index(['b', 'c'], dtype='object')
index[1]
Out[7]: 'b'
但是Index对象是不可修改的(immutable),下面这条语句会导致TypeError: Index does not support mutable operations
index[1] = 'd'
不可修改性非常重要,因为这样才能使Index对象在多个数据结构之间安全共享
obj2 = Series([1.5, 2,-1], index = index)
obj2
Out[14]:
0 1.5
1 2.0
2 -1.0
dtype: float64
obj2.index is index
Out[15]: True
除了长得像数组,Index的功能也类似一个固定大小的集合,也就是说可以通过类似'Ohio' in frame3.index
这样的方法访问
index的方法和属性
- append
- diff
- intersection
- union
- isin
- delete
- unique 计算Index中的唯一值
- …
基本功能
重新索引
pandas对象的一个重要方法就是重新索引,当某个索引值当前不存在,就引入缺失值
obj = Series([4.5, 7.1, 1.1, -2.3], index = ['d', 'b', 'a', 'c'])
obj
Out[24]:
d 4.5
b 7.1
a 1.1
c -2.3
dtype: float64
obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])
obj2
Out[26]:
a 1.1
b 7.1
c -2.3
d 4.5
e NaN
dtype: float64
也可以指定值填充
obj.reindex(['a', 'b', 'c', 'd', 'e'], fill_value=0)
Out[27]:
a 1.1
b 7.1
c -2.3
d 4.5
e 0.0
dtype: float64
对于时间序列这样的有序数据,重新索引时可能需要做一些差值处理,method方法可以达到此目的,比如下面的用后向值填充
obj3 = Series(['Blue', 'purple', 'yellow'], index=[0,2,4])
obj3
Out[29]:
0 Blue
2 purple
4 yellow
dtype: object
obj3.reindex(range(6), method='bfill')
Out[30]:
0 Blue
1 purple
2 purple
3 yellow
4 yellow
5 NaN
dtype: object
此外reindex的(插值)method选项
- ffill 前向填充
- bfill 后向填充
对于DataFrame,reindex可以修改行索引,列索引,也可以两个都修改,如果只传入一个,则重新索引行
frame = DataFrame(np.arange(9).reshape((3,3)), index=['a','c','d'],
columns=['Ohio', 'Texas', 'California'])
frame
Out[33]:
Ohio Texas California
a 0 1 2
c 3 4 5
d 6 7 8
frame2 = frame.reindex('a b c d'.split())
frame2
Out[35]:
Ohio Texas California
a 0.0 1.0 2.0
b NaN NaN NaN
c 3.0 4.0 5.0
d 6.0 7.0 8.0
states = ['Texas', 'Utah', 'Califor']
frame.reindex(columns=states)
Out[37]:
Texas Utah Califor
a 1 NaN NaN
c 4 NaN NaN
d 7 NaN NaN
使用 ix 标签索引功能,重新索引任务变得更加简洁
frame.ix[['a','b','c','d'], states]
__main__:1: DeprecationWarning:
.ix is deprecated. Please use
.loc for label based indexing or
.iloc for positional indexing
See the documentation here:
http://pandas.pydata.org/pandas-docs/stable/indexing.html#ix-indexer-is-deprecated
Out[47]:
Texas Utah Califor
a 1.0 NaN NaN
b NaN NaN NaN
c 4.0 NaN NaN
d 7.0 NaN NaN
reindex函数的参数
- index
- method
- fill_value
- limit
- level
- copy
丢弃指定轴上的项
先建立一个pandas结构
data = DataFrame(np.arange(16).reshape((4, 4)),
index = 'Ohio Colorado Utah NewYork'.split(),
columns = 'one two three four'.split())
data
Out[55]:
one two three four
Ohio 0 1 2 3
Colorado 4 5 6 7
Utah 8 9 10 11
NewYork 12 13 14 15
如果试图删除一个不存在的行或列,则会触发一个ValueError: labels ['Beijing'] not contained in axis
删除一整行的元素可以直接用data.drop('NewYork')
data2 = data.drop('Ohio')
data2
Out[61]:
one two three four
Colorado 4 5 6 7
Utah 8 9 10 11
NewYork 12 13 14 15
如果希望删除一整列的元素,则需要增加一个axis=1
的说明
data.drop('two', axis = 1)
Out[64]:
one three four
Ohio 0 2 3
Colorado 4 6 7
Utah 8 10 11
NewYork 12 14 15
索引、选取和过滤
对行元素的索引总是十分简单的,跟纯Python的数组和Series类似,不同的是,这里的切片是包含末端的(仅是对于用标签切片,用数字切片还是不包含末端的)
先建立一个pandas结构
obj = Series(np.arange(4.), index = 'a b c d'.split())
obj
Out[70]:
a 0.0
b 1.0
c 2.0
d 3.0
dtype: float64
下面是索引的示例
obj['b']
Out[71]: 1.0
obj[1]
Out[72]: 1.0
obj[2:4]
Out[73]:
c 2.0
d 3.0
dtype: float64
obj['b a d'.split()]
Out[74]:
b 1.0
a 0.0
d 3.0
dtype: float64
obj[obj<2]
Out[75]:
a 0.0
b 1.0
dtype: float64
obj['b':'c']
Out[76]:
b 1.0
c 2.0
dtype: float64
obj['b':'c'] = 5
obj
Out[78]:
a 0.0
b 5.0
c 5.0
d 3.0
dtype: float64
使用前文中用到的data
data['one']
Out[82]:
Ohio 0
Colorado 4
Utah 8
NewYork 12
Name: one, dtype: int32
这样看只是需要在调用drop方法的时候特别地标明 axis = 1
而在简单的索引的时候是可以直接索引到的
下面再展示一些其他的选取方法
data[data['three']>5]
Out[86]:
one two three four
Colorado 4 5 6 7
Utah 8 9 10 11
NewYork 12 13 14 15
data<5
Out[87]:
one two three four
Ohio True True True True
Colorado True False False False
Utah False False False False
NewYork False False False False
data[data<5]
Out[88]:
one two three four
Ohio 0.0 1.0 2.0 3.0
Colorado 4.0 NaN NaN NaN
Utah NaN NaN NaN NaN
NewYork NaN NaN NaN NaN
data[data<5] = 0
data
Out[90]:
one two three four
Ohio 0 0 0 0
Colorado 0 5 6 7
Utah 8 9 10 11
NewYork 12 13 14 15
ix 方法也很有意义
data.ix[data.three >5, :3]
Out[95]:
one two three
Colorado 0 5 6
Utah 8 9 10
NewYork 12 13 14
data.ix[1,2]
Out[96]: 6
对DataFrame的索引选项(重要)
- obj [ val ] 选取DataFrame的单个列或一组列
- obj.ix [ val ] 选取DataFrame的单个行或一组行
- obj.ix [ :, val] 选取单个列或列子集
- obj.ix [ val1, val2] 同时选取行或列
- reindex 方法 将一个或多个轴匹配到新索引
总结,如果希望总是成功选取,建议使用 ix 方法
算数运算和数据对齐
pandas最重要的一个功能是,它可以对不同索引的对象进行算数运算。将对象相加时,如果存在不同的索引对,则结果的索引就是该索引对的并集
下面是一个例子,先建立两个Series
s1 = Series([7.3, -2.5, 3.4, 5], index='a c d e'.split())
s2 = Series([-2, 3, 2, 5,10], index='a c e f g'.split())
s1
Out[112]:
a 7.3
c -2.5
d 3.4
e 5.0
dtype: float64
s2
Out[113]:
a -2
c 3
e 2
f 5
g 10
dtype: int64
s1+s2
Out[114]:
a 5.3
c 0.5
d NaN
e 7.0
f NaN
g NaN
dtype: float64
可见,重叠的项(都有的)值相加,不同的项,为NA值
如果在DataFrame,对齐操作会发生在行和列上
df1 = DataFrame(np.arange(16).reshape((4, 4)),
index = 'Ohio Colorado Utah NewYork'.split(),
columns = 'one two three four'.split())
df2 = DataFrame(np.arange(9).reshape((3, 3)),
index = 'Ohio Colorado NewYork'.split(),
columns = 'one two four'.split())
df1+df2
Out[121]:
four one three two
Colorado 12.0 7.0 NaN 9.0
NewYork 23.0 18.0 NaN 20.0
Ohio 5.0 0.0 NaN 2.0
Utah NaN NaN NaN NaN
在算数方法中填充值
为了避免不重叠值会产生NA,可使用add方法,并且指定 fill_value = 0
df1.add(df2, fill_value = 0)
Out[123]:
four one three two
Colorado 12.0 7.0 6.0 9.0
NewYork 23.0 18.0 14.0 20.0
Ohio 5.0 0.0 2.0 2.0
Utah 11.0 8.0 10.0 9.0
灵活的算数方法
- add
- sub
- div
- mul
DataFrame和Series之前的运算
首先展示一个NumPy的广播
arr = np.arange(12.).reshape((3,4))
arr
Out[125]:
array([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]])
arr[0]
Out[126]: array([ 0., 1., 2., 3.])
arr - arr[0]
Out[127]:
array([[ 0., 0., 0., 0.],
[ 4., 4., 4., 4.],
[ 8., 8., 8., 8.]])
DataFrame的广播是类似的
frame = DataFrame(np.arange(12.).reshape((4,3)), columns=list('bde'),
index = 'Utah Ohio Texas Oregon'.split())
frame
Out[129]:
b d e
Utah 0.0 1.0 2.0
Ohio 3.0 4.0 5.0
Texas 6.0 7.0 8.0
Oregon 9.0 10.0 11.0
frame - series
Out[133]:
b d e
Utah 0.0 0.0 0.0
Ohio 3.0 3.0 3.0
Texas 6.0 6.0 6.0
Oregon 9.0 9.0 9.0
如果希望匹配行且在行上广播,则必须要使用算数运算方法,如下
series3 = frame['d']
frame.sub(series3, axis=0)
Out[139]:
b d e
Utah -1.0 0.0 1.0
Ohio -1.0 0.0 1.0
Texas -1.0 0.0 1.0
Oregon -1.0 0.0 1.0
函数应用和映射
1.NumPy的ufuncs(元素级数组方法)也可用于操作pandas对象:
frame
Out[144]:
b d e
Utah 0.706821 0.626728 -0.511381
Ohio 3.949706 -1.771924 -0.416144
Texas -0.496887 -0.894768 -0.857036
Oregon 1.301712 -0.264923 -2.200233
np.abs(frame)
Out[145]:
b d e
Utah 0.706821 0.626728 0.511381
Ohio 3.949706 1.771924 0.416144
Texas 0.496887 0.894768 0.857036
Oregon 1.301712 0.264923 2.200233
2.行列级自定义函数
也可以对DataFrame采用自己定义的函数,默认是对列
f = lambda x: x.max() - x.min()
frame.apply(f)
Out[147]:
b 4.446593
d 2.398652
e 1.784089
dtype: float64
增加 axis 说明可以方便地转化到对行操作
frame.apply(f, axis=1)
Out[148]:
Utah 1.218203
Ohio 5.721630
Texas 0.397881
Oregon 3.501945
dtype: float64
除了标量以外,传递给apply函数的还可以返回由多个值组成的Series
def f(x):
return Series([x.min(), x.max()], index = ['min', 'max'])
frame
Out[151]:
b d e
Utah 0.706821 0.626728 -0.511381
Ohio 3.949706 -1.771924 -0.416144
Texas -0.496887 -0.894768 -0.857036
Oregon 1.301712 -0.264923 -2.200233
frame.apply(f)
Out[152]:
b d e
min -0.496887 -1.771924 -2.200233
max 3.949706 0.626728 -0.416144
3.使用 applymap 而非 apply 就可以采用元素级别的方法
如下是一个将浮点数格式化为字符串的方法
format = lambda x: '%.2f' %x
frame.applymap(format)
Out[154]:
b d e
Utah 0.71 0.63 -0.51
Ohio 3.95 -1.77 -0.42
Texas -0.50 -0.89 -0.86
Oregon 1.30 -0.26 -2.20
排序和排名
Series排序
可以直接使用 sort_index()方法
obj = Series(range(4), index = list('badc'))
obj
Out[157]:
b 0
a 1
d 2
c 3
dtype: int32
obj.sort_index()
Out[158]:
a 1
b 0
c 3
d 2
dtype: int32
DataFrame排序
默认对行进行排序
frame = DataFrame(np.arange(8).reshape((2,4)), index=['three', 'one'],
columns = list('dabc'))
frame
Out[160]:
d a b c
three 0 1 2 3
one 4 5 6 7
frame.sort_index()
Out[161]:
d a b c
one 4 5 6 7
three 0 1 2 3
下面两个例子展示了如何通过更改传入参数,实现降序排序和按照列排序
frame.sort_index(axis=1)
Out[162]:
a b c d
three 1 2 3 0
one 5 6 7 4
frame.sort_index(axis=1, ascending=False)
Out[163]:
d c b a
three 0 3 2 1
one 4 7 6 5
对 Series 值的排序
obj.sort_values()
Out[168]:
2 -1
3 2
0 4
1 7
dtype: int64
这个地方采用书上的 order() 方法会出现错误,所以这里采用 sort_value() 方法
对DataFrame的行依据某个列的值进行排序
后面一种方法实现了先按照 ‘a’ 排序, 后按照 ‘ b’ 排序
frame
Out[170]:
a b
0 0 4
1 1 7
2 0 -3
3 1 2
frame.sort_index(by='b')
__main__:1: FutureWarning: by argument to sort_index is deprecated,
pls use .sort_values(by=...)
Out[171]:
a b
2 0 -3
3 1 2
0 0 4
1 1 7
frame.sort_index(by=['a', 'b'])
__main__:1: FutureWarning: by argument to sort_index is deprecated,
pls use .sort_values(by=...)
Out[172]:
a b
2 0 -3
0 0 4
3 1 2
1 1 7
排名
排名 rank 与排序相似,会增设一个排名值,从1开始一直数到数组中的有效值,这里可以看出,相同值对应的排名是相同的,但这不是简单的 “并列第几” ,而是 “为各组分配一个平均排名” 的方式来破坏平级关系
obj = Series([7,-5,7,4,2,0,4])
obj
Out[175]:
0 7
1 -5
2 7
3 4
4 2
5 0
6 4
dtype: int64
obj.rank()
Out[174]:
0 6.5
1 1.0
2 6.5
3 4.5
4 3.0
5 2.0
6 4.5
dtype: float64
排名时用于破坏平级关系的method选项:average; min; max; first
带重复值的轴索引
截止目前,所有的范例都有唯一的轴标签(索引值),虽然许多pandas函数都有唯一标签值的要求,但是这并不是唯一的。
下面是一个例子
obj = Series(range(5), index=list('aabbc'))
obj
Out[177]:
a 0
a 1
b 2
b 3
c 4
dtype: int32
可以通过 is_unique
方法判断标签是否唯一,当然先要取 index
obj.index.is_unique
Out[178]: False
obj['a']
Out[179]:
a 0
a 1
dtype: int32
汇总和计算描述统计
跟NumPy数组方法相比,pandas的统计方法,如sum和mean
都是适用于缺失数据的
df = DataFrame([[1.4, np.nan],[7.1, -4.5],
[np.nan,np.nan],[0.75, -1.3]],
index = list('abcd'),
columns = ['one', 'two'])
df
Out[181]:
one two
a 1.40 NaN
b 7.10 -4.5
c NaN NaN
d 0.75 -1.3
df.sum()
Out[182]:
one 9.25
two -5.80
dtype: float64
df.sum(axis = 1)
Out[183]:
a 1.40
b 2.60
c 0.00
d -0.55
dtype: float64
用于查找最大的数
df.idxmax()
Out[184]:
one b
two d
dtype: object
cumsum是用于计算累加值的
df.cumsum()
Out[186]:
one two
a 1.40 NaN
b 8.50 -4.5
c NaN NaN
d 9.25 -5.8
describe方法可以生成汇总统计
df.describe()
Out[187]:
one two
count 3.000000 2.000000
mean 3.083333 -2.900000
std 3.493685 2.262742
min 0.750000 -4.500000
25% 1.075000 -3.700000
50% 1.400000 -2.900000
75% 4.250000 -2.100000
max 7.100000 -1.300000
描述和汇总统计
- count
- describe
- min、max
- argmin、argmax
- idmax
- mean、median
- var、std
- 还有三阶矩等统计量…
相关系数与协方差
这部分安装包的时候出了点问题,暂时不写
唯一值、值计数以及成员资格
1.唯一值
obj = Series(list('cadaabbcc'))
uniques = obj.unique()
uniques
Out[194]: array(['c', 'a', 'd', 'b'], dtype=object)
2.计数
obj.value_counts()
Out[195]:
a 3
c 3
b 2
d 1
dtype: int64
pd还有一个顶级方法也可以用于计数
pd.value_counts(obj.values, sort=False)
Out[196]:
c 3
b 2
a 3
d 1
dtype: int64
3.成员资格
make = obj.isin(['b','c'])
make
Out[198]:
0 True
1 False
2 False
3 False
4 False
5 True
6 True
7 True
8 True
dtype: bool
obj[make]
Out[199]:
0 c
5 b
6 b
7 c
8 c
dtype: object
有时,你可能希望得到DataFrame中多个相关列的一张柱状图,可用如下方法
data = DataFrame({'Qu1':[1,2,3,4,5],
'Qu2':[2,3,1,4,3],
'Qu3':[4,-1,2,3,4]})
data
Out[201]:
Qu1 Qu2 Qu3
0 1 2 4
1 2 3 -1
2 3 1 2
3 4 4 3
4 5 3 4
result = data.apply(pd.value_counts).fillna(0)
result
Out[203]:
Qu1 Qu2 Qu3
-1 0.0 0.0 1.0
1 1.0 1.0 0.0
2 1.0 1.0 1.0
3 1.0 2.0 1.0
4 1.0 1.0 2.0
5 1.0 0.0 0.0
处理缺失数据
pandas使用浮点值NaN(Not a Number)表示浮点和非浮点数组中的缺失值。
检测可以通过.isnull()
方法,此外,Python内置的None值
也会被当成NA处理
处理缺失数据有以下方法
- dropna(根据标签的值中是否有缺失数据对轴标签进行过滤,可以通过调节阈值来调节对缺失值的容忍度)
- fillna
- isnull
- notnull
1.滤除缺失数据
from numpy import nan as NA
data = Series([1, NA, 3.5, NA, 7])
data.dropna()
Out[206]:
0 1.0
2 3.5
4 7.0
dtype: float64
筛选出非NA项
data[data.notnull()]
Out[208]:
0 1.0
2 3.5
4 7.0
dtype: float64
dropna默认的 how 参数是 ‘any’, 意为只要有NA,就丢弃全行数据
data = DataFrame([[1,1,1],[1,NA, NA],[NA,NA,NA],[NA,6,3]])
data
Out[210]:
0 1 2
0 1.0 1.0 1.0
1 1.0 NaN NaN
2 NaN NaN NaN
3 NaN 6.0 3.0
cleaned = data.dropna()
cleaned
Out[212]:
0 1 2
0 1.0 1.0 1.0
如果把 how 参数改为 ‘all’ 就可以仅删除全部都是NA的数据
data.dropna(how = 'all')
Out[214]:
0 1 2
0 1.0 1.0 1.0
1 1.0 NaN NaN
3 NaN 6.0 3.0
如果希望对列进行操作,只要把 axis 参数改成 1 即可
data[4] = NA
data
Out[216]:
0 1 2 4
0 1.0 1.0 1.0 NaN
1 1.0 NaN NaN NaN
2 NaN NaN NaN NaN
3 NaN 6.0 3.0 NaN
data.dropna(axis = 1, how = 'all')
Out[217]:
0 1 2
0 1.0 1.0 1.0
1 1.0 NaN NaN
2 NaN NaN NaN
3 NaN 6.0 3.0
2.填充缺失数据
首先建立一个有NA值的DataFrame
df = DataFrame(randn(7,3))
df
Out[220]:
0 1 2
0 -0.559138 0.118788 1.594997
1 0.128713 0.321041 1.668125
2 -2.242085 0.452067 0.756208
3 0.256609 -1.662545 -0.464385
4 -1.815116 0.055104 -2.114799
5 1.057346 2.427503 1.233321
6 -0.543657 -0.276028 0.948238
df.ix[:4,1] = NA
df.ix[:2,2] = NA
df
Out[226]:
0 1 2
0 -0.559138 NaN NaN
1 0.128713 NaN NaN
2 -2.242085 NaN NaN
3 0.256609 NaN -0.464385
4 -1.815116 NaN -2.114799
5 1.057346 2.427503 1.233321
6 -0.543657 -0.276028 0.948238
用字典的方式可以对不同的列用不同的值进行填充
df.fillna({1:0.5,3:-1})
Out[227]:
0 1 2
0 -0.559138 0.500000 NaN
1 0.128713 0.500000 NaN
2 -2.242085 0.500000 NaN
3 0.256609 0.500000 -0.464385
4 -1.815116 0.500000 -2.114799
5 1.057346 2.427503 1.233321
6 -0.543657 -0.276028 0.948238
fillna默认是返回新数组,但是也可以通过修改参数的方法,就地修改
_ = df.fillna(0, inplace=True)
此外还可以通过参数method='ffill'
等方式,前向填充或者后向填充
fillna参数
- value
- method
- axis
- inplace
- limit
层次化索引
层次化索引也是pandas的一项重要功能,它使你能够在一个轴上拥有多个索引级别
data = Series(randn(10), index=[list('aaabbbccdd'), [1,2,3,1,2,3,1,2,3,3]])
data
Out[231]:
a 1 2.218448
2 1.177886
3 0.544273
b 1 0.974565
2 0.755104
3 -0.027735
c 1 2.104934
2 -0.018527
d 3 0.423208
3 0.577042
dtype: float64
data.index
Out[232]:
MultiIndex(levels=[['a', 'b', 'c', 'd'], [1, 2, 3]],
labels=[[0, 0, 0, 1, 1, 1, 2, 2, 3, 3], [0, 1, 2, 0, 1, 2, 0, 1, 2, 2]])
data['b']
Out[233]:
1 0.974565
2 0.755104
3 -0.027735
dtype: float64
关于重新分级顺序、根据级别汇总统计、使用DataFrame的列、其他有关pandas的话题 在本文中省略
大功告成
疑惑:
1.对DataFrame中某列组成的Series进行索引,如果直接访问单个元素会出错,访问一个切片的元素就没有问题切片
frame3['Ohio'][:-2]
Out[38]:
2000 1.5
Name: Ohio, dtype: float64
单个元素
frame3['Ohio'][2]
得到KeyError: 2
2.使用reindex同时重新索引行和列出错
frame.reindex(index=['a','b','c','d'], method='ffill',
columns=states)
得到ValueError: index must be monotonic increasing or decreasing
心得:
看到函数应用与映射一部分,心里一颤,怎么可能这么好用。虽然还没有非常了解,但已经开始相信pandas将会在以后的数据处理工作中起到重要的作用
还差最后一个单元!
Never mind happiness, do your mission