ch05-pandas入门

pandas库是本书后续内容的首选库。它含有使数据分析工作变得更快更简单的高级数据结构和操作工具。pandas是基于NumPy构建的。让以NumPy为中心的应用变得更加简单

要使用pandas, 首先得熟悉它的两个主要数据结构:Series和DataFrame,虽然它们不能解决所有问题,但它们为大多数应用提供了一种可靠的、易于使用的基础

本文摘要

  • Series
  • DataFrame
    • 可以输入给DataFrame构造器的数据
  • 索引对象
  • 基本功能
    • 重新索引
  • 丢弃指定轴上的项
  • 索引、选取和过滤
    • 对DataFrame的索引选项(重要)
  • 算数运算和数据对齐
    • 在算数方法中填充值
    • DataFrame和Series之前的运算
  • 函数应用和映射
    • 1.NumPy的ufuncs(元素级数组方法)也可用于操作pandas对象:
    • 2.行列级自定义函数
    • 3.使用 applymap 而非 apply 就可以采用元素级别的方法
  • 排序和排名
    • Series排序
    • DataFrame排序
    • 对 Series 值的排序
    • 对DataFrame的行依据某个列的值进行排序
    • 排名
  • 带重复值的轴索引
  • 汇总和计算描述统计
  • 相关系数与协方差
  • 唯一值、值计数以及成员资格
    • 1.唯一值
    • 2.计数
    • 3.成员资格
  • 处理缺失数据
    • 1.滤除缺失数据
    • 2.填充缺失数据
  • 层次化索引

首先是常用和必要的引入

from pandas import Series, DataFrame
import pandas as pd

Series

Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型)以及以一组与之相关的数据标签(即索引)组成。仅由一组数据即可产生最简单的Series

obj = Series([4, 7, -5, 3])

obj
Out[4]: 
0    4
1    7
2   -5
3    3
dtype: int64

它拥有一些性质

obj.values
Out[5]: array([ 4,  7, -5,  3], dtype=int64)

obj.index
Out[6]: RangeIndex(start=0, stop=4, step=1)

如果希望指定各个数据点的索引,可以将这个索引的数据作为第二个参数传入series函数中

obj2 = Series([4, 7, -5, 3], index = ['d', 'b', 'a', 'c'])

obj2
Out[8]: 
d    4
b    7
a   -5
c    3
dtype: int64

这样就可以通过指定的索引值来访问具体数据

obj2['a']
Out[9]: -5

还可以将Series看成一个定长的有序字典,因为它是索引值映射到数据值的一个映射。它可以用在许多原来需要字典参数的函数中

如下

'b' in obj2
Out[10]: True

既然如此,也可以通过字典来创建Series

sdata = {'hello':1000, 'bye':200}

obj3 = Series(sdata)

obj3
Out[13]: 
bye       200
hello    1000
dtype: int64

已经建好一个Series之后,如果再次对这个Series调用Series方法,就可以从原来的内容中筛选出部分需要的数据
如下

states = ['hello', 'hi']

obj4 = Series(sdata, index=states)

obj4
Out[16]: 
hello    1000.0
hi          NaN
dtype: float64

pd 中的 isnul 和 notnull 可以直接用于检测Series中值是否为NULL


pd.isnull(obj4)
Out[17]: 
hello    False
hi        True
dtype: bool

pd.notnull(obj4)
Out[18]: 
hello     True
hi       False
dtype: bool

对于许多应用而言,Series的最重要的一个功能是:它在算术运算中会自动对齐不同索引的数据

obj3 + obj4
Out[21]: 
bye         NaN
hello    2000.0
hi          NaN
dtype: float64

此外,Serie对象本身及其索引都有一个name的属性,该属性跟pandas的其他关键功能的关系非常密切

obj4.name = 'population'

obj4.index.name

obj4.index.name = 'state'

obj4
Out[25]: 
state
hello    1000.0
hi          NaN
Name: population, dtype: float64

Series的索引可以通过赋值的方式直接修改

obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan']

DataFrame

DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引、它可以被看做由Series组成的字典(共用同一个索引)
构建DataFrame的方法有很多,最常用的一种是直接传入一个由等长列表或NumPy数组组成的字典

 data = {'state':['Beijing', 'Hangzhou', 'Shanghai', 'Shenzhen'],
        'year':[2000, 2001, 2002, 2001],
        'pop':[1.4, 1.2, 2.3, 3.1]}

