利用python进行数据分析之pandas库的应用(二)

本节介绍Series和DataFrame中的数据的基本手段

重新索引

pandas对象的一个重要方法就是reindex,作用是创建一个适应新索引的新对象

 

>>> from pandas import Series,DataFrame
>>> obj=Series([4.5,7.2,-5.3,3.6],index=['d','b','a','c'])
>>> obj
d    4.5
b    7.2
a   -5.3
c    3.6
dtype: float64
#reindex对索引值进行重排,如果当前索引值不存在,就引入缺失值
>>> obj2=obj.reindex(['a','b','c','d','e']) >>> obj2 a -5.3 b 7.2 c 3.6 d 4.5 e NaN dtype: float64
#可以指定fill_value=0来进行缺失值的替换
>>> obj.reindex(['a','b','c','d','e'],fill_value=0) a -5.3 b 7.2 c 3.6 d 4.5 e 0.0 dtype: float64

 

对于时间序列这样的有序数据,重新索引时可能需要做一些插值处理,method选项即可达到此目的:

method参数介绍
参数 说明
ffill或pad 前向填充
bfill或backfill 后向填充

 

 

 

 

>>> obj3=Series(['blue','red','yellow'],index=[0,2,4])
>>> obj3.reindex(range(6),method='ffill')
0      blue
1      blue
2       red
3       red
4    yellow
5    yellow
dtype: object

对于DataFrame数据类型,reindex可以修改行与列索引,但如果仅传入一个序列,则优先重新索引行:

>>> DataFrame(np.arange(9).reshape((3,3)),index=['a','c','d'],columns=['ohio','texas','california'])
   ohio  texas  california
a     0      1           2
c     3      4           5
d     6      7           8
>>> frame=DataFrame(np.arange(9).reshape((3,3)),index=['a','c','d'],columns=['ohio','texas','california'])
>>> frame2=frame.reindex(['a','b','c','d'])
>>> frame2
   ohio  texas  california
a     0      1           2
b   NaN    NaN         NaN
c     3      4           5
d     6      7           8
#使用columns关键字可以对列重新索引 >>> frame.reindex(columns=['texas','utah','california']) texas utah california a 1 NaN 2 c 4 NaN 5 d 7 NaN 8
#可利用ix的标签索引功能,重新索引任务可以变得简洁
frame.ix[['a','b','c','d'],['texas','utah','california']]

     texas   utah   california
  a      1   NaN     2
  b    NaN   NaN         NaN
  c      4   NaN         5
  d      7   NaN         8

丢弃指定轴上的项

丢弃轴上的项很简单,使用drop方法返回的是一个在指定轴上删除指定值的新对象

>>> obj=Series(np.arange(5),index=['a','b','c','d','e'])
>>> new_obj=obj.drop('c')
>>> new_obj
a    0
b    1
d    3
e    4
dtype: int32
#对于DataFrame,可以删除任意轴上的索引值
>>> frame=DataFrame(np.arange(9).reshape((3,3)),index=['a','c','d'],columns=['ohio','texas','california']) >>> frame.drop(['ohio'],axis=1) texas california a 1 2 c 4 5 d 7 8

 

索引,选取和过滤

Series利用标签的切片运算与普通的python切片运算不同,其末端是包含的,

DataFrame进行索引就是获取一个或多个列

>>> frame.drop(['ohio'],axis=1)
   texas  california
a      1           2
c      4           5
d      7           8
>>> frame
   ohio  texas  california
a     0      1           2
c     3      4           5
d     6      7           8
>>> frame['ohio']
a    0
c    3
d    6
Name: ohio, dtype: int32
#也可通过切片和布尔型来选取
>>> frame[:2] ohio texas california a 0 1 2 c 3 4 5 >>> frame[frame['ohio']>=3] ohio texas california c 3 4 5 d 6 7 8

为了在DateFrame上进行标签索引,我们引入ix:

>>> frame
   ohio  texas  california
a     0      1           2
c     3      4           5
d     6      7           8
>>> frame.ix['a',['ohio','texas']]  #注意行标签在前,列标签在后
ohio     0
texas    1
Name: a, dtype: int32

 算术运算和数据对齐

pandas最重要的功能是对不同索引的对象进行算术运算,在将对象相加时,如果存在不同的索引对,则结果就是该索引对的并集。

>>> 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'])
>>> s1+s2
a    5.2
c    1.1
d    NaN
e    0.0
f    NaN
g    NaN
dtype: float64
#自动对齐操作在不重叠的索引处引入na值,缺失值会在算术运算中传播

在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'])
>>> df1
          b  c  d
ohio      0  1  2
texas     3  4  5
colorado  6  7  8
>>> df2
        b   d   e
