1、Series
(1)简介
Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。仅由一组数据即可产生最简单的Series:
obj = pd.Series([4,7,-5,3])
obj
Out[16]:
0 4
1 7
2 -5
3 3
dtype: int64
(2)Series的字符串表现形式为:索引在左,值在右边。
由于我们没有为数据指定索引,于是会自动创建一个0到N-1(N为数据的长度)的整数型索引。你可以通过Series的values和index属性获取其数组表示形式和索引对象:
obj.values
Out[17]: array([ 4, 7, -5, 3], dtype=int64)
obj.index
Out[19]: RangeIndex(start=0, stop=4, step=1)
(3)通常,我们希望所创建的Series带有一个可以对各个数据点进行标记的索引:
obj2 = pd.Series([4,7,-5,3],index=['d','F','W','f'])
obj2
Out[4]:
d 4
F 7
W -5
f 3
dtype: int64
obj2.index
Out[5]: Index(['d', 'F', 'W', 'f'], dtype='object')
与普通NumPy数组相比,你可以通过索引的方式选取Series中的单个或一组值:
obj2['d']
Out[7]: 4
obj2['d'] = 6
obj2[['d','F','W']]
Out[9]:
d 6
F 7
W -5
dtype: int64
(4)NumPy数组运算(如根据布尔型数组进行过滤、标量乘法、应用数学函数等)都会保留索引和值之间的链接:
obj2
Out[10]:
d 6
F 7
W -5
f 3
dtype: int64
obj2[obj2 > 0]
Out[11]:
d 6
F 7
f 3
dtype: int64
obj2 * 2
Out[12]:
d 12
F 14
W -10
f 6
dtype: int64
np.exp(obj2)
Out[15]:
d 403.428793
F 1096.633158
W 0.006738
f 20.085537
dtype: float64
(5)可以将Series看成是一个定长的有序字典,因为它是索引值到数据值的一个映射。它可以用在许多原本需要字典参数的函数中:
'b' in obj2
Out[16]: False
'd' in obj2
Out[17]: True
如果数据被存放在一个Python字典中,也可以直接通过这个字典来创建Series:
data = {'a':23,'T':45,'S':34}
obj3 = pd.Series(data)
obj3
Out[22]:
a 23
T 45
S 34
dtype: int64
如果只传入一个字典,则结果Series中的索引就是原字典的键(有序排列)。
import pandas as pd
sdata = {'sa':23,'sfq':45,'dsa':75}
obj3 = pd.Series(sdata)
print(obj3)
sa 23
sfq 45
dsa 75
dtype: int64
states = ['sa','hh','dsa','sfq']
obj4 = pd.Series(sdata,index = states)
obj4
Out[4]:
sa 23.0
hh NaN
dsa 75.0
sfq 45.0
dtype: float64
在这个例子中,sdata中跟states索引相匹配的那3个值会被找出来并放到相应的位置上,但由于“hh”所对应的sdata值找不到,所以其结果就为NaN(即‘not a number’,在pandas中,它用于表示缺失或NA值。在这里会使用missing或NA表示缺失数据)。pandas的isnull和notnull函数可用于检测缺失数据:
pd.isnull(obj4)
Out[5]:
sa False
hh True
dsa False
sfq False
dtype: bool
pd.notnull(obj4)
Out[6]:
sa True
hh False
dsa True
sfq True
dtype: bool
Series也有类似的实例方法:
obj4.isnull()
Out[7]:
sa False
hh True
dsa False
sfq False
dtype: bool
(6)对于应用而言,Series最重要的一个功能是:它在算术运算中会自动对齐不同索引的数据。
obj3
Out[8]:
sa 23
sfq 45
dsa 75
dtype: int64
obj4
Out[9]:
sa 23.0
hh NaN
dsa 75.0
sfq 45.0
dtype: float64
obj3+obj4
Out[10]:
dsa 150.0
hh NaN
sa 46.0
sfq 90.0
dtype: float64
(7)Series对象本身及其索引都有一个name属性,该属性跟pandas其他的关键功能关系非常密切:
obj4.name='population'
obj4.index.name = 'state'
obj4
Out[13]:
state
sa 23.0
hh NaN
dsa 75.0
sfq 45.0
Name: population, dtype: float64
Series的索引可以通过赋值的方式就地修改:
obj4.index = ['Bob','Ss','sw','ww'] #对的
obj4.index = ['Bob','Ss','sw','ww','fwq'] #错的,个数与原Series不符
2、DataFrame
(1)DataFrame简介
DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引,它可以被看作由Series组成的字典(共用同一个索引)。跟其他类似的数据结构相比(如R的data.frame),DataFrame中面向行和面向列的操作基本上是平衡的。其实,DataFrame中的数据是以一个或多个二维块存放的(而不是列表、字典或别的一维数据结构)。
(2)构建DataFrame
构建DataFrame的方法有很多,最常用的一种是直接传入一个由等长列表或NumPy数组组成的字典:
from pandas import Series,DataFrame
data = {'state':['a','b','c','d','e'],
'year':[200,341,3432,23,43],
'pop':[1.5,2.4,2.3,4.4,5.5]}
frame = DataFrame(data)
结果DataFrame会自动加上索引(跟Series一样),且全部列会被有序排列:
frame
Out[4]:
state year pop
0 a 200 1.5
1 b 341 2.4
2 c 3432 2.3
3 d 23 4.4
4 e 43 5.5
如果指定了列序列,则DataFrame的列就会按照指定顺序进行排列:
DataFrame(data,columns=['year','state','pop'])
Out[5]:
year state pop
0 200 a 1.5
1 341 b 2.4
2 3432 c 2.3
3 23 d 4.4
4 43 e 5.5
(3)跟Series一样,如果传入的列在数据中找不到,就会产生NA值:
frame2 = DataFrame(data,columns=['year','state','pop','debt'],index=['one','two','three','four','five'])
frame2
Out[7]:
year state pop debt
one 200 a 1.5 NaN
two 341 b 2.4 NaN
three 3432 c 2.3 NaN
four 23 d 4.4 NaN
five 43 e 5.5 NaN
frame2.columns
Out[8]: Index(['year', 'state', 'pop', 'debt'], dtype='object')
(4)通过类似字典标记的方式或属性的方式,可以将DataFrame的列获取为一个Series:
frame2.year
Out[9]:
one 200
two 341
three 3432
four 23
five 43
Name: year, dtype: int64
frame2['state']
Out[10]:
one a
two b
three c
four d
five e
Name: state, dtype: object
注意,返回的Series拥有原DataFrame相同的索引,且其name属性也已经被相应地设置好了。
行也可以通过位置或名称的方式进行获取,比如用索引字段ix,没有iy这个东东!
frame2.ix['three']
Out[11]:
year 3432
state c
pop 2.3
debt NaN
Name: three, dtype: object
(5)列可以通过赋值的方式进行修改,例如,我们可以给那个空的“debt”列赋上一个标量值或一组值:
frame2['debt']=2
frame2
Out[13]:
year state pop debt
one 200 a 1.5 2
two 341 b 2.4 2
three 3432 c 2.3 2
four 23 d 4.4 2
five 43 e 5.5 2
import numpy as np
frame2['debt'] = np.arange(5.)
frame2
Out[16]:
year state pop debt
one 200 a 1.5 0.0
two 341 b 2.4 1.0
three 3432 c 2.3 2.0
four 23 d 4.4 3.0
five 43 e 5.5 4.0
将列表或数组赋值给某个列时,其长度必须跟DataFrame的长度相匹配。如果赋值的是一个Series,就会精确匹配DataFrame的长度相匹配。如果赋值的是一个Series,就会精确匹配DataFrame的索引,所有的空位都将被填上缺失值:
val = Series([-1.2,-1.5,2.3],index=['two','t','five']) #如果设置的index中,存在和原DataFrame不相同的索引,会忽略
frame2['debt'] = val
frame2
Out[17]:
year state pop debt
one 200 a 1.5 NaN
two 341 b 2.4 -1.2
three 3432 c 2.3 NaN
four 23 d 4.4 NaN
five 43 e 5.5 2.3
为不存在的列赋值会创建出一个新列。关键字del用于删除列:
frame2['eastern'] = frame2.state=='Oh'
frame2
Out[19]:
year state pop debt eastern
one 200 a 1.5 NaN False
two 341 b 2.4 -1.2 False
three 3432 c 2.3 NaN False
four 23 d 4.4 NaN False
five 43 e 5.5 2.3 False
del frame2['eastern']
frame2.columns
Out[20]: Index(['year', 'state', 'pop', 'debt'], dtype='object')
通过索引方式返回的列只是相应数据的视图而已,并不是副本。因此对返回的Series所做的任何就地修改全都会反映到源DataFrame上。通过Series的copy方法即可显式地复制列。
(6)嵌套字典(字典中的字典)
pop = {'aa':{100:3,324:21},'bb':{200:1.5,201:1.7,203:4.5}}
如果将它传给DataFrame,则 外层字典的键作为列,内层键则作为行索引:
frame = DataFrame(pop)
frame
Out[21]:
aa bb
100 3.0 NaN
200 NaN 1.5
201 NaN 1.7
203 NaN 4.5
324 21.0 NaN
当然,可以对该结果进行转置:
frame.T
Out[22]:
100 200 201 203 324
aa 3.0 NaN NaN NaN 21.0
bb NaN 1.5 1.7 4.5 NaN
DataFrame(pop,index=[100,200,201,203,204])
Out[23]:
aa bb
100 3.0 NaN
200 NaN 1.5
201 NaN 1.7
203 NaN 4.5
204 NaN NaN
DataFrame(pop,columns=['aa','bb'])
Out[25]:
aa bb
100 3.0 NaN
200 NaN 1.5
201 NaN 1.7
203 NaN 4.5
324 21.0 NaN
由Series组成的字典差不多也是一样的用法:
pdata = {'aa':frame['aa'][:-1],
'cc':frame['bb'][:2]}
DataFrame(pdata)
Out[27]:
aa cc
100 3.0 NaN
200 NaN 1.5
201 NaN NaN
203 NaN NaN
二维ndarray | 数据矩阵,还可以传入行标和列标 |
由数组、列表或元组组成的字典 | 每个序列会变成DataFrame的一列。所有序列的长度必须相同 |
NumPy的结构化/记录数组 | 类似于“由数组组成的字典” |
由Series组成的字典 | 每个Series会成为一列。如果没有显示指定索引,则各Series的索引会被合并成结果的行索引 |
由字典组成的字典 | 各内层字典会成为一列。键会被合并成结果的行索引,跟“由Series组成的字典”的情况一样 |
字典或Series的列表 | 各项将会成为DataFrame的一行。字典键或Series索引的并集将会成为DataFrame的列标 |
由列表或元组组成的列表 | 类似于“二维ndarray” |
另一个DataFrame | 该DataFrame的索引将会被沿用,除非显式指定了其他索引 |
NumPy的MaskedArray | 类似于“二维ndarray”的情况,只是掩码值在结果DataFrame会变成NA/缺失值 |
如果设置了DataFrame的index和columns的names属性,则这些信息也会被显示出来:
frame.index.name = 'year'
frame.columns.name = 'state'
frame
Out[4]:
state aa bb
year
100 3.0 NaN
200 NaN 1.5
201 NaN 1.7
203 NaN 4.5
324 21.0 NaN
跟Series一样,values属性也会以二维ndarray的形式返回DataFrame中的数据:
frame.values
Out[5]:
array([[ 3. , nan],
[ nan, 1.5],
[ nan, 1.7],
[ nan, 4.5],
[21. , nan]])
如果DataFrame各列的数据类型不同,则值数组的数据类型就会选用能兼容所有列的数据类型。
3、索引对象
pandas的索引对象负责管理轴标签和其他元数据(比如轴名称等)。构建Series或DataFrame时,所用到的任何数组或其他序列的标签都会被转换成一个Index:
obj = Series(range(3),index=['a','b','c'])
index = obj.index
index
Out[17]: Index(['a', 'b', 'c'], dtype='object')
index[1:]
Out[26]: Index(['b', 'c'], dtype='object')
Index对象是不可修改的(immutable),因此用户不能对其进行修改。这样才能使Index对象在多个数据结构之间安全共享:
index0 = pd.Index(np.arange(3))
obj2 = Series([2,3,4],index=index0)
obj2.index is index0
Out[25]: True
Index甚至可以被继承从而实现特别的轴索引功能