frame = DataFrame(data)

结果DataFrame会自动加上索引,并且全部列会被有序排列


frame
Out[36]: 
   pop     state  year
0  1.4   Beijing  2000
1  1.2  Hangzhou  2001
2  2.3  Shanghai  2002
3  3.1  Shenzhen  2001

如果指定了列序列,则DataFrame的列就会按照指定的顺序进行排列

DataFrame(data, columns=['year', 'state', 'pop'])
Out[37]: 
   year     state  pop
0  2000   Beijing  1.4
1  2001  Hangzhou  1.2
2  2002  Shanghai  2.3
3  2001  Shenzhen  3.1

跟Series一样,如果传入的列在数据中找不到,就会产生NA值

frame2 = DataFrame(data, columns = ['year', 'state', 'pop', 'debt'],
                    index = ['one', 'two', 'three','four'])

frame2
Out[40]: 
       year     state  pop debt
one    2000   Beijing  1.4  NaN
two    2001  Hangzhou  1.2  NaN
three  2002  Shanghai  2.3  NaN
four   2001  Shenzhen  3.1  NaN

类似于字典标记的方法或属性的方式,可以将DataFrame的列获取为一个Series
如下

frame2['state']
Out[7]: 
one       Beijing
two      Hangzhou
three    Shanghai
four     Shenzhen
Name: state, dtype: object
frame2.year
Out[8]: 
one      2000
two      2001
three    2002
four     2001
Name: year, dtype: int64

对DataFrame的行也可以进行索引,比如用索引字段 ix

frame2.ix['three']
__main__:1: DeprecationWarning: 
.ix is deprecated. Please use
.loc for label based indexing or
.iloc for positional indexing

See the documentation here:
http://pandas.pydata.org/pandas-docs/stable/indexing.html#ix-indexer-is-deprecated
Out[9]: 
year         2002
state    Shanghai
pop           2.3
debt          NaN
Name: three, dtype: object

类似NumPy数组,也可以将列以赋值的方式进行修改

frame2['debt'] = 16.5

frame2
Out[11]: 
       year     state  pop  debt
one    2000   Beijing  1.4  16.5
two    2001  Hangzhou  1.2  16.5
three  2002  Shanghai  2.3  16.5
four   2001  Shenzhen  3.1  16.5

或者

frame2['debt'] = np.arange(4)

frame2
Out[15]: 
       year     state  pop  debt
one    2000   Beijing  1.4     0
two    2001  Hangzhou  1.2     1
three  2002  Shanghai  2.3     2
four   2001  Shenzhen  3.1     3

将列表或者数组赋值给某个列时,其长度必须跟DataFrame的长度相等。如果赋值的是一个Series,就会精确匹配DataFrame的索引,所有的空位都会被填上缺失值

val = Series([-1.2, -1.5, -.17], index=['two', 'four', 'one'])
frame2['debt'] = val
frame2
Out[19]: 
       year     state  pop  debt
one    2000   Beijing  1.4 -0.17
two    2001  Hangzhou  1.2 -1.20
three  2002  Shanghai  2.3   NaN
four   2001  Shenzhen  3.1 -1.50

为不存在的列赋值将会创建出一个新列。关键字del用于删除列

frame2['Beijing'] = frame2.state == 'Beijing'

frame2
Out[22]: 
       year     state  pop  debt  Beijing
one    2000   Beijing  1.4 -0.17     True
two    2001  Hangzhou  1.2 -1.20    False
three  2002  Shanghai  2.3   NaN    False
four   2001  Shenzhen  3.1 -1.50    False
del frame2['Beijing']

frame2
Out[24]: 
       year     state  pop  debt
one    2000   Beijing  1.4 -0.17
two    2001  Hangzhou  1.2 -1.20
three  2002  Shanghai  2.3   NaN
four   2001  Shenzhen  3.1 -1.50

注意,以索引的方式返回的列只是相应数据的视图而已,不是副本。对返回的Series的任何就地修改全都会反映到源DataFrame上

另外一种创建DataFrame的方式是通过嵌套字典。这会被解释为:外层字典的键作为列,内层键作为索引

pop = {'Nevada':{2001: 2.4, 2002:2.9},
        'Ohio':{2000:1.5, 2002:3.6}}


frame3 = DataFrame(pop)