utah    0   1   2
ohio    3   4   5
texas   6   7   8
oregon  9  10  11
>>> df1+df2
           b   c   d   e
colorado NaN NaN NaN NaN
ohio       3 NaN   6 NaN
oregon   NaN NaN NaN NaN
texas      9 NaN  12 NaN
utah     NaN NaN NaN NaN
#只返回行列均匹配的数值

 在对不同的索引对象进行算术运算时,当一个对象中某个轴标签在另一个对象中找不到时填充一个特殊值

>>> df1
          b  c  d
ohio      0  1  2
texas     3  4  5
colorado  6  7  8
>>> df2
        b   d   e
utah    0   1   2
ohio    3   4   5
texas   6   7   8
oregon  9  10  11
>>> df1.add(df2,fill_value=0)
          b   c   d   e
colorado  6   7   8 NaN
ohio      3   1   6   5
oregon    9 NaN  10  11
texas     9   4  12   8
utah      0 NaN   1   2

DataFrame和Series之间的算术运算也是有明确规定的,会进行一种广播运算,默认情况下DataFrame和Series之间的运算会将Series的索引匹配到DataFrame的列索引,然后沿着行一直向下传播,

>>> frame=DataFrame(np.arange(12).reshape((4,3)),columns=list('bde'),index=['utah','ohio','texas','oregon'])
>>> series=frame.ix[0]
>>> frame
        b   d   e
utah    0   1   2
ohio    3   4   5
texas   6   7   8
oregon  9  10  11
>>> series
b    0
d    1
e    2
Name: utah, dtype: int32
>>> frame-series
        b  d  e
utah    0  0  0
ohio    3  3  3
texas   6  6  6
oregon  9  9  9

如果希望匹配行索引并且在列上进行广播,则必须使用算是运算方法:

>>> frame['d']
utah       1
ohio       4
texas      7
oregon    10
Name: d, dtype: int32
>>> frame.sub(frame['d'],axis=0)
        b  d  e
utah   -1  0  1
ohio   -1  0  1
texas  -1  0  1
oregon -1  0  1

 函数应用和映射

numpy的函数也可以操作pandas对象:

>>> frame=DataFrame(np.random.randn(4,3),columns=list('bde'),index=['utah','ohio','texas','oregon'])
>>> frame
               b         d         e
utah   -1.258749  0.147998  0.250556
ohio    0.801182 -0.295881  1.377340
texas  -0.281857 -0.009323 -0.520724
oregon  1.859103  0.098237 -0.475264
>>> np.abs(frame)
               b         d         e
utah    1.258749  0.147998  0.250556
ohio    0.801182  0.295881  1.377340
texas   0.281857  0.009323  0.520724
oregon  1.859103  0.098237  0.475264

另一种常用的操作是,将函数应用到由各行各列所形成的一维数组上,利用apply方法可实现此功能:

>>> f=lambda x: x.max()-x.min()
>>> frame.apply(f)  #在行上进行操作
b    3.117851
d    0.443879
e    1.898065
dtype: float64
>>> frame.apply(f,axis=1)#在列上进行函数操作
utah      1.509304
ohio      1.673221
texas     0.511402
oregon    2.334367
dtype: float64
>>> 

 元素级的python函数也是适用的:

>>> format1=lambda x:'%.2f' %x
>>> frame.applymap(format1)  #用applymap,是因为Series有一个用于元素级函数的map方法
            b      d      e
utah    -1.26   0.15   0.25
ohio     0.80  -0.30   1.38
texas   -0.28  -0.01  -0.52
oregon   1.86   0.10  -0.48

排序和排名

根据条件对数据集排序也是一种重要的内置运算,对行列索引进行排序可使用sort_index方法,它将返回一个已排序的新对象

>>> obj=Series(range(4),index=['a','b','c','d'])
>>> obj.sort_index()
a    0
b    1
c    2
d    3
dtype: int64

对于DataFrame,可以根据任意一个轴上的索引进行排序:

>>> frame=DataFrame(np.arange(8).reshape((2,4)),index=['three','one'],columns=['d','a','b','c'])
>>> frame
       d  a  b  c
three  0  1  2  3
one    4  5  6  7
>>> frame.sort_index()
       d  a  b  c
one    4  5  6  7
three  0  1  2  3
>>> frame.sort_index(axis=1)  #指定轴进行排序
       a  b  c  d
three  1  2  3  0
one    5  6  7  4

 Series若要进行按值排序,则可使用order方法,ascending参数可指定升降序

>>> obj
a    0
b    1
c    2
d    3
dtype: int64
>>> obj.order(ascending=False)
d    3
c    2
b    1
a    0
dtype: int64 #排序时任何缺失值都会被排到Series的末尾

