pandas入门
Pandas含有使数据分析工作变得更快更简单的高级数据结构和操作工具。pandas是基于NumPy构建的,让以Numpy为中心的应用变得更加简单。
Pandas的两个主要数据结构:Series和DataFrame。
Series:
- Series是一种类似于一维数组的对象,它由数据(各种NumPy数据类型)以及与之相关的数据标签(即索引)组成。
In [2]: from pandas import Series, DataFrame
In [3]: obj = Series([4, 7, -5, 3])
In [4]: obj
Out[4]:
0 4
1 7
2 -5
3 3
dtype: int64
- 可以通过Series的values和index属性获取其数组表示形式和索引对象:
- In [5]: obj.values Out[5]: array([ 4, 7, -5, 3]) In [6]: obj.index Out[6]: RangeIndex(start=0, stop=4, step=1)
- 可以通过索引的方式选取Series中的单个或一组值
- NumPy数组运算(如根据布尔型数组进行过滤、标量乘法、应用数学函数等)都会保留索引和值之间的链接:
In [7]: obj[obj>2]
Out[7]:
0 4
1 7
3 3
dtype: int64
In [8]: obj*2
Out[8]:
0 8
1 14
2 -10
3 6
dtype: int64
- 还可以将Series看成是一个定长的有序字典,因为它是索引值到数据值的一个映射:
0 in obj
Out[9]: True
- Python字典中的数据也可以直接创建Series:
In [10]: sdata = {'Ohio':35000, 'Texas':71000, 'Oregon':16000, 'Utah':5000}
In [11]: obj3 = Series(sdata)
In [12]: obj3
Out[12]:
Ohio 35000
Oregon 16000
Texas 71000
Utah 5000
dtype: int64
- Pandas的isnull和notnull函数可用于检测缺失数据:
In [14]: import pandas as pd
In [16]: pd.isnull(obj3)
Out[16]:
Ohio False
Oregon False
Texas False
Utah False
dtype: bool
- Series对象本身及其索引都有一个name属性
In [17]: obj3.name = 'population'
In [18]: obj3.index.name = 'state'
In [19]: obj3
Out[20]:
state
Ohio 35000
Oregon 16000
Texas 71000
Utah 5000
Name: population, dtype: int64
Series最重要的一个功能:它在算术运算中会自动对齐不同索引的数据。
DataFrame
- DataFrame是一个表格型数据,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame即有行索引也有列索引,它可以被看做由Series组成的字典(共用同一个索引)。
from pandas import Series, DataFrame
data = {'state':['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'],
'year':[2000, 2001, 2002, 2001, 2001],
'pop':[1.5, 1.7, 3.6, 2.4, 2.9]}
frame = DataFrame(data);
print (frame)
- 结果DataFrame会自动加上索引,且全部列会被有序排列:
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 2001
- 如果指定了列序列,则DataFrame的列就会按照指定的顺序进行排序:
frame2 = DataFrame(data,columns=['year', 'state', 'pop'])
- 传入的列在数据中找不到,就会产生NA值。
- 通过类似字典标记的方式或属性的方式,可以将DataFrame的列获取为一个Series:
print (frame2['state'])
print (frame2.year)
输出:
0 Ohio
1 Ohio
2 Ohio
3 Nevada
4 Nevada
Name: state, dtype: object
0 2000
1 2001
2 2002
3 2001
4 2001
Name: year, dtype: int64
- 行也可以通过位置或名称的方式进行获取,比如用索引字段 ix
- 跟Series一样,如果传入的列在数据中找不到,就会产生NA值:
frame3 = DataFrame(data,columns=['year', 'state', 'pop', 'debt'])
print (frame3)
输出:
year state pop debt
0 2000 Ohio 1.5 NaN
1 2001 Ohio 1.7 NaN
2 2002 Ohio 3.6 NaN
3 2001 Nevada 2.4 NaN
4 2001 Nevada 2.9 NaN
列可以通过赋值的方式修改:
frame3['debt'] = np.arange(5.0)
print (frame3)
输出:
year state pop debt
0 2000 Ohio 1.5 0.0
1 2001 Ohio 1.7 1.0
2 2002 Ohio 3.6 2.0
3 2001 Nevada 2.4 3.0
4 2001 Nevada 2.9 4.0
- 将列表或数组赋值给某个列时,其长度必须跟DataFrame的长度想匹配。如果赋值的是一个Series,就会精确匹配DataFrame的索引,所有的空位都将被填上缺失值:
val = Series([-1.2, -1.5, -1.7], index=[ 0, 2, 3])
frame3['debt'] = val
print (frame3)
输出:
year state pop debt
0 2000 Ohio 1.5 -1.2
1 2001 Ohio 1.7 NaN
2 2002 Ohio 3.6 -1.5
3 2001 Nevada 2.4 -1.7
4 2001 Nevada 2.9 NaN
注意:通过索引方式返回的列只是相应数据的视图,并不是副本
- 另一种常见的数据形式是嵌套字典(字典的字典):
pop = {'Nevada':{2001:2.4, 2002:2.9},
'Ohio': {2000:2.5, 2001:1.7, 2002:3.6}}
frame4 = DataFrame(pop)
print (frame4)
输出:
Nevada Ohio
2000 NaN 2.5
2001 2.4 1.7
2002 2.9 3.6
转置:
frame4.T
- 由Series组成的字典用法类似
- 如果设置了DataFrame的index和columns的name属性,则这些信息也会被显示出来:
frame4 = DataFrame(pop)
frame4.index.name = 'year'
frame4.columns.name = 'state'
print (frame4)
输出:
state Nevada Ohio
year
2000 NaN 2.5
2001 2.4 1.7
2002 2.9 3.6
- 跟Series一样,values属性也会以二维ndarray的形式返回DataFrame中的数据:
print (frame4.values)
#输出
[[ nan 2.5]
[ 2.4 1.7]
[ 2.9 3.6]]
基本功能
重新索引
- 调用该Series的reindex将会根据数据索引进行重排。如果某个索引值当前不存在,就引入缺失值NaN:
obj = Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a' , 'c'])
obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])
print (obj2)
#输出
a -5.3
b 7.2
c 3.6
d 4.5
e NaN
dtype: float64
- 使用 fill_value 可做插值处理
obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'], fill_value=0)
print (obj2)
#输出
a -5.3
b 7.2
c 3.6
d 4.5
e 0.0
dtype: float64
- method选项
obj3 = Series(['blue', 'purple', 'yellow'], index=[0, 2, 4])
print (obj3.reindex(range(6), method='ffill'))
#输出
0 blue
1 blue
2 purple
3 purple
4 yellow
5 yellow
dtype: object
参数 | 说明 |
ffill或pad | 前向填充值 |
bfill或backfill | 后向填充值 |
- 对于DataFrame,reindex可以修改(行)索引、列,或两个都修改。
frame = DataFrame(np.arange(9).reshape((3, 3)), index=['a', 'c', 'd'], columns=['Ohio', 'Texas', 'California'])
frame2 = frame.reindex(['a', 'b', 'c', 'd'])
states = ['Texas', 'Utah', 'California']
frame3 = frame.reindex(columns=states)
利用ix的标签索引功能,重新索引任务可以变的更简洁:
frame.ix[['a', 'b', 'c', 'd'], states]
丢弃指定轴上的项
- 丢掉某条轴上的一个或多个项,只要有一个索引数组或列表即可,使用 drop 方法
data = DataFrame(np.arange(16).reshape((4,4)), index=['Ohio', 'Colorado', 'Utah', 'New York'], columns=['one', 'two', 'three', 'four'])
print (data.drop(['Colorado', 'Ohio']))
print (data.drop(['two', 'three'], axis=1))
索引、选取和过滤
- Series索引的几个例子:
obj = Series(np.arange(4.), index=['a', 'b', 'c', 'd'])
obj['b']
obj[1]
obj[2:4]
obj['b', 'a', 'd']
obj[[1,3]]
obj[obj<2]
obj['b', 'c']
- DataFrame索引:
data = DataFrame(np.arange(16).reshape((4,4)), index=['Ohio', 'Colorado', 'Utah',
data[['two', 'three']]
#输出
two three
Ohio 1 2
Colorado 5 6
Utah 9 10
New York 13 14
data[:2]
#输出
one two three four
Ohio 0 1 2 3
Colorado 4 5 6 7
data[data['three']>5]
#输出
one two three four
Colorado 4 5 6 7
Utah 8 9 10 11
New York 12 13 14 15
- 专门的索引字段ix
类型 | 说明 |
obj[val] | 选取DataFrame的单个列或一组列 |
obj.ix[val] | 选取DataFrame的单个行或一组行 |
obj.ix[:,val] | 选取单个列或列子集 |
obj.ix[val1,val2] | 同时选取行和列 |
算术运算和数据对齐
- pandas最重要的一个功能是,它可以对不同的索引的对象进行算术运算。在将对象相加时,如果存在不同的索引对,则结果的索引就是该索引对的并集。
- 使用df1的 add 方法,传入df2以及一个fill_value参数:
df1 = DataFrame(np.arange(12.).reshape((3,4)), columns= list('abcd'))
df2 = DataFrame(np.arange(20.).reshape((4,5)), columns= list('abcde'))
print(df1+df2)
print(df1.add(df2,fill_value=0))
#输出
a b c d e
0 0.0 2.0 4.0 6.0 NaN
1 9.0 11.0 13.0 15.0 NaN
2 18.0 20.0 22.0 24.0 NaN
3 NaN NaN NaN NaN NaN
a b c d e
0 0.0 2.0 4.0 6.0 4.0
1 9.0 11.0 13.0 15.0 9.0
2 18.0 20.0 22.0 24.0 14.0
3 15.0 16.0 17.0 18.0 19.0
- 在对Series或DataFrame重新索引时,也可以指定一个填充值:
df1.reindex(columns=df2.columns, fill_value=0)
#输出
a b c d e
0 0.0 1.0 2.0 3.0 0
1 4.0 5.0 6.0 7.0 0
2 8.0 9.0 10.0 11.0 0
- 默认情况下,DataFrame和Series之间的算术运算会将Series的索引匹配到DataFrame的列,然后沿着行一直向下广播。
- 如果某个索引值在DataFrame的列或Series的索引中找不到,则参与运算的两个对象就会被重新索引以形成并集。
函数应用和映射
- NumPy的ufuncs(元素级数组方法)也可以用于操作pandas对象:
#示例 np.abs(frame)
- 另一种常见的操作是,将函数应用到各列或行所形成的一维数组上。使用DataFrame的 apply 方法。
frame = DataFrame(np.random.randn(4,3), columns=list('bde'), index=[1,2,3,4])
print (frame)
f = lambda x:x.max() - x.min()
print (frame.apply(f))
print (frame.apply(f, axis=1))
#输出
b d e
1 0.756197 2.094682 -2.139083
2 0.231391 -0.682302 0.908212
3 0.447181 -0.172543 0.221593
4 -0.500720 0.248337 -0.034403
b 1.256918
d 2.776984
e 3.047295
dtype: float64
1 4.233765
2 1.590513
3 0.619723
4 0.749058
dtype: float64
- 元素级的Python函数也是可以用的:
format = lambda x: '%.2f' %x
print (frame.applymap(format))
之所以叫applymap,是因为Series有一个勇于应用元素级函数的map方法:
print (frame['e'].map(format))
#输出
b d e
1 -0.84 0.10 1.07
2 0.56 -0.49 -1.98
3 -0.60 -1.57 -1.42
4 0.53 -0.85 -0.01
1 1.07
2 -1.98
3 -1.42
4 -0.01
Name: e, dtype: object
排序和排名
- 要对行或列索引进行排序(按字典顺序),可使用 sort_index 方法,它将返回一个已排序的心对象:
obj = Series(range(4), index=['d', 'a', 'b', 'c']) print (obj.sort_index()) #输出 a 1 b 2 c 3 d 0 dtype: int64
默认升序,降序如下:
obj.sort_index(axis=1, ascending=False)
- 按值对Series进行排序,可使用其 order 方法:
- 在DataFrame上,将一个或多个列的名字传递给 by 选项即可根据一个或多个列中的值进行排序:
frame = DataFrame({'b':[4, 7, -3, 2], 'a':[0, 1, 0 , 1]}) print (frame.sort_values(by=['a','b'])) #输出 a b 2 0 -3 0 0 4 3 1 2 1 1 7
带有重复值的轴索引
- 许多pandas函数(如reindex)要求标签唯一,但这并不是强制性的。
obj = Series(range(5),index=['a', 'a', 'b', 'b', 'c'])
索引的 is_unique 属性可以告诉你它的值是否唯一
obj.index.is_unique
- 对于带有重复值的索引,如果某个索引对应多个值,则返回一个Series,而对应单个值的,则返回一个标量值。
- 对DataFrame的行进行索引时也是如此。
汇总和计算描述统计
- pandas对象拥有一组常用的数学和统计方法。它们大部分都属于约简和汇总统计,用于从Series中提取单个值(如sum或mean)或从DataFrame的行或列中提取一个Series。
df = 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']) print (df) print (df.sum()) print (df.sum(axis=1)) #axis 约简的轴。DataFrame的行用0,列用1 #输出 one two a 1.40 NaN b 7.10 -4.5 c NaN NaN d 0.75 -1.3 one 9.25 two -5.80 dtype: float64 a 1.40 b 2.60 c NaN d -0.55 dtype: float64
NA值会自动被排除,除非整个切片(这里指的是行或列)都是NA。通过 skipna 选项可以禁用该功能。
- 有些方法(如 idxmin 和 idxmax )返回的是间接统计(比如达到最小值或最大值的索引)
相关系数和协方差
- Series的 corr 方法用于计算两个Series中重叠的、非NA的、按索引对齐的值的相关系数。与此类似,cov 用于计算协方差。
- DataFrame的 corr 和 cov 方法将以DataFrame的形式返回完整的相关系数或协方差矩阵。
唯一值、值计数以及成员资格
- unique 函数可以得到Series中的唯一值数组:
obj = Series(['c', 'a', 'd', 'a', 'a', 'b', 'b', 'c', 'c']) uniques = obj.unique() print (uniques) #输出 ['c' 'a' 'd' 'b']
返回的唯一值是为排序的,可使用 uniques.sort() 进行排序
- value_counts 用于计算一个Series中各值出现的频率:
print (obj.value_counts()) #输出 c 3 a 3 b 2 d 1 dtype: int64
结果是按值频率降序排列的。
pd.value_counts(obj.values, sort=False)
- isin 用于判断矢量化集合的成员资格,可用于选取Series中或DataFrame列中数据的子集:
mask = obj.isin(['b','c']) print (mask) #输出 0 True 1 False 2 False 3 False 4 False 5 True 6 True 7 True 8 True dtype: bool
处理缺失数据
- pandas使用浮点值 NaN(Not a Number)表示浮点和非浮点数组中的缺失数据,它只是一个用于被检测出来的标记而已:
string_data = Series(['aa', 'bb', np.nan, 'cc']) print (string_data.isnull()) #输出 0 False 1 False 2 True 3 False dtype: bool
Python内置的 None 值也会被当作NA处理。
- NA处理方法
方法 | 说明 |
dropna | 根据各标签的值中是否存在缺失数据对轴标签进行过滤,可通过阀值调节对缺失值的容忍度 |
fillna | 用指定值或插值方法(如ffill或bfill)填充缺失数据 |
isnull | 返回一个含有布尔值的对象,这些布尔值表示哪些值是缺失值/NA,该对象的类型与源类型一样 |
notnull | isnull的否定式 |
滤除缺失数据
- 对于一个Series,dropna 返回一个仅含非空数据和索引值的Series:
data = Series([1, np.nan, 3.5, np.nan, 7]) print (data.dropna()) #输出 0 1.0 2 3.5 4 7.0 dtype: float64
- 对于DataFrame对象,dropna 默认丢弃任何含有缺失值的行
传入 how='all' 将只丢弃全为 NA 的那些行:
data.dropna(how='all')
以这种方式丢弃列:
data.dropna(axis=1, how='all')
填充缺失数据
- 通常一个常数调用 fillna 就会将缺失值替换为那个常数:
df.fillna(0)
- 若通过一个字典调用 fillna ,就可以实现对不同的 列 填充不同的值:
df.fillna({1:0.5, 3:-1})
注:fillna 默认返回新对象,但也可以对现有对象进行修改:
#总是返回被填充对象的引用 _ = df.fillna(o, inplace=True)
- 对 reindex 有效的那些插值方法也可以用于fillna:
#df.fillna(method='ffill') df.fillna(method='ffill', limit=2) #(对于前向和后向填充)可以连续填充的最大数量 #输出 0 1 2 0 -2.512334 0.566809 -0.310823 1 1.480002 0.089615 -0.876138 2 1.446703 0.089615 -0.705835 3 -0.241433 0.089615 0.897966 4 0.028517 NaN 0.897966 5 -0.045509 NaN 0.897966
层次化索引
- 层次化索引能使你能在一个轴上拥有多个(两个以上)索引级别:
data = Series(np.random.randn(10), index=[['a','a','a','b','b','b','c','c','d','d'],[1,2,3,1,2,3,1,2,1,2]]) print (data) print (data.index) #输出 a 1 -0.041274 2 1.288469 3 -0.731776 b 1 1.411813 2 -1.108839 3 -0.689199 c 1 -0.185918 2 0.803436 d 1 0.094525 2 0.692778 dtype: float64 MultiIndex(levels=[[u'a', u'b', u'c', u'd'], [1, 2, 3]], labels=[[0, 0, 0, 1, 1, 1, 2, 2, 3, 3], [0, 1, 2, 0, 1, 2, 0, 1, 0, 1]])
- 对于一个层次化索引的对象选取数据子集操作:
data['b'] data['b':'c'] data.ix[['b', 'd']]
在内层中选取:
data[:, 2] #输出 a 0.780424 b 0.034343 c -1.635875 d -1.068981 dtype: float64
重排分级顺序
- 重新调整某条轴上各级别的顺序,swaplevel 接收两个级别编号或名称,并返回互换了级别的新对象(但数据不会发生变化):
frame = DataFrame(np.arange(12).reshape(4,3), index=[['a','a','b','b'], [1,2,1,2]], columns=[['Ohio', 'Ohio', 'Colorado'], ['Green', 'Red', 'Green']]) frame.index.names = ['key1', 'key2'] frame.columns.names = ['state', 'color'] #输出 state Ohio Colorado color Green Red Green key1 key2 a 1 0 1 2 2 3 4 5 b 1 6 7 8 2 9 10 11 frame.swaplevel('key1', 'key2')
- sortlevel根据单个级别中的值对数据进行排序(稳定):
frame.sort_index(level=1) #输出 state 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
- 交换级别:
frame.swaplevel(0,1).sort_index(level=0) #输出 state Ohio Colorado color Green Red Green key2 key1 1 a 0 1 2 b 6 7 8 2 a 3 4 5 b 9 10 11
根据级别汇总统计
- 许多对DataFrame和Series的描述和汇总统计都有一个level选项,它用于指定在某条轴上求和的级别。
#示例 frame.sum(level='key2') #输出 state Ohio Colorado color Green Red Green key2 1 6 8 10 2 12 14 16
frame.sum(level='color', axis=1) #输出 color Green Red key1 key2 a 1 2 1 2 8 4 b 1 14 7 2 20 10
使用DataFrame的列
- 人们经常想要将DataFrame的一个或多个列当作索引来用,或者可能希望将行索引变成DataFrame的列:
frame = DataFrame({'a':range(7), 'b':range(7,0,-1), 'c':['one','one','one','two','two','two','two'], 'd':[0,1,2,0,1,2,3]}) print frame #输出 a b c d 0 0 7 one 0 1 1 6 one 1 2 2 5 one 2 3 3 4 two 0 4 4 3 two 1 5 5 2 two 2 6 6 1 two 3
- DataFrame的 set_index 函数会将其一个或多个列转换为行索引,并创建一个新的DataFrame:
frame2 = frame.set_index(['c','d']) #输出 a b c d one 0 0 7 1 1 6 2 2 5 two 0 3 4 1 4 3 2 5 2 3 6 1
- reset_index 的功能跟 set_index 刚好相反,层次化索引的级别会被转移到列里面:
frame2.reset_index()