frame3
Out[27]: 
      Nevada  Ohio
2000     NaN   1.5
2001     2.4   NaN
2002     2.9   3.6

对已经建好的DataFrame的处理又多种多样了

frame3.T
Out[29]: 
        2000  2001  2002
Nevada   NaN   2.4   2.9
Ohio     1.5   NaN   3.6
DataFrame(pop, index=[2001, 2002, 2003])
Out[30]: 
      Nevada  Ohio
2001     2.4   NaN
2002     2.9   3.6
2003     NaN   NaN

由Series组成的字典类似

pdata = {'Ohio':frame3['Ohio'][:-1],
        'Nevada':frame3['Nevada'][:2]}


DataFrame(pdata)
Out[41]: 
      Nevada  Ohio
2000     NaN   1.5
2001     2.4   NaN

可以输入给DataFrame构造器的数据

  • 二维ndarray
  • 由数组、列表或元组组成的字典,每个序列变成DataFrame的一列。所有序列程度必须相同
  • NumPy的结构化/记录数组
  • 由Series组成的字典
  • 由字典组成的字典(前文中的嵌套字典)

  • 如果设置了DataFrame的index和columns 的name属性,这些信息也会显示处理
frame3.index.name = 'year'; frame3.columns.name = 'state'

frame3
Out[44]: 
state  Nevada  Ohio
year               
2000      NaN   1.5
2001      2.4   NaN
2002      2.9   3.6

跟Series一样,values属性会以二维ndarray形式返回DataFrame中的数据

frame3.values
Out[45]: 
array([[ nan,  1.5],
       [ 2.4,  nan],
       [ 2.9,  3.6]])
frame2.values
Out[48]: 
array([[2000, 'Beijing', 1.4, -0.17],
       [2001, 'Hangzhou', 1.2, -1.2],
       [2002, 'Shanghai', 2.3, nan],
       [2001, 'Shenzhen', 3.1, -1.5]], dtype=object)

索引对象

Pandas的索引对象负责管理轴标签和其他元数据(比如轴名称等)。构建Series或DataFrame时,所用到的任何数组或其他序列的标签都会被转换成一个Index

obj = Series(range(3), index = ['a', 'b', 'c'])

obj
Out[3]: 
a    0
b    1
c    2
dtype: int32

index = obj.index

index
Out[5]: Index(['a', 'b', 'c'], dtype='object')

访问方法与Series相似

index[1:]
Out[6]: Index(['b', 'c'], dtype='object')

index[1]
Out[7]: 'b'

但是Index对象是不可修改的(immutable),下面这条语句会导致TypeError: Index does not support mutable operations

index[1] = 'd'

不可修改性非常重要,因为这样才能使Index对象在多个数据结构之间安全共享

obj2 = Series([1.5, 2,-1], index = index)

obj2
Out[14]: 
0    1.5
1    2.0
2   -1.0
dtype: float64

obj2.index is index
Out[15]: True

除了长得像数组,Index的功能也类似一个固定大小的集合,也就是说可以通过类似'Ohio' in frame3.index 这样的方法访问

index的方法和属性

  • append
  • diff
  • intersection
  • union
  • isin
  • delete
  • unique 计算Index中的唯一值

基本功能

重新索引

pandas对象的一个重要方法就是重新索引,当某个索引值当前不存在,就引入缺失值

obj = Series([4.5, 7.1, 1.1, -2.3], index = ['d', 'b', 'a', 'c'])

obj
Out[24]: 
d    4.5
b    7.1
a    1.1
c   -2.3
dtype: float64

obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])

obj2
Out[26]: 
a    1.1
b    7.1
c   -2.3
d    4.5
e    NaN
dtype: float64

也可以指定值填充

obj.reindex(['a', 'b', 'c', 'd', 'e'], fill_value=0)
Out[27]: 
a    1.1
b    7.1
c   -2.3
d    4.5
e    0.0
dtype: float64

对于时间序列这样的有序数据,重新索引时可能需要做一些差值处理,method方法可以达到此目的,比如下面的用后向值填充

obj3 = Series(['Blue', 'purple', 'yellow'], index=[0,2,4])

obj3
Out[29]: 
0      Blue
2    purple
4    yellow
dtype: object

obj3.reindex(range(6), method='bfill')
Out[30]: 
0      Blue
1    purple
2    purple
3    yellow
4    yellow
5       NaN
dtype: object