DataFrame的按值排序可以根据一个或多个列中的值进行排序,将一个或多个列名传递给by参数即可

>>> frame=DataFrame({'a':[4,7,-3,2],'b':[0,1,0,1]})
>>> frame
   a  b
0  4  0
1  7  1
2 -3  0
3  2  1
>>> frame.sort_index(by='b')
   a  b
0  4  0
2 -3  0
1  7  1
3  2  1
>>> frame.sort_index(by=['a','b'])  #多列排序传入列名的列表即可
   a  b
2 -3  0
3  2  1
0  4  0
1  7  1

排名跟排序关系密切,且会增加一个排名值(排名从1开始),给对应值排名,输出索引和名次,

>>> obj=Series([7,-5,7,4,2,0,4])
>>> obj
0    7
1   -5
2    7
3    4
4    2
5    0
6    4
dtype: int64
>>> 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

rank函数也可以根据值在数据中出现的位置顺序进行排名,相同值顺序在前排名高,也可以进行降序排名:

>>> obj.rank(method='first')
0    6
1    1
2    7
3    4
4    3
5    2
6    5
dtype: float64
>>> obj.rank(ascending=False,method='max')
0    2
1    7
2    2
3    4
4    5
5    6
6    4
dtype: float64

带有重复值的轴索引

pandas中轴索引非必须为唯一,对于带有重复值的索引,数据选取的行为将不同,如果某个索引对应多个值,则返回一个Series,而对应单个值,则返回一个标量值,对于Series与DataFrame类型数据皆为如此。(DataFrame单索引返回Series,重复索引返回DataFrame类型)

>>> obj=Series(range(5),index=['a','a','b','b','c'])
>>> obj.index.is_unique
False
>>> obj['a']
a    0
a    1
dtype: int64
>>> obj['c']
4

汇总和计算统计描述

idxmin,idxmax返回的是间接统计,cumsum返回累计统计

>>> 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'])
>>> df
    one  two
a  1.40  NaN
b  7.10 -4.5
c   NaN  NaN
d  0.75 -1.3
>>> df.idxmax()
one    b
two    d
dtype: object
>>> df.cumsum()
    one  two
a  1.40  NaN
b  8.50 -4.5
c   NaN  NaN
d  9.25 -5.8

describe方法一次性产生多个汇总统计,对于非数值型数据,describe方法会产生另外一种汇总统计:

>>> 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
>>> obj=Series(['a','a','b','c']*4)
>>> obj.describe()
count     16
unique     3
top        a
freq       8
dtype: object
描述和汇总统计方法介绍
参数 说明
count 非NA值的数量
describe 针对Series或各DataFrame列计算汇总统计
min,max 计算最大值和最小值
argmin,argmax 计算能够获取到最大最小值的索引位置(整数)
idxmin,idxmax 计算能够获取到最大最小值的索引值
sum 值的求和
mean 均值
mad 根据平均值计算绝对离差
var 方差
std 标准差
diff 计算一阶差分
cumsum 样本值的累积和

 

 

 

 

 

 

 

 

 

 

唯一值,值计数以及成员资格

一类方法可以从一维Series中抽取信息:

>>> obj=Series(['c','a','d','a','a','b','b','c'])
>>> uniques=obj.unique()
>>> uniques
array(['c', 'a', 'd', 'b'], dtype=object)
#unique方法得到Series中唯一值数组
>>> obj.value_counts()
a    3
b    2
c    2
d    1
dtype: int64
#value_counts用于计算Series中各值出现的频率
>>> mask=obj.isin(['b','c'])
>>> mask
0     True
1    False
2    False
3    False
4    False
5     True
6     True
7     True
dtype: bool
>>> obj[mask]
0    c
5    b
6    b
7    c
dtype: object
#isin用于判断矢量化的成员资格,可用于选取Series列中的数据子集

 处理缺失数据

pandas使用浮点值NaN表示浮点数和非浮点数组中的缺失数据,它只是一个便于被检测出来的标记,pandas对象上所有的描述统计都排除了缺失数据

>>> from pandas import Series,DataFrame
>>> import numpy as np
>>> string_data=Series(['aardvark','artichoke',np.nan,'avocado'])
>>> string_data
0     aardvark
1    artichoke
2          NaN
3      avocado
dtype: object
>>> sring_data.isnull()
>>> string_data.isnull()
0    False
1    False
2     True
3    False
dtype: bool
#python内置的None属性会被当作NA处理
>>> string_data[0]=None
>>> string_data.isnull()
0     True
1    False
2     True
3    False
dtype: bool

