数据分析用到的
1. apply 直接传函数
def add_prop(group):
births=group.births.astype(float)
group['prop']=births/births.sum()
return group
names=names.groupby(['year','sex']).apply(add_prop)
2.用np.allcolse()来检查分组总计值是否接近1
print np.allclose(names.groupby(['year','sex']).prop.sum(),1)
返回:true
3.取该数据集的子集:每对sex/year组合的前1000名
def get_top1000(group):
return group.sort_index(by='births',ascending=False)[:1000]
grouped=names.groupby(['year','sex'])
top1000=grouped.apply(get_top1000)
print top1000
4.生成一张year,name统计表,查看下面4个名字取名的趋势,画张列表
.取该数据集的子集:每对sex/year组合的前1000名
total_births=top1000.pivot_table('births',index='year',columns='name',aggfunc=sum)
# print total_births
subset=total_births[['John','Harry','Mary','Marilyn']]
subset.plot(subplots=True,figsize=(12,10),grid=False,title="Number of births per year")
pl.show()
验证父母给小孩起常见的名字越来越少:办法是计算最流行的1000个名字所占的比例
table=top1000.pivot_table('prop',index='year',columns='sex',aggfunc=sum)
table.plot(title='sum of table1000.prop by year and sex',yticks=np.linspace(0,1.2,13),xticks=range(1880,2020,10))
pl.show()
5.unique与drop_duplicates区别
#dataframe中去重函数,drop_duplicates是返回一个移除了重复行的DataFrame
data=pd.DataFrame({'K':[1,1,2,2,3,4,2]})
print data
IsDuplicated=data.duplicated()
print IsDuplicated
print type(IsDuplicated)
data=data.drop_duplicates()
print data
#ISDuplicated和drop_duplicates是判断全部列,也可以指定部分列进行重复项判断
# data.drop_duplicates(['k2']) #对名字为k2的列进行去重
取不重复的值
all_names=top1000.name.unique() #取不重名的名字
6. index 与reindex的区别
用index修改的索引不存在会报错,而reindex则会用None填充
obj=pd.Series(range(4),index=['d','b','a','c')
#返回结果如下
d 0
b 1
a 2
c 3
obj=pd.Series(range(4),index=['d','b','a','c','e']) #会报错,因为‘e’超出了范围,不存在此索引
print obj
#但用reindex则会用None填充
#reindex更多的不是修改pandas对象的索引,而只是修改索引的顺序,如果修改的索引不存在就会使用默认的None代替此行。
# 且不会修改原数组,要修改需要使用赋值语句。
print obj.reindex(['a', 'b', 'c', 'd', 'e'])
#返回结果如下:
a 2.0
b 1.0
c 3.0
d 0.0
e NaN
7.索引对象:Index
pandas的索引对象负责管理轴标签和其它元数据(比如轴名称等),构建Series或DataFrame时,
所用到的任何数组或其它序列的标签都会被转换成一个Index:
obj=Series(range(3),index=['a','b','c'])
index=obj.index
print obj
#输出结果如下:
# a 0
# b 1
# c 2
print index #输出结果:Index([u'a', u'b', u'c'], dtype='object')
print index[1:] #输出结果:Index([u'b', u'c'], dtype='object')
(1)Index对象是不可修改的(immutable),因此用户不能对其进行修改
# index[1]='d'
# print index #报错: Index does not support mutable operations
#注意:不可修改性非常重要,因为这样才能使Index对象在多个数据结构之间安全共享:
index=pd.Index(np.arange(3))
obj2=Series([1.5,-2.5,0],index=index)
print obj2
#输出结果如下:
# 0 1.5
# 1 -2.5
# 2 0.0
# dtype: float64
print obj2.index is index #输出结果:True
print "1" in obj2.index #"1"是obj2的行索引吗?#输出结果是False
# print "1" in obj2.columns #报错,Series没有列索引,不象datafram表格类型
print '0' in obj2.index
pandas中主要的Index对象
Index 最泛化的Index对象,将轴标签表示为一个由python对象组成的Numpy数组
Int64Index 针对整数的特殊Index
MultiIndex “层次化”索引对象,表示单个轴上的多层索引。可以看做由元组组成的数组
DatetimeIndex 存储纳秒组时间戳
PeriodIndex 针对Period数据(时间间隔)的特殊Index
7.重新索引:reindex
pandas对象的一个重要方法是reindex,其作用是创建一个适应新索引的新对象
obj1=Series([4.5,7.2,-5.3,3.6],index=['d','b','a','c'])
print obj1
#输出结果如下:
# d 4.5
# b 7.2
# a -5.3
# c 3.6
# dtype: float64
#调用该Series的reindex将会根据新索引进行重排。如果某个索引值当前不存在,就引入缺失值
obj2=obj1.reindex(['a','b','c','d','e'])
print obj2
#输出结果如下:
# a -5.3
# b 7.2
# c 3.6
# d 4.5
# e NaN
# dtype: float64
obj2=obj1.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选项即可达到此目的,例如,使用ffill可以实现前向值填充
obj3=Series(['blue','purple','yellow'],index=[0,2,4])
obj3.reindex(range(6),method='ffill')
print obj3
#输出的结果:
# 0 blue
# 1 blue
# 2 purple
# 3 purple
# 4 yellow
# 5 yellow
列出了可用的method选项。其实我们有时需要比前向和后向填充更为精准的插值方式
reindex的插值method选项
参数 说明
ffill或pad 前向填充值
bfill或backfill 后向填充值
对于DataFrame,reindex可以修改(行)索引、列,或两个都修改。如果仅传入一个序列,则会重新索引行
frame=DataFrame(np.arange(9).reshape((3,3)),index=['a','c','d'],
columns=['Ohio','Texas','California'])
print frame
#输出结果如下:
# Ohio Texas California
# a 0 1 2
# c 3 4 5
# d 6 7 8
frame2=frame.reindex(['a','b','c','d'])
print frame2
#输出结果如下:
# 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
#使用columns关键字即可重新索引列:
states=['Texas','Utah','California']
frame2=frame.reindex(columns=states)
print frame2
#输出结果如下:
# Texas Utah California
# a 1 NaN 2
# c 4 NaN 5
# d 7 NaN 8
利用ix的标签索引功能,重新索引任务可以变得更简洁
print frame2.ix[['a','b','c','d'],states]
reindex函数的参数
index 用作索引的新序列,即可以是Index实例,也可以是其它序列型的python数据结构
method 插值(填充)方式
fill_value 在重新索引的过程中,需要引入缺失值时使用的替代值
limit 前向或后向填充时的最大填充量
level 在MultiIndex的指定级别上匹配简单索引,否则选取其子集
copy 默认为True,无认如何都复制;如果为False,则新旧相等就不复制
8.丢弃指定轴上的项:drop
丢弃某条轴上的一个或多个项很简单,只要有一个索引数组或列表即列。
drop方法返回的是一个在指定轴上删除了指定值的新对象。
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
obj=Series(np.arange(5.),index=['a','b','c','d','e'])
new_obj=obj.drop('c')
print new_obj
#输出结果如下:
# a 0.0
# b 1.0
# d 3.0
# e 4.0
# dtype: float64
new_obj=obj.drop(['d','c'])
print new_obj
#输出结果如下 :
# a 0.0
# b 1.0
# e 4.0
# dtype: float64
对于DataFrame,可以删除任意轴上的索引值:
data=DataFrame(np.arange(16).reshape((4,4)),
index=['Ohio','Colorado','Utah','New York'],
columns=['one','two','three','four'])
print data
#输出结果如下:
# one two three four
# Ohio 0 1 2 3
# Colorado 4 5 6 7
# Utah 8 9 10 11
# New York 12 13 14 15
new_data=data.drop(['Colorado','Ohio'])
print new_data
#输出结果如下:
# one two three four
# Utah 8 9 10 11
# New York 12 13 14 15
new_data=data.drop('two',axis=1)
print new_data
#输出结果如下:
# one three four
# Ohio 0 2 3
# Colorado 4 6 7
# Utah 8 10 11
# New York 12 14 15
# new_data=data.drop('two',axis=0) #axis=0是指行,axis=1指一整列
# print new_data #报错:labels ['two'] not contained in axis,two没有包启在axis=0的行索引中,它是列的索引,故只能用axis=1
new_data=data.drop(['two','four'],axis=1) #axis=1列中索引为'two','four'
print new_data
#输出结果如下:
# one three
# Ohio 0 2
# Colorado 4 6
# Utah 8 10
# New York 12 14
9.索引、选取和过滤
Series的选取、过滤介绍:
Series索引(obj[...])的工作方式类似于Numpy数组的索引,只不过Series的索引值不只是整数.
(1)它可以像数组一样以下标形式取出,也可以用行索引,ix是用于DataFrame中的行索引。
obj['b'],obj[1]
(2)可以切片取值,下标的切片与python一样,右边是不包含的:obj[2:4]
(3)取出多个行:用索引值取或者用下标取,但都用[[]](即双括号)
obj[['b','a','d']]
obj[[1,3]]
(4)可用条件,布尔型
obj[obj<2]
(5)但用标签(即行索引)的切片运算,它与python不一样,是包含右边的
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
# Series索引、选取和过滤
obj=Series(np.arange(4),index=['a','b','c','d'])
print obj
#输出结果如下:
# a 0
# b 1
# c 2
# d 3
# dtype: int64
print obj['b'] #与下面的下标取值是一样的obj[1],下标是从0开始算的
#输出结果: 1
print obj[1]
#输出结果: 1
print obj[2:4] #取出从下标为2-4的但不包含右边的值4,即取出下标为2,3的值
#输出结果如下:
# c 2
# d 3
print obj[['b','a','d']] #取多行,按行索引取出多行
#输出结果如下:
# b 1
# a 0
# d 3
# dtype: int64
print obj[[1,3]] #取多行,取出下标为1,3行的,下标从0开始
#输出结果如下:
# b 1
# d 3
# dtype: int64
print obj[obj<2] #obj<2的值为True,即0,1,再取出obj[True]为true的值
#输出结果如下:
# a 0
# b 1
# dtype: int64
print obj['b':'c'] #标签(即行索引,Series没有列索引)切片,包含右边值
# b 1
# c 2
# dtype: int64
#切片的值设置很简单,直接赋值即可
obj['b':'c']=5
print obj
#输出结果如下:
# a 0
# b 5
# c 5
# d 3
# dtype: int64
DataFrame的选取、过滤介绍:
DataFrame进行索引其实就比Series多获取一个或多个列
行可以用切片,列不可以用切片
(1) 获取单列(和Series一样):用列索引获取
data['two']
DataFrame就不能像Series用单个下标了,因为它是表格形式(有行,列下标,单个它没法分清),而Series是数组.
data[2,3] data[2]都会报错
(2) 获取多列:用[[]]
data[['three','one']]
(3) 切片选取行(与Series一样,下标方式获取):
data[:2]
(4) 布尔型数组选取行,与ndarray一样
data[data['three']>5] data[data<5]=0 data.ix[data.three>5,:3]
(5) 标签进行行索引,引入了字段ix.px 它可以通过Numpy式的标记法以及轴标签从DataFrame中选取行和列的子集。
即先取出行,再取列的子集
data.ix['Colorado',['two','three']]
(6) 用标签ix索引取多行多列:先取多行用ix,再取多列子集(列可用下标,下标从0开始算)
data.ix[['Colorado','Utah'],[3,0,1]]
data.ix[['Colorado','Utah'],['two','three']]
(7) 取整行:ix[下标],ix['行索引']
data.ix[2] data.ix[:'Utah','two']
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
data=DataFrame(np.arange(16).reshape((4,4)),
index=['Ohio','Colorado','Utah','New York'],
columns=['one','two','three','four'])
print data
#输出结果如下:
# one two three four
# Ohio 0 1 2 3
# Colorado 4 5 6 7
# Utah 8 9 10 11
# New York 12 13 14 15
print "++++++++++++++++++++++++++"
print data['two'] #取出列索引为'two'的值
#输出结果如下:
# Ohio 1
# Colorado 5
# Utah 9
# New York 13
# Name: two, dtype: int64
print "+++++++++++++++++++++++++"
print data[['three','one']]
#输出结果如下:
# three one
# Ohio 2 0
# Colorado 6 4
# Utah 10 8
# New York 14 12
print data[:2] #下标从0开始,右边不包含。故取出的是下标为0,1的行
#输出结果如下:
# one two three four
# Ohio 0 1 2 3
# Colorado 4 5 6 7
print data[data['three']>5] #data['three']>5返回布尔值,若是>5的则返回True,再data['True']取出为true的值
#输出结果如下:
# one two three four
# Colorado 4 5 6 7
# Utah 8 9 10 11
# New York 12 13 14 15
data[data<5]=0 #将data<5的值赋0
print data
#输出结果如下:
# one two three four
# Ohio 0 0 0 0
# Colorado 0 5 6 7
# Utah 8 9 10 11
# New York 12 13 14 15
利用ix取行索引,还可取出行索引和列的子集
print data.ix['Colorado',['two','three']] #ix标签行索引为'colorado'的,再取子集的列索引为['two','three']的值
#输出结果如下:
# two 5
# three 6
# Name: Colorado, dtype: int64
print data.ix[['Colorado','Utah'],[3,0,1]] #多行多列,用ix先取多行,再用下标取多列子集
#输出结果如下:
# four one two
# Colorado 7 0 5
# Utah 11 8 9
print data.ix[['Colorado','Utah'],['two','three']]
#输出结果如下:
# two three
# Colorado 5 6
# Utah 9 10
print data.ix[2] #取出的是# Utah 8 9 10 11这行的数据,下标从0开始算
#输出结果如下:
# one 8
# two 9
# three 10
# four 11
# Name: Utah, dtype: int64
print data.ix[:'Utah','two'] #行用切片(标签切片包含最右边的),列子集只有一个用列索引
#输出结果如下:
# Ohio 0
# Colorado 5
# Utah 9
# Name: two, dtype: int64
print data.ix[data.three>5,:3] #data.three列的值>5的行为True,再取出列为:3,
# 故取出的是前3列(下标切片3不包含,切片右边数据不包含)
#输出结果如下:
# one two three
# Colorado 0 5 6
# Utah 8 9 10
# New York 12 13 14
DataFrame的索引选项
类型 说明
obj[val] 选取DataFrame的单个列或一组列。在一些特殊情况下会比较便利:布尔型数组(过滤片)、
切片(行切片)、布尔型DataFrame(根据条件设置值)
obj.ix[val] 选取DataFrame的单个行或一组行
obj.ix[:,val] 选取单个列或列子集
obj.ix[val1,val2] 同时选取行和列
reindex方法 将一个或多个轴匹配到新索引
xs方法 根据标签选取单行或单列,并返回一个Series
icol,irow方法 根据整数位置选取单列或单行,并返回一个Series
get_value、set_value方法 根据行标签和列标签选取单个值
10.算术运算和数据对齐
pandas最重要的功能是,它可以对不同索引的对象进行算术运算。
在将对象相加时,如果存在不同的索引对,则结果的索引就是该索引对的交集。
例如下面的s1+s2,就是s1,s2的索引对的并集,即索引在s1,s2中都有的,则s1+s2;若没有索引非重叠,则用Nan
(1)Series的算术运算和数据对齐:
s1=Series([7.3,-2.5,3.4,1.5],index=['a','c','d','e'])
s2=Series([-2.1,3.6,-1.5,4,3.1],index=['a','c','e','f','g'])
print s1
print s2
#输出结果如下:
# a 7.3
# c -2.5
# d 3.4
# e 1.5
# dtype: float64
#
# a -2.1
# c 3.6
# e -1.5
# f 4.0
# g 3.1
# dtype: float64
print s1+s2 #s1,s2的索引对的并集,即索引在s1,s2中都有的,则s1+s2
#输出的结果如下:
# a 5.2
# c 1.1
# d NaN
# e 0.0
# f NaN
# g NaN
# dtype: float64
(2)对于DataFrame,对齐操作同时发生在行和列上:
df1=DataFrame(np.arange(9).reshape((3,3)),columns=list('bcd'),
index=['Ohio','Texas','Colorado'])
df2=DataFrame(np.arange(12).reshape((4,3)),columns=list('bde'),
index=['Utah','Ohio','Texas','Oregon'])
print df1
print df2
#输出结果如下:
# b c d
# Ohio 0 1 2
# Texas 3 4 5
# Colorado 6 7 8
#
# b d e
# Utah 0 1 2
# Ohio 3 4 5
# Texas 6 7 8
# Oregon 9 10 11
#把它们相加后将会返回一个新的DataFrame,其索引和列为原来那两个DataFrame的并集
print df1+df2
#输出结果如下:
# b c d e
# Colorado NaN NaN NaN NaN #Colorado在df2中无此行索引,故全为NaN
# Ohio 3.0 NaN 6.0 NaN #ohio索引df1,df2中都有,列共同有的只有b,d,故其它列都是NaN
# Oregon NaN NaN NaN NaN
# Texas 9.0 NaN 12.0 NaN
# Utah NaN NaN NaN NaN
11.在算术方法中填充值
在算术中若像上面存在NaN的值(缺省值),可以用特定值来填充。在对不同索引的对象进行算术运算时,你可能希望当一个对象
中某个轴标签在另一个对象中找不到时填充一个特殊值(比如0):
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
df1=DataFrame(np.arange(12).reshape((3,4)),columns=list('abcd'))
df2=DataFrame(np.arange(20).reshape((4,5)),columns=list('abcde'))
print df1
print df2
#输出结果如下:
# a b c d
# 0 0 1 2 3
# 1 4 5 6 7
# 2 8 9 10 11
#
# a b c d e
# 0 0 1 2 3 4
# 1 5 6 7 8 9
# 2 10 11 12 13 14
# 3 15 16 17 18 19
print df1+df2 #将它样相加,没有重叠的位置就会产生Na值
#输出结果如下:
# 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
(1)方法1:使用df1的add方法(将+改成方法add,可传入填充的参数值),传入df2以及一个fill_value参数:
print df1.add(df2,fill_value=0)
#输出结果如下:
# 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
(2)方法2:与上面类似,在对Series或DataFrame重新索引时,也可以指定一个填充值:
print df1.reindex(columns=df2.columns,fill_value=0) #df1重新修改列索引,列索引的值=df2.columns,若与df2.columns不相同则填充0
#输出结果如下:
# a b c d e
# 0 0 1 2 3 0
# 1 4 5 6 7 0
# 2 8 9 10 11 0
#注意:add和reindex方法的不同之处:
# df1.add(df2,fill_value=0) add方法是以df2为主的,行和列若只在df2中有,在df1中没有。则留原来df2的原值
# df1.reindex(columns=df2.columns,fill_value=0) reindex方法是修改df1中的例,其列索引=df2.columns,故列df1的e列没有,
# 修改后的列名中有e列,但它的值是0.(即列的并集)。但是行没有在参数中,故行是以df1为主,df1只有0,1,2三行。
注意:add和reindex方法的不同之处:
df1.add(df2,fill_value=0) add方法是df1,df2都有,但不重叠,则会保留df1,df2的原值,若两者都没有值,则返回NaN.
df1.reindex(columns=df2.columns,fill_value=0) reindex方法是修改df1中的例,其df1列索引=df2.columns,故列df1的e列没有,
修改后的列名中有e列,但它的值是0.(即列的并集)。但是行没有在参数中,故行是以df1为主,df1只有0,1,2三行。
再举一个df1,df2都有不同列的例子如下:
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
df1=DataFrame(np.arange(12).reshape((3,4)),columns=list('abfd'))
df2=DataFrame(np.arange(20).reshape((4,5)),columns=list('abcde'))
print df1
print df2
#输出结果如下:
# a b f d
# 0 0 1 2 3
# 1 4 5 6 7
# 2 8 9 10 11
# a b c d e
# 0 0 1 2 3 4
# 1 5 6 7 8 9
# 2 10 11 12 13 14
# 3 15 16 17 18 19
print df1+df2 #将它样相加,没有重叠的位置就会产生Na值
#输出结果如下:
# a b c d e f
# 0 0.0 2.0 NaN 6.0 NaN NaN
# 1 9.0 11.0 NaN 15.0 NaN NaN
# 2 18.0 20.0 NaN 24.0 NaN NaN
# 3 NaN NaN NaN NaN NaN NaN
print df1.add(df2,fill_value=0)
#输出结果如下:
# a b c d e f
# 0 0.0 2.0 2.0 6.0 4.0 2.0
# 1 9.0 11.0 7.0 15.0 9.0 6.0
# 2 18.0 20.0 12.0 24.0 14.0 10.0
# 3 15.0 16.0 17.0 18.0 19.0 NaN
print df1.reindex(columns=df2.columns,fill_value=0) #df1重新修改列索引,列索引的值=df2.columns,若与df2.columns不相同则填充0
#输出结果如下:
# a b c d e
# 0 0 1 0 3 0
# 1 4 5 0 7 0
# 2 8 9 0 11 0
灵活的算术方法:
方法 说明
add 用于加法(+)的方法
sub 用于减法(-)的方法
div 用于除法(/)的方法
mul 用于乘法(*)的方法
12.DataFrame和Series之间的运算
跟Numpy数组一样,DataFrame和Series之间算术运算也是有明确规定的。
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
#下面是array数组的相减,计算一个二维数组与某行之间的差
arr=np.arange(12.).reshape((3,4))
print arr
#输出结果如下:
# [[ 0. 1. 2. 3.]
# [ 4. 5. 6. 7.]
# [ 8. 9. 10. 11.]]
print arr[0]
#输出结果:[ 0. 1. 2. 3.]
print arr-arr[0]
#输出结果如下:
# [[ 0. 0. 0. 0.]
# [ 4. 4. 4. 4.]
# [ 8. 8. 8. 8.]]
这就叫广播
DataFrame和Series之间的运算差不多也是如此:
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
frame=DataFrame(np.arange(12.).reshape((4,3)),columns=list('bde'),
index=['Utah','Ohio','Texas','Oregon'])
print frame
#输出结果如下:
# 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
series=frame.ix[0] #ix是取dataframe的行下标为0的一行数据,即第一行数据
print series
#输出结果如下:
# b 0.0
# d 1.0
# e 2.0
# Name: Utah, dtype: float64
print frame-series
#输出结果如下:
# 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
如果某个索引值在DataFrame的列或Series的索引中找不到,则参与运算的两个对象就会被重新索引以形成并集
series2=Series(range(3),index=['b','e','f'])
print series2
#输出结果如下:
# b 0
# e 1
# f 2
# dtype: int64
print frame+series2 #列只有b,e有,d,f没有,则并集计算
#输出的结果如下:
# b d e f
# Utah 0.0 NaN 3.0 NaN
# Ohio 3.0 NaN 6.0 NaN
# Texas 6.0 NaN 9.0 NaN
# Oregon 9.0 NaN 12.0 NaN
若你希望匹配行且在列上广播,则必须使用算术运算方法。
series3=frame['d'] #series3取的是frame['d']上的一列数据,因为series是数组只有行索引。它不是DataFrame表格形式
print frame
print series3
#输出结果如下:
# Utah 1.0
# Ohio 4.0
# Texas 7.0
# Oregon 10.0
# Name: d, dtype: float64
print frame.sub(series3,axis=0)
#输出的结果如下:frame['d']列-series3得到该列的结果是0
# 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
13.函数应用和映射
Numpy的ufuncs(元素级数组方法)也可用于操作Pandas对象,
若要每次生成的随机数一样则用seed,np.random.randn(4,3),np.seed(0),see()里的参数一致随机生成的就一致。
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
下面举例中用的是randn,没有用seed,故每次运行的随机frame的值都不一样。下面的输出结果是不一样的。
frame=DataFrame(np.random.randn(4,3),columns=list('bde'),
index=['Utah','Ohio','Texas','Oregon'])
print frame
#输出结果如下:
# b d e
# Utah 0.717460 -0.686366 0.678220
# Ohio 0.821139 -0.266131 0.780161
# Texas -0.956684 -1.301178 1.863898
# Oregon -1.106230 1.590944 -0.366192
print np.abs(frame)
#输出结果如下:
# b d e
# Utah 0.717460 0.686366 0.678220
# Ohio 0.821139 0.266131 0.780161
# Texas 0.956684 1.301178 1.863898
# Oregon 1.106230 1.590944 0.366192
另一种常见的操作是,将函数应用到由各列或行所形成的一维数组上。DataFrame的apply方法即可实现
f=lambda x:x.max()-x.min()
print frame.apply(f) #没有参数,默认axis=0即列,每一列的值用最大值-最小值,得到b,d,e列的值
# b 2.613551
# d 1.960512
# e 2.738963
# dtype: float64
print frame.apply(f,axis=1) #axis=1是每一行上最大值-最小值得到到下面的行
#输出结果如下:因为随机数每次产生的结果都不一样。故算的结果也不一样。
# Utah 0.415836
# Ohio 2.827663
# Texas 0.339280
# Oregon 2.702060
# dtype: float64
#许多最为常见的数组统计功能都实现成DataFrame的方法(如sum和mean),因此无需使用apply方法
除标量值外(即单行值),传递给apply的函数还可以返回由多个值组成的Series:
def f(x):
return Series([x.min(),x.max()],index=['min','max'])
print frame.apply(f)
#输出结果如下:
# b d e
# min -2.036368 -1.635511 -0.817457
# max 0.641699 0.997854 0.303625
此外,元素级的Python函数也是可以用的。假如你想得到frame中各个浮点值的格式化字符吕,使用applymap即可
format=lambda x:'%.2f'%x
print frame.applymap(format)
#输出结果如下:
# b d e
# Utah 2.01 -2.30 0.27
# Ohio -0.61 0.77 0.74
# Texas 0.74 1.50 -0.51
# Oregon 1.78 -0.01 0.33
#之所以叫做applymap,是因为Series有一个用于应用元素级函数的map方法
print frame['e'].map(format) #单独取出DataFrame的一列就是Series了,然后用Series方法即可
#输出结果如下
# Utah -1.65
# Ohio 0.80
# Texas 1.12
# Oregon -0.14
# Name: e, dtype: object
14.排序和排名
a.按索引排序
根据条件对数据集排序sorting;要对行或列索引进行排序(按字典排序),可使用sort_index方法,
它将返回一个已排序的新对象。
注意:Series用range,DataFrame用arange
(1) Series排序
obj=Series(range(4),index=['d','a','b','c'])
print obj
#输出结果:
# d 0
# a 1
# b 2
# c 3
print obj.sort_index() #sort_index,Series按行索引排序,Series只有行
#输出的结果如下:
# a 1
# b 2
# c 3
# d 0
# dtype: int64
(2)对于DataFrame,则可以根据任意一个軕上的索引进行排序
frame=DataFrame(np.arange(8).reshape((2,4)),
index=['three','one'],
columns=['d','a','b','c'])
print frame
#输出结果如下:
# d a b c
# three 0 1 2 3
# one 4 5 6 7
print frame.sort_index() #没有axis参数,表示默认axis=0,即行索引排序
#输出结果如下:
# d a b c
# one 4 5 6 7
# three 0 1 2 3
print frame.sort_index(axis=1) #axis=1,表示列索引排序:a,b,c,d
#输出结果如下:
# a b c d
# three 1 2 3 0
# one 5 6 7 4
数据默认是按升序排列的,但也可以降序排序,参数ascending=False。即列为d,c,b,a
print frame.sort_index(axis=1,ascending=False)
#输出结果如下:
# d c b a
# three 0 3 2 1
# one 4 7 6 5
b.按值进行排序
(1)对Series进行排序
若要按值对Series进行排序,可使用其order方法:
obj=Series([4,7,-3,2])
print obj.sort_values() #老版本用sort_value()
# print obj.order() #pandas新版本用order()
#输出结果如下:对值排序
# 2 -3
# 3 2
# 0 4
# 1 7
# dtype: int64
在排序时,任何缺失值默认都会被放到Series的末尾:
obj=Series([4,np.nan,7,np.nan,-3,2])
# print obj.order()
print obj.sort_values()
#输出结果如下:
# 4 -3.0
# 5 2.0
# 0 4.0
# 2 7.0
# 1 NaN
# 3 NaN
# dtype: float64
(2)在DataFrame上,可以根据一个或多个列中的值进行排序。将一个或多个列的名字传递给by选项即可达到目的。
frame=DataFrame({'b':[4,7,-3,2],'a':[0,1,0,1]})
print frame
#输出结果如下:
# a b
# 0 0 4
# 1 1 7
# 2 0 -3
# 3 1 2
# print frame.sort_index(by='b')
#输出结果如下:
# a b
# 2 0 -3
# 3 1 2
# 0 0 4
# 1 1 7
要根据多个列进行排序,传入名称的列表即可:
print frame.sort_index(by=['a','b'])
#输出结果如下:
# a b
# 2 0 -3
# 0 0 4
# 3 1 2
# 1 1 7
ranking排名跟排序关系密切,且它会增设一个排名值(从1开始,一直到数组中有效数据的数量)。
它跟numpy.argsort产生的间接排序索引差不多,只不过它可以根据某种规则破坏平级关系。
默认情况下,rank是通过"为各组分配一个平均排名"的方式破坏平级关系的。
obj=Series([7,-5,7,4,2,0,4])
print obj.rank()
#输出结果如下:
# 0 6.5
# 1 1.0
# 2 6.5
# 3 4.5
# 4 3.0
# 5 2.0
# 6 4.5
# dtype: float64
#也可以根据值在原数据中出现的顺序给出排名
print obj.rank(method='first')
#输出结果如下:
# 0 6.0
# 1 1.0
# 2 7.0
# 3 4.0
# 4 3.0
# 5 2.0
# 6 5.0
# dtype: float64
#当然,你也可以按降序进行排名:
print obj.rank(ascending=False,method='max')
#输出结果如下:
# 0 2.0
# 1 7.0
# 2 2.0
# 3 4.0
# 4 5.0
# 5 6.0
# 6 4.0
# dtype: float64
#DataFrame可以在行或列上计算排名:
frame=DataFrame({'b':[4.3,7,-3,2],'a':[0,1,0,1],
'c':[-2,5,8,-2.5]})
print frame
#输出结果如下:
# a b c
# 0 0 4.3 -2.0
# 1 1 7.0 5.0
# 2 0 -3.0 8.0
# 3 1 2.0 -2.5
print frame.rank(axis=1)
#输出结果如下:
# a b c
# 0 2.0 3.0 1.0
# 1 1.0 3.0 2.0
# 2 2.0 1.0 3.0
# 3 2.0 3.0 1.0
排名时(rank)用于破坏平级关系的method选项
method 说明
‘average’ 默认:在相等分组中,为各个值分配平均排名
‘min’ 使用整个分组的最小排名
‘max’ 使用整个分组的最大排名
‘first’ 按值在原始数居中的出现顺序分配排名
15.带有重得值的轴索引
许多pandas函数(如reindex)都要求标签唯一,但这并不是强制性的。它也可以带有重复索引值的Series.
obj=Series(range(5),index=['a','a','b','b','c'])
print obj
#输出结果如下:
# a 0
# a 1
# b 2
# b 3
# c 4
# dtype: int64
索引的is_unique属性可以告诉你它的值是否是唯一的:
print obj.index.is_unique #输出结果是:False
对于带有重复值的索引,数据选取的行为将会有些不同。如果某个索引对应多个值,则返回一个Series;
而对应单个值的,则返回一个标量值(即一行)
print obj['a']
#返回结果如下:
# a 0
# a 1
# dtype: int64
print obj['c'] #返回:4
DataFrame的行进行索引也是如此:
df=DataFrame(np.random.randn(4,3),index=['a','a','b','b'])
print df
#输出结果如下:
# 0 1 2
# a -0.008028 -0.066083 -1.412515
# a 1.291454 0.301502 -1.470759
# b -1.046987 -1.236650 0.367174
# b -0.913669 0.035940 0.327931
print df.ix['b'] #ix取行索引
#输出结果如下:
# 0 1 2
# b -1.046987 -1.23665 0.367174
# b -0.913669 0.03594 0.327931
16.汇总和计算描述统计
pandas对象拥有一组常用的数学和统计方法。它们在部分都属于约简和汇总统计,
用于对Series中提取单个值(如sum或mean)或从DataFrame的行或列中提取一个Series.
跟对应的Numpy数组方法相比,它们都是基于没有缺失数据的假设来构建的。
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
#输出结果如下:
# one two
# a 1.40 NaN
# b 7.10 -4.5
# c NaN NaN
# d 0.75 -1.3
调用DataFrame的sum方法将会返回一个含有小计的Series:每一列求和
print df.sum()
#输出结果如下:
# one 9.25
# two -5.80
若传入axis=1将会按进行求和运算:
#输出结果如下:
# a 1.40
# b 2.60
# c NaN
# d -0.55
Na值会自动被排除,除非整个切片(这里指的是行或列,即一整行或一整列)都是NA.通过skipna选项可以禁用该功能。
print df.mean(axis=1,skipna=False)
#输出结果如下:
# a NaN
# b 1.300
# c NaN
# d -0.275
sum,mean等约简方法的选项:
选项 说明
axis 约简的轴。DataFrame的行axis=0,列用1(axis=1)
skipna 排除缺失值,默认值为True
level 如果轴是层次化索引的(即MultiIndex),则根据level分组约简
(1)有些方法(如idxmin,idmax)返回的是间接统计(比如达到最小值和最大值的索引)
print df.idxmax()
#输出结果如下:
# one b
# two d
#另一些方法则是累计型的:
print df.cumsum()
#输出结果如下:
# one two
# a 1.40 NaN
# b 8.50 -4.5
# c NaN NaN
# d 9.25 -5.8
(2)还有一种方法,它即不是约简型也不是累计型。如dexcribe用于一次性产生多个汇总统计
print df.describe()
#输出结果如下:
# 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
(3)对于非数值型数据,describe会产生另外一种汇总统计
obj=Series(['a','a','b','c']*4)
print obj.describe()
#输出结果如下:
# count 16
# unique 3
# top a
# freq 8
描述和汇总统计:
方法 说明
count 非NA值的数量
describe 针对Series或各DataFrame列计算汇总统计
min,max 计算最小值和最大值
argmin,argmax 计算能够获取到最小值和最大值的索引位置(整数)
idxmin,idxmax 计算能够获取到最小值和最大值的索引值
quantile 计算样本的分位数(0到1)
sum 值的总和
mean 值的平均数
median 值的算术中位数(50%分位数)
mad 根据平均值计算平均绝对离差
var 样本值的方差
std 样本值的标准差
skew 样本值的偏度(三阶矩)
kurt 样本值的峰度(四阶矩)
cumsum 样本值的累计和
cummin、cummax 样本值的累计最大值和累计最小值
cumprod 样本值的累计积
diff 计算一阶差分(对时间序列很有用)
pct_change 计算百分数变化
相关系数和协方差:
#有些汇总统计(如相关系数和协方差)是通过参数对计算出来的。
import pandas.io.data as web
all_data={}
for ticker in ['AAPL','IBM','MSFT','GOOG']:
all_data[ticker]=web.get_data_yahoo(ticker,'1/1/2000','1/1/2018')
price=DataFrame({tic:data['Adj Close']
for tic,data in all_data.iteritems()})
volume=DataFrame({tic:data['Volume']
for tic,data in all_data.iteritems()})
print volume
returns=price.pct_change
print returns.tail()
#Series的corr方法用于计算两个Series中重叠的、非NA的、按索引对齐的值的相关系数,cov用于计算协方差
print returns.MSFT.corr(returns.IBM)
print returns.MSFT.cov(returns.IBM)
print returns.corr() #DataFrame的corr和cov方法将DataFrame的形式返回完整的相关系数和协方差矩阵
#利用DataFrame的corrwith方法,可以计算其列或行跟另一个Series或DataFrame之间的相关系数。
#传入一个Series将会返回一个相关系数值Series(针对各列进行计算)。
print returns.corrwith(returns.IBM)
#传入一个DataFrame则会计算按列名配对的相关系数。这里,我计算百分比变化与成交量的相关系数
print returns.corrwith(volume) #传入axis=1即可按行进行计算
#在计算相关系数之前,所有的数据项都会按标签对齐。
唯一值、值计数以及成员资格:
还有一类方法可以从一维Series值中抽取信息。
#(1) unique() 去重复值
obj=Series(['c','a','d','a','a','b','b','c','c'])
uniques=obj.unique()
print uniques
#输出结果如下:
# ['c' 'a' 'd' 'b']
#还可以对返回的值进行排序用:sort()
print uniques.sort()
#(2)value_counts用于计算一个Series中各值出现的频率,它是按值降序排序的
print obj.value_counts()
#输出结果如下:
# c 3
# a 3
# b 2
# d 1
#value_counts还是一个顶级pandas方法,可用于任何数组或序列
print pd.value_counts(obj.values,sort=False) #sort=False升序排序
#输出结果如下:
# a 3
# c 3
# b 2
# d 1
#(3)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
print obj[mask] #mask是布尔值,故是True的值取出
#输出结果如下:
# 0 c
# 5 b
# 6 b
# 7 c
# 8 c
唯一值、值计数以及成员资格方法
方法 说明
isin 计算一个表示“Series各值是否包含于传入的值序列中”的布尔型数组
unique 计算Series中的唯一值数组,按发现的顺序返回
value_counts 返回一个Series,其索引为唯一值,其值为频率,按计数值降序排序
#若希望得到DataFrame中多个相关列的一张柱状图
data=DataFrame({'Qu1':[1,3,4,3,4],
'Qu2':[2,3,1,2,3],
'Qu3':[1,5,2,4,4]})
print data
#输出结果如下:
# Qu1 Qu2 Qu3
# 0 1 2 1
# 1 3 3 5
# 2 4 1 2
# 3 3 2 4
# 4 4 3 4
#将pandas.value_counts传给DataFrame的apply函数
result=data.apply(pd.value_counts)
print result
#输出结果如下:
# Qu1 Qu2 Qu3
# 1 1.0 1.0 1.0
# 2 NaN 2.0 1.0
# 3 2.0 2.0 NaN
# 4 2.0 NaN 2.0
# 5 NaN NaN 1.0
result=data.apply(pd.value_counts).fillna(0)
print result
#输出结果如下:
# 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
17.缺失数据处理
import numpy as np
from pandas import Series,DataFrame
import pandas as pd
#(1)pandas使用浮点值NaN表示浮点和非浮点数组中的缺失数据
string_data=Series(['aardvark','artichoke',np.nan,'avocado'])
print string_data
#输出结果如下:
# 0 aardvark
# 1 artichoke
# 2 NaN
# 3 avocado
# dtype: object
print string_data.isnull()
#输出的结果如下:
# 0 False
# 1 False
# 2 True
# 3 False
# dtype: bool
#(2)python内置的None值也会被当做NA处理
string_data[0]=None
print string_data.isnull()
#输出结果如下:
# 0 True
# 1 False
# 2 True
# 3 False
# dtype: bool
NA处理方法:
方法 说明
dropna 根据各标签的值中是否存在缺失数据对轴标签进行过滤,可通过阈值调节对缺失值的容忍度
fillna 用指定值或插值方法(如ffill或bfill)填充缺失数据
isnull 返回一个含有布尔值的对象,这些布尔值表示哪些值是缺失值NA,该对象的类型与源类型一样
notnull isnull的否定式
过滤掉缺失数据的办法有很多种。纯手工操作方法永远是一个办法,但dropna可能会更实用一些。
Series过滤掉缺失数据的方法如下:
(1)dropna
#对于一个Series,dropna返回一个仅含非空数据和索引值的Series.
from numpy import nan as NA
data=Series([1,NA,3.5,NA,7])
print data.dropna()
#输出结果如下:
# 0 1.0
# 2 3.5
# 4 7.0
# dtype: float64
(2)通过布尔型索引达到目的:notnull
print data[data.notnull()] #data.notnull返回布尔型,True为不为空的值。data[True]取出data中为True的值
#输出的结果如下:
# 0 1.0
# 2 3.5
# 4 7.0
# dtype: float64
DataFrame过滤掉缺数据方法如下:
DataFrame你可能希望丢弃全NA或者含有NA的行或列
(1) dropna默认丢弃任何含有缺失值的行,如果只想丢弃全为NA的那些行,则传入参数how='all'
data=DataFrame([[1.,6.5,3.],[1.,NA,NA],
[NA,NA,NA],[NA,6.5,3.]])
cleaned=data.dropna()
print data
#输出结果哪下:
# 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
print cleaned
#输出结果如下:
# 0 1 2
# 0 1.0 6.5 3.0
print data.dropna(how='all')
#输出的结果如下:
# 0 1 2
# 0 1.0 6.5 3.0
# 1 1.0 NaN NaN
# 3 NaN 6.5 3.0
(2)要用dropna这种方式丢弃列,只需传入axis=1即可:
data[4]=NA
print data
#输出结果如下:
# 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
print data.dropna(axis=1,how='all') #axis=1表示列,how='all'这一列全是NaN的
#输出结果如下:
# 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
(3)另一个滤除DataFrame行的问题涉及时间序列数据。假设你只想留下一部分观测数据,可以用thresh参数实现
df=DataFrame(np.random.randn(7,3))
df.ix[:4,1]=NA #:4从下标到4行,1表示下标为1的列即第2列
print df
#输出结果如下:
# 0 1 2
# 0 -1.059619 NaN 1.958930
# 1 -0.551849 NaN -0.072130
# 2 -0.372930 NaN 0.835485
# 3 -0.537468 NaN 0.610045
# 4 0.381160 NaN -1.121259
# 5 -0.993335 0.078202 -0.108020
# 6 0.032738 -1.469338 0.125924
print df.dropna(thresh=3) #留下没有Nan的数据
#thresh指的是列,只能是3,这个例子若是thresh=2无结果,
# thresh=4报Empty DatatFrme,Columns: [0, 1, 2]
#输出结果如下:
# 0 1 2
# 5 -0.993335 0.078202 -0.108020
# 6 0.032738 -1.469338 0.125924
填充缺失数据:
你可能不想滤除缺失数据(有可能丢弃跟它有关的其它数据),而是希望通过其他方式填补那些“空洞”。
对于大多数情况而言,fillna方法是最主要的函数。通过一个常数调用fillna就会将缺失值替换为那个常数值。
(1)fillna的应用
(1)fillna()填充指定值
print df.fillna(0)
#输出结果如下:
# 0 1 2
# 0 0.435719 0.000000 0.403724
# 1 -1.320617 0.000000 0.044588
# 2 0.624846 0.000000 0.171051
# 3 -0.968712 0.000000 1.402204
# 4 1.222497 0.000000 -1.486042
# 5 0.106718 0.579158 0.064224
# 6 -1.301850 0.076622 0.956990
(2)若是通过一个字典调用fillna,就可以实现对不同的列填充不同的值
print df.fillna({1:0.5,3:-1}) #下标为1的列填充0.5,下标为3的列填充为-1
#输出结果如下:
# 0 1 2
# 0 0.435719 0.500000 0.403724
# 1 -1.320617 0.500000 0.044588
# 2 0.624846 0.500000 0.171051
# 3 -0.968712 0.500000 1.402204
# 4 1.222497 0.500000 -1.486042
# 5 0.106718 0.579158 0.064224
# 6 -1.301850 0.076622 0.956990
(3)fillna默认会返回新对象,但也可以对现有对象进行就地修改
#总是返回被填充对象的引用
_=df.fillna(0,inplace=True)
print df
#输出结果如下:
# 0 1 2
# 0 0.435719 0.000000 0.403724
# 1 -1.320617 0.000000 0.044588
# 2 0.624846 0.000000 0.171051
# 3 -0.968712 0.000000 1.402204
# 4 1.222497 0.000000 -1.486042
# 5 0.106718 0.579158 0.064224
# 6 -1.301850 0.076622 0.956990
(4)对reindex有效的那些插值方法也可用于fillna
df=DataFrame(np.random.randn(6,3))
df.ix[2:,1]=NA #下标为2即从第3行开始,1表示下标为1的即第2列都为NaN
df.ix[4:,2]=NA
print df
#输出结果如下:
# 0 1 2
# 0 0.251605 -1.470314 0.724193
# 1 -1.654733 -0.169537 -0.773023
# 2 0.294954 NaN 0.126516
# 3 1.918257 NaN -0.154707
# 4 0.978893 NaN NaN
# 5 0.443479 NaN NaN
print df.fillna(method='ffill') #向前填充,即和前面的值一样
#输出结果如下:
# 0 1 2
# 0 0.251605 -1.470314 0.724193
# 1 -1.654733 -0.169537 -0.773023
# 2 0.294954 -0.169537 0.126516
# 3 1.918257 -0.169537 -0.154707
# 4 0.978893 -0.169537 -0.154707
# 5 0.443479 -0.169537 -0.154707
print df.fillna(method='ffill',limit=2) #只限制2条数据向前填充,其它的还是NaN
#输出结果如下:
# 0 1 2
# 0 0.251605 -1.470314 0.724193
# 1 -1.654733 -0.169537 -0.773023
# 2 0.294954 -0.169537 0.126516
# 3 1.918257 -0.169537 -0.154707
# 4 0.978893 NaN -0.154707
# 5 0.443479 NaN -0.154707
(5)只要稍微动动脑子,就可以利用fillna实现许多别的功能。
#比如说,可以传入Series的平均值或中位数
data=Series([1.,NA,3.5,NA,7])
print data.fillna(data.mean())
#输出结果如下:
# 0 1.000000
# 1 3.833333
# 2 3.500000
# 3 3.833333
# 4 7.000000
# dtype: float64
fillna函数的参数:
参数 说明
value 用于填充缺失值的标量值或字典对象
method 插值方式。如果函数调用时未指定其他参数的话,默认为“ffill”(向前填充)
axis 待填充的轴,默认axis=0(axis=0行,axis=1列)
inplace 修改调用者对象而不产生副本
limit (对于前向和后向填充)可以连续填充的最大数量
18.层次化索引
层次化索引是pandas的一项重要功能,它使你能在一个轴上拥有多个(两个以上)索引级别。
它使你能以低维度形式处理高维度数据。
Series层次化索引:
import numpy as np
from pandas import Series,DataFrame
from numpy import nan as NA
import pandas as pd
df=DataFrame(np.random.randn(7,3))
df.ix[:4,1]=NA
#层次化索引
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,2,3]])
print data
#输出结果如下:
# a 1 0.284752
# 2 -0.480090
# 3 -0.171065
# b 1 -0.672707
# 2 -1.553886
# 3 -2.647718
# c 1 0.913590
# 2 0.279225
# d 2 -0.550275
# 3 0.444103
(1)这就是带有MultiIndex(双索引)索引的Series的格式化输出形式。索引之间的"间隔"表示"直接使用上面的标签"
print data.index
#输出结果如下:
# 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, 1, 2]])
(2)对于一个层次化索引的对象,选取数据子集的操作
print data['b']
#输出结果如下:
# 1 -0.672707
# 2 -1.553886
# 3 -2.647718
print data['b':'c'] #索引切片包含右侧,若下标切片和python一样不包含右侧
#输出结果如下:
# b 1 -0.672707
# 2 -1.553886
# 3 -2.647718
# c 1 0.913590
# 2 0.279225
print data.ix[['b','d']]
#输出结果如下:
# b 1 -0.672707
# 2 -1.553886
# 3 -2.647718
# d 2 -0.550275
# 3 0.444103
(3)还可以在"内层"中进行选取
print data[:,2]
#输出结果如下:
# a -0.480090
# b -1.553886
# c 0.279225
# d -0.550275
DataFrame层次化索引:
层次化索引在数据重塑和基于分组的操作(如透视表生成)中扮演着重要的角色。
比如说,这段数据可以通过其unstack方法被重新安排到一个DataFrame中
(1)unstack与stack
print data.unstack()
#输出结果如下:
# 1 2 3
# a 0.879771 0.928296 -1.305827
# b -1.236556 1.285491 1.213506
# c -1.422645 1.176860 NaN
# d NaN -0.454782 -1.567219
#unstack的逆运算是stack:
print data.unstack().stack()
#对于一个DataFrame,每条轴都可以有分层索引:
frame=DataFrame(np.arange(12).reshape((4,3)),
index=[['a','a','b','b'],[1,2,1,2]],
columns=[['Ohio','Ohio','Colorado'],
['Green','Red','Green']])
print frame
#输出结果如下:
# Ohio Colorado
# Green Red Green
# a 1 0 1 2
# 2 3 4 5
# b 1 6 7 8
# 2 9 10 11
(2)各层都可以有名字(可以是字符串,也可以是别的python对象)。如果指定了名称,它们就会显示在控制台输出中(不要将索引名称
# 跟轴标签混为一谈# )。
frame.index.names=['key1','key2']
frame.columns.names=['state','color']
print frame
#输出结果如下:
# 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
(3)由于有了部分的列索引,因此可以轻松选取列分组
print frame['Ohio']
#输出结果如下:
# color Green Red
# key1 key2
# a 1 0 1
# 2 3 4
# b 1 6 7
# 2 9 10
重排分级顺序:
有时需要重新调整某条轴上各级别的顺序,或根据指定级别上的值对数据进行排序。
swaplevel接受两个级别编号或名称,并返回一个互换了级别的新对象(但数据不会发生变化),
(1)swaplevel 索引互换
print frame.swaplevel('key1','key2')
#输出的结果如下:
# state 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
(2)sortlevel :对索引级别进行排序
sortlevel则根据单个级别中的值对数据进行排序(稳定的)。交换级别时,常常也会用到sortlevel,这样最终结果就是有序的了。
print frame.sortlevel(1) #按第2个索引值排序,即key2
#输出结果如下:
# 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
print frame.swaplevel(0,1).sortlevel(0) #swaplevel(0,1)是把0列和1列互换,然后sortlevel(0)按第1列排序
#输出结果如下:
# 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选项,它用于指定在某条轴上求和的级别。我们以DataFrame
为例可以根据行和列来求和。
frame=DataFrame(np.arange(12).reshape((4,3)),
index=[['a','a','b','b'],[1,2,1,2]],
columns=[['Ohio','Ohio','Colorado'],
['Green','Red','Green']])
print frame
#输出结果如下:
# Ohio Colorado
# Green Red Green
# a 1 0 1 2
# 2 3 4 5
# b 1 6 7 8
# 2 9 10 11
frame.index.names=['key1','key2']
frame.columns.names=['state','color']
print frame
#输出结果如下:
# 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
#许多对DataFrame和Series的描述和汇总统计都有一个level选项,它用于指定在某条轴上求和的级别。
print frame.sum(level='key2') #将key2列的值求和
#输出结果如下:
# state Ohio Colorado
# color Green Red Green
# key2
# 1 6 8 10
# 2 12 14 16
print frame.sum(level='color',axis=1) #按color的行求行,且axis=1是列
#输出结果如下:
# color Green Red
# key1 key2
# a 1 2 1
# 2 8 4
# b 1 14 7
# 2 20 10
#这其实是用了pandas的groupby功能。
使用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
#(1)set_index函数会将其一个或多个列转换为行索引,并创建一个新的DataFrame
frame2=frame.set_index(['c','d'])
print frame2
#输出结果如下:
# 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
#默认情况下,加上drop=False 那些列会从DataFrame中移除,但也可以将其保留下来
print frame.set_index(['c','d'],drop=False)
#输出结果如下:
# 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
# 3 6 1 two 3
#(2)reset_index的功能跟set_index刚好相反,层次化索引的级别会被转移到列里面
print frame2.reset_index()
#输出结果如下:
# c d a b
# 0 one 0 0 7
# 1 one 1 1 6
# 2 one 2 2 5
# 3 two 0 3 4
# 4 two 1 4 3
# 5 two 2 5 2
# 6 two 3 6 1
19.pandas的整数索引和面板数据
import numpy as np
from pandas import Series,DataFrame
from numpy import nan as NA
import pandas as pd
import pandas.io.data as web
#整数索引
ser=Series(np.arange(3.))
# print ser[-1] #会报错
#在这种情况下,虽然pandas会"求助于"整数索引,但没有哪种方法能够既不引入任何bug又有效地解决该问题
#这里,我们有一个含有0,1,2的索引,但是很难推断出用户想要什么
print ser
#输出结果哪下:
# 0 0.0
# 1 1.0
# 2 2.0
# dtype: float64
#对于一个非整数索引,就没有这样的歧义
ser2=Series(np.arange(3.),index=['a','b','c'])
print ser2[-1] #输出结果:2.0
print ser.ix[:1]
#输出结果如下:
# 0 0.0
# 1 1.0
# value 方法和DataFrame的irow和icol方法
ser3=Series(range(3),index=[-5,1,3])
# print ser3.iget_value(2)
frame=DataFrame(np.arange(6).reshape(3,2),index=[2,0,1])
print frame
print frame.irow(0)
#面板数据
pdata=pd.Panel(dict((stk,web.get_data_yahoo(stk,'1/1/2009','6/1/2012'))
for stk in ['AAPL','GOOG','MSFT','DELL']))
print pdata