此外reindex的(插值)method选项

  • ffill 前向填充
  • bfill 后向填充

对于DataFrame,reindex可以修改行索引,列索引,也可以两个都修改,如果只传入一个,则重新索引行

frame = DataFrame(np.arange(9).reshape((3,3)), index=['a','c','d'],
                columns=['Ohio', 'Texas', 'California'])


frame
Out[33]: 
   Ohio  Texas  California
a     0      1           2
c     3      4           5
d     6      7           8
frame2 = frame.reindex('a b c d'.split())

frame2
Out[35]: 
   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

states = ['Texas', 'Utah', 'Califor']

frame.reindex(columns=states)
Out[37]: 
   Texas  Utah  Califor
a      1   NaN      NaN
c      4   NaN      NaN
d      7   NaN      NaN

使用 ix 标签索引功能,重新索引任务变得更加简洁

frame.ix[['a','b','c','d'], states]
__main__:1: DeprecationWarning: 
.ix is deprecated. Please use
.loc for label based indexing or
.iloc for positional indexing

See the documentation here:
http://pandas.pydata.org/pandas-docs/stable/indexing.html#ix-indexer-is-deprecated
Out[47]: 
   Texas  Utah  Califor
a    1.0   NaN      NaN
b    NaN   NaN      NaN
c    4.0   NaN      NaN
d    7.0   NaN      NaN

reindex函数的参数

  • index
  • method
  • fill_value
  • limit
  • level
  • copy

丢弃指定轴上的项

先建立一个pandas结构

data = DataFrame(np.arange(16).reshape((4, 4)),
                index = 'Ohio Colorado Utah NewYork'.split(),
                columns = 'one two three four'.split())


data
Out[55]: 
          one  two  three  four
Ohio        0    1      2     3
Colorado    4    5      6     7
Utah        8    9     10    11
NewYork    12   13     14    15

如果试图删除一个不存在的行或列,则会触发一个ValueError: labels ['Beijing'] not contained in axis
删除一整行的元素可以直接用data.drop('NewYork')

data2 = data.drop('Ohio')

data2
Out[61]: 
          one  two  three  four
Colorado    4    5      6     7
Utah        8    9     10    11
NewYork    12   13     14    15

如果希望删除一整列的元素,则需要增加一个axis=1的说明

data.drop('two', axis = 1)
Out[64]: 
          one  three  four
Ohio        0      2     3
Colorado    4      6     7
Utah        8     10    11
NewYork    12     14    15

索引、选取和过滤

对行元素的索引总是十分简单的,跟纯Python的数组和Series类似,不同的是,这里的切片是包含末端的(仅是对于用标签切片,用数字切片还是不包含末端的)

先建立一个pandas结构

obj = Series(np.arange(4.), index = 'a b c d'.split())

obj
Out[70]: 
a    0.0
b    1.0
c    2.0
d    3.0
dtype: float64

下面是索引的示例

obj['b']
Out[71]: 1.0

obj[1]
Out[72]: 1.0

obj[2:4]
Out[73]: 
c    2.0
d    3.0
dtype: float64

obj['b a d'.split()]
Out[74]: 
b    1.0
a    0.0
d    3.0
dtype: float64

obj[obj<2]
Out[75]: 
a    0.0
b    1.0
dtype: float64

obj['b':'c']
Out[76]: 
b    1.0
c    2.0
dtype: float64

obj['b':'c'] = 5

obj
Out[78]: 
a    0.0
b    5.0
c    5.0
d    3.0
dtype: float64

使用前文中用到的data

data['one']
Out[82]: 
Ohio         0
Colorado     4
Utah         8
NewYork     12
Name: one, dtype: int32

这样看只是需要在调用drop方法的时候特别地标明 axis = 1而在简单的索引的时候是可以直接索引到的

下面再展示一些其他的选取方法

data[data['three']>5]
Out[86]: 
          one  two  three  four
Colorado    4    5      6     7
Utah        8    9     10    11
NewYork    12   13     14    15
data<5
Out[87]: 
            one    two  three   four
Ohio       True   True   True   True
Colorado   True  False  False  False
Utah      False  False  False  False
NewYork   False  False  False  False

data[data<5]
Out[88]: 
          one  two  three  four
Ohio      0.0  1.0    2.0   3.0
Colorado  4.0  NaN    NaN   NaN
Utah      NaN  NaN    NaN   NaN
NewYork   NaN  NaN    NaN   NaN