滤除缺失数据的方法有很多,手工是一种,但dropna是比较实用的一种方法,dropna返回一个仅含非空数据和索引值的Series。

>>> data=Series([1,np.nan,3.5,np.nan,7])
>>> data
0    1.0
1    NaN
2    3.5
3    NaN
4    7.0
dtype: float64
>>> data.dropna()
0    1.0
2    3.5
4    7.0
dtype: float64
#也可以通过布尔型索引达到这个目的
>>> data[data.notnull()]
0    1.0
2    3.5
4    7.0
dtype: float64

对于DataFrame对象,dropnan默认丢弃任何含有缺失值的行:

>>> data=DataFrame([[1,6.5,3],[1,np.nan,np.nan],[np.nan,np.nan,np.nan],[np.nan,6.5,3]])
>>> data
    0    1   2
0   1  6.5   3
1   1  NaN NaN
2 NaN  NaN NaN
3 NaN  6.5   3
>>> cleaned=data.dropna()
>>> cleaned
   0    1  2
0  1  6.5  3
#传入how='all',则只丢弃全为na的那些行
>>> data.dropna(how='all')
    0    1   2
0   1  6.5   3
1   1  NaN NaN
3 NaN  6.5   3
#如要丢弃列,则传入axis=1即可

 当你不想丢弃过滤缺失数据时,可以通过其他方法填补缺失数据,大多数情况下fillna是最主要的函数,通过一个常数调用就会将缺失值替换为想要的常数值

>>> df.ix[:4,1]=np.nan
>>> df
          0         1         2
0  0.644651       NaN -0.858760
1 -0.093238       NaN -0.179058
2  1.547357       NaN -0.160275
3 -0.159654       NaN -0.898084
4 -0.987568       NaN -0.128100
5 -0.950301 -0.882556  0.155634
6  1.090057 -0.312113 -1.098901
>>> df.fillna(0)
          0         1         2
0  0.644651  0.000000 -0.858760
1 -0.093238  0.000000 -0.179058
2  1.547357  0.000000 -0.160275
3 -0.159654  0.000000 -0.898084
4 -0.987568  0.000000 -0.128100
5 -0.950301 -0.882556  0.155634
6  1.090057 -0.312113 -1.098901
#通过字典调用fillna,可实现不同列填充不同的值
>>> df.fillna({1:0.5,3:-1})
          0         1         2
0  0.644651  0.500000 -0.858760
1 -0.093238  0.500000 -0.179058
2  1.547357  0.500000 -0.160275
3 -0.159654  0.500000 -0.898084
4 -0.987568  0.500000 -0.128100
5 -0.950301 -0.882556  0.155634
6  1.090057 -0.312113 -1.098901

 层次化索引

层次化索引是pandas的一项重要功能,它使你能在一个轴上拥有多个索引级别,可以低纬度的形式处理高维度数据:

 

>>> 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]])
>>> data
a  1    0.671419
   2   -0.645337
   3   -0.681691
b  1   -1.096300
   2   -1.017407
   3   -0.299791
c  1    1.268928
   2    1.051565
d  2    0.821926
   3   -0.628511
dtype: float64
>>> data['b']
1   -1.096300
2   -1.017407
3   -0.299791
dtype: float64
#数据甚至可以在内层选取
>>> data[:,2]
a   -0.645337
b   -1.017407
c    1.051565
d    0.821926
dtype: float64

层次化索引在数据重塑和基于分组的操作中,扮有重要角色,对于DataFrame,每条轴都可以有分层索引,可以轻松选取列分组

#Series可以通过unstack安排到一个DataFrame中去
>>> data.unstack()
          1         2         3
a  0.671419 -0.645337 -0.681691
b -1.096300 -1.017407 -0.299791
c  1.268928  1.051565       NaN
d       NaN  0.821926 -0.628511
>>> data.unstack().stack()
a  1    0.671419
   2   -0.645337
   3   -0.681691
b  1   -1.096300
   2   -1.017407
   3   -0.299791
c  1    1.268928
   2    1.051565
d  2    0.821926
   3   -0.628511
dtype: float64

重排分级顺序与根据级别进行汇总统计

有时需要重新调整某条轴上各级别的顺序或者根据指定级别上的值进行重新排序,swaplevel可以接受两个级别编号或名称,并返回一个互换了级别的新对象。值汇总统计时,使用level参数可以指定在某条轴上求和的级别。

>>> 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
     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']
>>> 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
#在key2上进行归纳求和 >>> 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的set_index函数会将其一个或多个列转换为行索引,并创建一个新的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]})
>>> frame2=frame.set_index(['c','d'])
>>> 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

 

posted on 2016-02-19 16:48  splended  阅读(1834)  评论(0编辑  收藏  举报

导航