5 pandas入门
约定:1
2from pandas import Series, DataFrame
import pandas as pd
5.1 pandas的数据机构介绍
pandas两个主要数据结构Series
和DataFrame
Series
Series有两个属性values
和index
,表示数据(各种NumPy数据类型)及与之相关的标签(索引),因此可以从一个Python字典中直接创建Series1
2
3sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}
obj3 = Series(sdata)
obj3
Output:1
2
3
4
5Ohio 35000
Oregon 16000
Texas 71000
Utah 5000
dtype: int64
可以指定index,注意只有index中的数据保留:1
2
3states = ['California', 'Ohio', 'Oregon', 'Texas']
obj4 = Series(sdata, index=states)
obj4
Output:1
2
3
4
5California
Ohio 35000
Oregon 16000
Texas 71000
dtype:
Series最重要的一个功能是:在算术运算中自动对齐不同索引的数据。1
obj3 + obj4
Output:1
2
3
4
5
6California
Ohio 70000
Oregon 32000
Texas 142000
Utah
dtype:
Series对象本省及其索引都有一个name
属性,这跟pandas其他关键功能关系密切。1
2
3obj4.name = 'population'
obj4.index.name = 'state'
obj4
Output:1
2
3
4
5
6state
California NaN
Ohio 35000
Oregon 16000
Texas 71000
Name: population, dtype: float64
DataFrame
DataFrame是一个表格型数据结构,它含有一组有序的列,每列可以是不同的类型。DataFrame既有行索引也有列索引,可以看作是由Series组成的字典。
构建DataFrame最直接的方式是传入一个由等长列表或NumPy数组组成的字典:1
2
3
4
5data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'],
'year': [2000, 2001, 2002, 2001, 2002],
'pop': [1.5, 1.7, 3.6, 2.4, 2.9]}
frame = DataFrame(data)
frame
Output:1
2
3
4
5
6 pop state year
0 1.5 Ohio 2000
1 1.7 Ohio 2001
2 3.6 Ohio 2002
3 2.4 Nevada 2001
4 2.9 Nevada 2002
创建时可以指定列序列,DataFrame会按照指定顺序排列列。1
frame2 = DataFrame(data, columns=['year', 'state', 'pop'], index=['one', 'two', 'three', 'four', 'five'])
如果传入的列在数据中找不到,就会产生NaN
值。
通过字典标记的方式或属性的方式,可以已Series的方式获取DataFrame的列。1
2frame2['state']
frame2.year
通过ix
可以获取行。1
frame2.ix['three']
Output:1
2
3
4year 2002
state Ohio
pop 3.6
Name: three, dtype: object
用索引方式返回的都是源数据的视图,并非副本,因此所有的修改都会全部反映到源DataFrame中。
索引对象
5.2 基本功能
重新索引
pandas对象一个重要方法是reindex
,创建一个适应新索引的新对象。
丢弃指定轴上的项drop
防范可以删除任意轴上的索引项。
索引、选取和过滤Series
索引用标签切片的运算与普通Python切片不同,是末端包含的。
对DataFrame
进行索引就是获取一个或多个列,但是通过切片或布尔数组方式选取的是行,这是逻辑用法是来源于
算术运算和数据对齐
pandas对象相加时,如果存在不同的索引树,结果的索引就是该索引对的并集。
在算术方法中填充值时,如果希望对缺失值赋予一个特殊值,可以使用fill_value
参数,该参数在重新索引时也可以使用。1
2
3
4df1 = DataFrame(np.arange(12.).reshape((3,4)), columns=list('abcd'))
df2 = DataFrame(np.arange(20.).reshape((4,5)), columns=list('abcde'))
df1 + df2
df1.add(df2, fill_value=0)
Output:1
2
3
4
5
6
7
8
9
10
11 a b c d e
0 0 2 4 6 NaN
1 9 11 13 15 NaN
2 18 20 22 24 NaN
3 NaN NaN NaN NaN NaN
a b c d e
0 0 2 4 6 4
1 9 11 13 15 9
2 18 20 22 24 14
3 15 16 17 18 19
DataFrame和Series之间的运算
和NumPy中不同维度数组之间的广播机制类似,DataFrame和Series之间的算术运算会将Series的索引匹配到DataFrame的列,然后沿着行的防线一直向下广播。1
2
3frame = DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'), index=['Utah','Ohio','Texas','Oregon'])
series = frame.ix[0]
frame - series
Output:1
2
3
4
5 b d e
Utah 0 0 0
Ohio 3 3 3
Texas 6 6 6
Oregon 9 9 9
如果希望匹配行在列上广播,必须使用算术运算方法。1
2series3 = frame['d']
frame.sub(series3, axis=0)
Output:1
2
3
4
5 b d e
Utah -1 0 1
Ohio -1 0 1
Texas -1 0 1
Oregon -1 0 1
函数应用和映射
NumPy的ufuncs(元素级数组方法)也可用于操作pandas对象。另外一个常见的用法是将函数应用到各类或各行所在的一维数组上,DataFrame的.apply()
方法可以实现此功能。1
2
3
4
5frame = DataFrame(np.random.randn(4,3), columns=list('bde'), index=['Utah','Ohio','Texas','Oregon'])
f = lambda x: x.max() - x.min()
frame
frame.apply(f)
frame.apply(f, axis=1)
Output:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 b d e
Utah 0.062492 -1.727616 -0.079996
Ohio 1.313402 0.658781 -0.992717
Texas -1.954599 2.428276 1.372190
Oregon -0.821649 0.896800 2.221896
b 2.389651
d 3.365110
e 2.934581
dtype: float64
Utah 0.263963
Ohio 1.964547
Texas 1.133140
Oregon 1.777723
dtype: float64
除此之外,传递给apply
的函数还可以是返回多个值的Series。1
2
3
4def f(x):
return Series([x.min(), x.max()], index=['min','max'])
frame.apply(f)
Output:1
2
3 b d e
min -0.274731 -2.239277 -2.157811
max 0.408729 0.724984 0.180029
元素级的函数也可以使用.applymap
方法实现。
排序和排名
使用.sort_index
方法对行或列索引排序,将返回一个已排序的新对象。
如果希望对一个或多个列中的值进行排序,将列名传递给by
选项即可。1
2frame = DataFrame({'b':[4,7-3,2], 'a':[0,1,0,1]})
frame.sort_index(by=['a','b'])
Output:1
2
3
4
5 a b
2 0 -3
0 0 4
3 1 2
1 1 7
带有重复值的轴索引
可以使用index
的.is_unique
属性来看轴索引是否有重复值。在数据选取时,如果索引对应多个值,则会返回Series,否则返回一个标量值。
5.3 汇总和计算描述统计
pandas的常用数学统计方法,都是基于没有缺失数据的假设而构建的。1
2
3
4
5df = DataFrame([[1.4, np.nan], [7.1, -4.5],
[np.nan, np.nan], [0.75, -1.3]],
index=['a', 'b', 'c', 'd'],
columns=['one', 'two'])
df
Output:1
2
3
4
5 one two
a 1.40 NaN
b 7.10 -4.5
c NaN NaN
d 0.75 -1.3
相关系数与协方差
唯一值、值计数以及成员资格
这类方法可以从一维Series
的值中抽取信息,例如unique
返回唯一值数组,value_counts
计算各值出现的频率,isin
用于判断矢量化集合的成员资格1
2
3
4obj = Series(['c', 'a', 'd', 'a', 'a', 'b', 'b', 'c', 'c'])
mask = obj.isin(['b', 'c'])
mask
obj[mask]
Output:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
170 True
1 False
2 False
3 False
4 False
5 True
6 True
7 True
8 True
dtype: bool
0 c
5 b
6 b
7 c
8 c
dtype: object
1 | data = DataFrame({'Qu1': [1, 3, 4, 3, 4], |
Output:1
2
3
4
5
6 Qu1 Qu2 Qu3
1 1.0 1.0 1.0
2 0.0 2.0 1.0
3 2.0 2.0 0.0
4 2.0 0.0 2.0
5 0.0 0.0 1.0
5.4 处理缺失数据
pandas使用浮点值NaN
(Not a Number)表示浮点和非浮点数组中的缺失数字,Python内置的None
也会被当作NA
处理
滤除缺失数据.dropna
方法或者使用[data.notnull()]
布尔型索引都可以直接过滤掉缺失数据。对于DataFrame
对象,dtopna()
默认丢弃任何含有缺失的行。
填充缺失数据fillna
方法是最主要的填充缺失数据的函数。通过传入一个字典,可以实现对不同列填充不同的值。传入inplace=True
参数可以就地修改而不是默认返回新对象。1
2
3df.fillna({1: 0.5, 3: -1})
# always returns a reference to the filled object
_ = df.fillna(0, inplace=True)
5.5 层次化索引
对于一个DataFrame,每条轴都可以有分层索引1
2frame = DataFrame(np.arange(12).reshape((4,3)), index=[['a','a','b','b'], [1,2,1,2]], columns=[['Ohio','Ohio','Colorado'],['Green','Red','Green']])
frame
Output1
2
3
4
5
6 Ohio Colorado
Green Red Green
a 1 0 1 2
2 3 4 5
b 1 6 7 8
2 9 10 11
各层都可以有名字,并且可以单独创建MultiIndex然后复用。1
2
3frame.index.names = ['key1','key2']
frame.columns.names = ['state', 'color']
MultiIndex.from_array([['Ohio','Ohio','Colorado'],['Green','Red','Green'], names=['statue','color'])
重排分级顺序
如果需要调整某条轴上各级别的顺序时可以使用swaplevel
方法,它接受两个级别编号或名称,斌返回互换级别的新对象(但数据不会变化)1
frame.swaplevel('key1', 'key2')
Output:1
2
3
4
5
6
7state Ohio Colorado
color Green Red Green
key2 key1
1 a 0 1 2
2 a 3 4 5
1 b 6 7 8
2 b 9 10 11
sortlevel
方法则根据单个级别中的值对数据进行排序(稳定的)。注意这里的参数是索引的编号,索引编号是从外向内方向计数的。1
frame.sortlevel(1)
Output:1
2
3
4
5
6
7state Ohio Colorado
color Green Red Green
key1 key2
a 1 0 1 2
b 1 6 7 8
a 2 3 4 5
b 2 9 10 11
对层次化索引的分级重排是为了提升数据选取操作的效率,按照索引的顺序选取性能要好很多。
根据级别汇总统计
DataFrame和Series的描绘和汇总统计有一个level
选项,用于指定在某条轴上求和的级别,这其实是利用了pandas的groupby
功能1
frame.sum(level='color', axis=1)
Output:1
2
3
4
5
6color Green Red
key1 key2
a 1 2 1
2 8 4
b 1 14 7
2 20 10
使用DataFrame的列
通常情况下,我们会将DataFrame的一个或多个列当作行索引,或者可以希望将行索引变成DataFrame的列。set_index
会将一个或多个列专为行索引,并创建一个新的DataFrame。1
2
3frame = DataFrame({'a': range(7), 'b': range(7, 0, -1), 'c': ['one','one','one','two','two','two','tow'], 'd': [0,1,2,0,1,2,3]})
frame2 = frame.set_index(['c','d'])
frame2
Output:1
2
3
4
5
6
7
8
9 a b
c d
one 0 0 7
1 1 6
2 2 5
two 0 3 4
1 4 3
2 5 2
tow 3 6 1
默认情况下这些列会从DataFrame中移除,但通过添加dtop
参数可以将其保留。1
frame2 = frame.set_index(['c','d'], drop=False)
Output:1
2
3
4
5
6
7
8
9 a b c d
c d
one 0 0 7 one 0
1 1 6 one 1
2 2 5 one 2
two 0 3 4 two 0
1 4 3 two 1
2 5 2 two 2
tow 3 6 1 tow 3
reset_index
和set_index
功能相反,将层次化的索引转移到列里面。
5.6 其他有关pandas的话题
整数索引
操作由整数索引的pandas对象要注意,因为跟内置Python数据结构在索引语义上的不同,经常会产生一个错误。1
2ser = Series(np.arange(3.))
ser[-1]
上述代码会产生一个错误,但是如果设置了非整数索引,就不会产生问题。1
2ser = Series(np.arange(3.), index['a','b','c'])
ser[-1]
Output:1
2.0
如果你不考虑索引,而是完全基于位置的索引方法,可以使用Series的iget_value
和DataFrame的irow
和icol
方法。
面板数据
pandas有一个Panel
数据结果,可以视作是一个三维版的DataFrame,Panel中的每一项(类似于DataFrame的列)都是一个DataFrame。