data[data<5] = 0

data
Out[90]: 
          one  two  three  four
Ohio        0    0      0     0
Colorado    0    5      6     7
Utah        8    9     10    11
NewYork    12   13     14    15

ix 方法也很有意义

data.ix[data.three >5, :3]
Out[95]: 
          one  two  three
Colorado    0    5      6
Utah        8    9     10
NewYork    12   13     14

data.ix[1,2]
Out[96]: 6

对DataFrame的索引选项(重要)

  • obj [ val ] 选取DataFrame的单个列或一组列
  • obj.ix [ val ] 选取DataFrame的单个行或一组行
  • obj.ix [ :, val] 选取单个列或列子集
  • obj.ix [ val1, val2] 同时选取行或列
  • reindex 方法 将一个或多个轴匹配到新索引

总结,如果希望总是成功选取,建议使用 ix 方法

算数运算和数据对齐

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

下面是一个例子,先建立两个Series

s1 = Series([7.3, -2.5, 3.4, 5], index='a c d e'.split())

s2 = Series([-2, 3, 2, 5,10], index='a c e f g'.split())

s1
Out[112]: 
a    7.3
c   -2.5
d    3.4
e    5.0
dtype: float64

s2
Out[113]: 
a    -2
c     3
e     2
f     5
g    10
dtype: int64
s1+s2
Out[114]: 
a    5.3
c    0.5
d    NaN
e    7.0
f    NaN
g    NaN
dtype: float64

可见,重叠的项(都有的)值相加,不同的项,为NA值

如果在DataFrame,对齐操作会发生在行和列上

df1 = DataFrame(np.arange(16).reshape((4, 4)),
                index = 'Ohio Colorado Utah NewYork'.split(),
                columns = 'one two three four'.split())


df2 = DataFrame(np.arange(9).reshape((3, 3)),
                index = 'Ohio Colorado NewYork'.split(),
                columns = 'one two four'.split())
df1+df2
Out[121]: 
          four   one  three   two
Colorado  12.0   7.0    NaN   9.0
NewYork   23.0  18.0    NaN  20.0
Ohio       5.0   0.0    NaN   2.0
Utah       NaN   NaN    NaN   NaN

在算数方法中填充值

为了避免不重叠值会产生NA,可使用add方法,并且指定 fill_value = 0

df1.add(df2, fill_value = 0)
Out[123]: 
          four   one  three   two
Colorado  12.0   7.0    6.0   9.0
NewYork   23.0  18.0   14.0  20.0
Ohio       5.0   0.0    2.0   2.0
Utah      11.0   8.0   10.0   9.0

灵活的算数方法

  • add
  • sub
  • div
  • mul

DataFrame和Series之前的运算

首先展示一个NumPy的广播

arr = np.arange(12.).reshape((3,4))

arr
Out[125]: 
array([[  0.,   1.,   2.,   3.],
       [  4.,   5.,   6.,   7.],
       [  8.,   9.,  10.,  11.]])

arr[0]
Out[126]: array([ 0.,  1.,  2.,  3.])
arr - arr[0]
Out[127]: 
array([[ 0.,  0.,  0.,  0.],
       [ 4.,  4.,  4.,  4.],
       [ 8.,  8.,  8.,  8.]])

DataFrame的广播是类似的

frame = DataFrame(np.arange(12.).reshape((4,3)), columns=list('bde'),
                index = 'Utah Ohio Texas Oregon'.split())


frame
Out[129]: 
          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
frame - series
Out[133]: 
          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

如果希望匹配行且在行上广播,则必须要使用算数运算方法,如下

series3 = frame['d']

frame.sub(series3, axis=0)
Out[139]: 
          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

函数应用和映射

1.NumPy的ufuncs(元素级数组方法)也可用于操作pandas对象:

frame
Out[144]: 
               b         d         e
Utah    0.706821  0.626728 -0.511381
Ohio    3.949706 -1.771924 -0.416144
Texas  -0.496887 -0.894768 -0.857036
Oregon  1.301712 -0.264923 -2.200233

np.abs(frame)
Out[145]: 
               b         d         e
Utah    0.706821  0.626728  0.511381
Ohio    3.949706  1.771924  0.416144
Texas   0.496887  0.894768  0.857036
Oregon  1.301712  0.264923  2.200233

2.行列级自定义函数

也可以对DataFrame采用自己定义的函数,默认是对列

f = lambda x: x.max() - x.min()

frame.apply(f)
Out[147]: 
b    4.446593
d    2.398652
e    1.784089
dtype: float64

增加 axis 说明可以方便地转化到对行操作

frame.apply(f, axis=1)
Out[148]: 
Utah      1.218203
Ohio      5.721630
Texas     0.397881
Oregon    3.501945
dtype: float64

除了标量以外,传递给apply函数的还可以返回由多个值组成的Series

def f(x):
    return Series([x.min(), x.max()], index = ['min', 'max'])


frame
Out[151]: 
               b         d         e
Utah    0.706821  0.626728 -0.511381
Ohio    3.949706 -1.771924 -0.416144
Texas  -0.496887 -0.894768 -0.857036
Oregon  1.301712 -0.264923 -2.200233

frame.apply(f)
Out[152]: 
            b         d         e
min -0.496887 -1.771924 -2.200233
max  3.949706  0.626728 -0.416144

3.使用 applymap 而非 apply 就可以采用元素级别的方法

如下是一个将浮点数格式化为字符串的方法

format = lambda x: '%.2f' %x

frame.applymap(format)
Out[154]: 
            b      d      e
Utah     0.71   0.63  -0.51
Ohio     3.95  -1.77  -0.42
Texas   -0.50  -0.89  -0.86
Oregon   1.30  -0.26  -2.20

排序和排名

Series排序

可以直接使用 sort_index()方法

obj = Series(range(4), index = list('badc'))

obj
Out[157]: 
b    0
a    1
d    2
c    3
dtype: int32

obj.sort_index()
Out[158]: 
a    1
b    0
c    3
d    2
dtype: int32

DataFrame排序

默认对行进行排序

frame = DataFrame(np.arange(8).reshape((2,4)), index=['three', 'one'],
                columns = list('dabc'))


frame
Out[160]: 
       d  a  b  c
three  0  1  2  3
one    4  5  6  7

frame.sort_index()
Out[161]: 
       d  a  b  c
one    4  5  6  7
three  0  1  2  3

下面两个例子展示了如何通过更改传入参数,实现降序排序和按照列排序

frame.sort_index(axis=1)
Out[162]: 
       a  b  c  d
three  1  2  3  0
one    5  6  7  4

frame.sort_index(axis=1, ascending=False)
Out[163]: 
       d  c  b  a
three  0  3  2  1
one    4  7  6  5

对 Series 值的排序

obj.sort_values()
Out[168]: 
2   -1
3    2
0    4
1    7
dtype: int64

这个地方采用书上的 order() 方法会出现错误,所以这里采用 sort_value() 方法

对DataFrame的行依据某个列的值进行排序

后面一种方法实现了先按照 ‘a’ 排序, 后按照 ‘ b’ 排序

frame
Out[170]: 
   a  b
0  0  4
1  1  7
2  0 -3
3  1  2

frame.sort_index(by='b')
__main__:1: FutureWarning: by argument to sort_index is deprecated, 
                                        pls use .sort_values(by=...)
Out[171]: 
   a  b
2  0 -3
3  1  2
0  0  4
1  1  7

frame.sort_index(by=['a', 'b'])
__main__:1: FutureWarning: by argument to sort_index is deprecated, 
                                        pls use .sort_values(by=...)
Out[172]: 
   a  b
2  0 -3
0  0  4
3  1  2
1  1  7

排名

排名 rank 与排序相似,会增设一个排名值,从1开始一直数到数组中的有效值,这里可以看出,相同值对应的排名是相同的,但这不是简单的 “并列第几” ,而是 “为各组分配一个平均排名” 的方式来破坏平级关系

obj = Series([7,-5,7,4,2,0,4])

obj
Out[175]: 
0    7
1   -5
2    7
3    4
4    2
5    0
6    4
dtype: int64

obj.rank()
Out[174]: 
0    6.5
1    1.0
2    6.5
3    4.5
4    3.0
5    2.0
6    4.5
dtype: float64

排名时用于破坏平级关系的method选项:average; min; max; first

带重复值的轴索引

截止目前,所有的范例都有唯一的轴标签(索引值),虽然许多pandas函数都有唯一标签值的要求,但是这并不是唯一的。

下面是一个例子

obj = Series(range(5), index=list('aabbc'))

obj
Out[177]: 
a    0
a    1
b    2
b    3
c    4
dtype: int32

可以通过 is_unique方法判断标签是否唯一,当然先要取 index

obj.index.is_unique
Out[178]: False

obj['a']
Out[179]: 
a    0
a    1
dtype: int32

汇总和计算描述统计

跟NumPy数组方法相比,pandas的统计方法,如sum和mean都是适用于缺失数据的

df = DataFrame([[1.4, np.nan],[7.1, -4.5],
                [np.nan,np.nan],[0.75, -1.3]],
                index = list('abcd'),
                columns = ['one', 'two'])


df
Out[181]: 
    one  two
a  1.40  NaN
b  7.10 -4.5
c   NaN  NaN
d  0.75 -1.3
df.sum()
Out[182]: 
one    9.25
two   -5.80
dtype: float64

df.sum(axis = 1)
Out[183]: 
a    1.40
b    2.60
c    0.00
d   -0.55
dtype: float64

用于查找最大的数

df.idxmax()
Out[184]: 
one    b
two    d
dtype: object

cumsum是用于计算累加值的

df.cumsum()
Out[186]: 
    one  two
a  1.40  NaN
b  8.50 -4.5
c   NaN  NaN
d  9.25 -5.8

describe方法可以生成汇总统计

df.describe()
Out[187]: 
            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

描述和汇总统计

  • count
  • describe
  • min、max
  • argmin、argmax
  • idmax
  • mean、median
  • var、std
  • 还有三阶矩等统计量…

相关系数与协方差

这部分安装包的时候出了点问题,暂时不写

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

1.唯一值

obj = Series(list('cadaabbcc'))

uniques = obj.unique()

uniques
Out[194]: array(['c', 'a', 'd', 'b'], dtype=object)

2.计数

obj.value_counts()
Out[195]: 
a    3
c    3
b    2
d    1
dtype: int64

pd还有一个顶级方法也可以用于计数

pd.value_counts(obj.values, sort=False)
Out[196]: 
c    3
b    2
a    3
d    1
dtype: int64

3.成员资格

make = obj.isin(['b','c'])

make
Out[198]: 
0     True
1    False
2    False
3    False
4    False
5     True
6     True
7     True
8     True
dtype: bool

obj[make]
Out[199]: 
0    c
5    b
6    b
7    c
8    c
dtype: object

有时,你可能希望得到DataFrame中多个相关列的一张柱状图,可用如下方法


data = DataFrame({'Qu1':[1,2,3,4,5],
                    'Qu2':[2,3,1,4,3],
                    'Qu3':[4,-1,2,3,4]})


data
Out[201]: 
   Qu1  Qu2  Qu3
0    1    2    4
1    2    3   -1
2    3    1    2
3    4    4    3
4    5    3    4

result = data.apply(pd.value_counts).fillna(0)

result
Out[203]: 
    Qu1  Qu2  Qu3
-1  0.0  0.0  1.0
 1  1.0  1.0  0.0
 2  1.0  1.0  1.0
 3  1.0  2.0  1.0
 4  1.0  1.0  2.0
 5  1.0  0.0  0.0

处理缺失数据

pandas使用浮点值NaN(Not a Number)表示浮点和非浮点数组中的缺失值。
检测可以通过.isnull()方法,此外,Python内置的None值也会被当成NA处理

处理缺失数据有以下方法

  • dropna(根据标签的值中是否有缺失数据对轴标签进行过滤,可以通过调节阈值来调节对缺失值的容忍度)
  • fillna
  • isnull
  • notnull

1.滤除缺失数据

from numpy import nan as NA

data = Series([1, NA, 3.5, NA, 7])

data.dropna()
Out[206]: 
0    1.0
2    3.5
4    7.0
dtype: float64

筛选出非NA项


data[data.notnull()]
Out[208]: 
0    1.0
2    3.5
4    7.0
dtype: float64

dropna默认的 how 参数是 ‘any’, 意为只要有NA,就丢弃全行数据

data = DataFrame([[1,1,1],[1,NA, NA],[NA,NA,NA],[NA,6,3]])

data
Out[210]: 
     0    1    2
0  1.0  1.0  1.0
1  1.0  NaN  NaN
2  NaN  NaN  NaN
3  NaN  6.0  3.0

cleaned = data.dropna()

cleaned
Out[212]: 
     0    1    2
0  1.0  1.0  1.0

如果把 how 参数改为 ‘all’ 就可以仅删除全部都是NA的数据

data.dropna(how = 'all')
Out[214]: 
     0    1    2
0  1.0  1.0  1.0
1  1.0  NaN  NaN
3  NaN  6.0  3.0

如果希望对列进行操作,只要把 axis 参数改成 1 即可

data[4] = NA

data
Out[216]: 
     0    1    2   4
0  1.0  1.0  1.0 NaN
1  1.0  NaN  NaN NaN
2  NaN  NaN  NaN NaN
3  NaN  6.0  3.0 NaN

data.dropna(axis = 1, how = 'all')
Out[217]: 
     0    1    2
0  1.0  1.0  1.0
1  1.0  NaN  NaN
2  NaN  NaN  NaN
3  NaN  6.0  3.0

2.填充缺失数据

首先建立一个有NA值的DataFrame

df = DataFrame(randn(7,3))

df
Out[220]: 
          0         1         2
0 -0.559138  0.118788  1.594997
1  0.128713  0.321041  1.668125
2 -2.242085  0.452067  0.756208
3  0.256609 -1.662545 -0.464385
4 -1.815116  0.055104 -2.114799
5  1.057346  2.427503  1.233321
6 -0.543657 -0.276028  0.948238

df.ix[:4,1] = NA
df.ix[:2,2] = NA

df
Out[226]: 
          0         1         2
0 -0.559138       NaN       NaN
1  0.128713       NaN       NaN
2 -2.242085       NaN       NaN
3  0.256609       NaN -0.464385
4 -1.815116       NaN -2.114799
5  1.057346  2.427503  1.233321
6 -0.543657 -0.276028  0.948238

用字典的方式可以对不同的列用不同的值进行填充

df.fillna({1:0.5,3:-1})
Out[227]: 
          0         1         2
0 -0.559138  0.500000       NaN
1  0.128713  0.500000       NaN
2 -2.242085  0.500000       NaN
3  0.256609  0.500000 -0.464385
4 -1.815116  0.500000 -2.114799
5  1.057346  2.427503  1.233321
6 -0.543657 -0.276028  0.948238

fillna默认是返回新数组,但是也可以通过修改参数的方法,就地修改

_ = df.fillna(0, inplace=True)

此外还可以通过参数method='ffill'等方式,前向填充或者后向填充

fillna参数

  • value
  • method
  • axis
  • inplace
  • limit

层次化索引

层次化索引也是pandas的一项重要功能,它使你能够在一个轴上拥有多个索引级别

data = Series(randn(10), index=[list('aaabbbccdd'), [1,2,3,1,2,3,1,2,3,3]])

data
Out[231]: 
a  1    2.218448
   2    1.177886
   3    0.544273
b  1    0.974565
   2    0.755104
   3   -0.027735
c  1    2.104934
   2   -0.018527
d  3    0.423208
   3    0.577042
dtype: float64
data.index
Out[232]: 
MultiIndex(levels=[['a', 'b', 'c', 'd'], [1, 2, 3]],
           labels=[[0, 0, 0, 1, 1, 1, 2, 2, 3, 3], [0, 1, 2, 0, 1, 2, 0, 1, 2, 2]])
data['b']
Out[233]: 
1    0.974565
2    0.755104
3   -0.027735
dtype: float64

关于重新分级顺序、根据级别汇总统计、使用DataFrame的列、其他有关pandas的话题 在本文中省略

大功告成


疑惑:
1.对DataFrame中某列组成的Series进行索引,如果直接访问单个元素会出错,访问一个切片的元素就没有问题切片

frame3['Ohio'][:-2]
Out[38]: 
2000    1.5
Name: Ohio, dtype: float64

单个元素

frame3['Ohio'][2]

得到KeyError: 2

2.使用reindex同时重新索引行和列出错

frame.reindex(index=['a','b','c','d'], method='ffill',
                columns=states)

得到ValueError: index must be monotonic increasing or decreasing


心得:
看到函数应用与映射一部分,心里一颤,怎么可能这么好用。虽然还没有非常了解,但已经开始相信pandas将会在以后的数据处理工作中起到重要的作用

还差最后一个单元!

Never mind happiness, do your mission

猜你喜欢

转载自blog.csdn.net/yfren1123/article/details/79211334
今日推荐