Python数据分析 笔记3(pandas)

参考书籍 《利用Python进行数据分析(原书第2版)》第5章 pandas入门

pandas是用来处理表格型或异质型数据的。而NumPy则相反,它更适合处理同质型的数值类数组数据。

导入惯例 -> import pandas as pd

5.1 pandas数据结构介绍

两个常用的工具数据结构 -> Series和DataFrame
5.1.1 Series

Series是一种一维的数组型对象,它包含了一个值序列,并且包含了数据标签,称为索引(index)。
可以通过values属性和index属性分别获得Series对象的值和索引。

默认生成的索引是从0到N-1(N是数据的长度)
可以创建一个索引序列,用标签标识每个数据点 => 类似Python的字典,但长度固定且有序,和键不同,其索引值能重复

In [11]: import pandas as pd

In [12]: obj = pd.Series([222,666,888,999])

In [13]: obj
Out[13]:
0    222
1    666
2    888
3    999
dtype: int64

In [14]: obj.values
Out[14]: array([222, 666, 888, 999], dtype=int64)

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

In [16]: obj2 = pd.Series([222,666,888,999], index=['a','b','c','d'])

In [17]: obj2
Out[17]:
a    222
b    666
c    888
d    999
dtype: int64

@使用布尔值对Series进行过滤

In [18]: obj[obj>666]
Out[18]:
2    888
3    999
dtype: int64

@使用一个Python字典生成Series

In [19]: sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}

In [20]: obj3 = pd.Series(sdata)

In [21]: obj3
Out[21]:
Ohio      35000
Texas     71000
Oregon    16000
Utah       5000
dtype: int64

当你把字典传递给Series构造函数时,产生的Series的索引将是排序好的字典键。
你可以将字典键按照你所想要的顺序传递给构造函数,从而使生成的Series的索引顺序符合你的预期:

In [22]: states = ['California', 'Ohio', 'Oregon', 'Texas']

In [23]: obj4 = pd.Series(sdata, index=states)

In [24]: obj4
Out[24]:
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
dtype: float64

说明:因为’California’没有出现在sdata的键中,它对应的值是NaN,这是pandas中标记缺失值或NA值的方式。

In [25]: pd.isnull(obj4)
Out[25]:
California     True
Ohio          False
Oregon        False
Texas         False
dtype: bool

In [26]: obj4.notnull()
Out[26]:
California    False
Ohio           True
Oregon         True
Texas          True
dtype: bool

@Series的自动对齐索引特性 

In [27]: obj3 + obj4
Out[27]:
California         NaN
Ohio           70000.0
Oregon         32000.0
Texas         142000.0
Utah               NaN
dtype: float64

@为Series对象自身和其索引的name属性赋值

In [28]: obj4.name

In [29]: obj4.name = 'population'
In [30]: obj4.name
Out[30]: 'population'

In [31]: obj4.index.name

In [32]: obj4.index.name = 'state'
In [33]: obj4.index.name
Out[33]: 'state'

@修改Series的索引
Series的索引可以通过按位置赋值的方式进行改变,且能重复

In [37]: obj
Out[37]:
7     222
8     666
78    888
7     999
dtype: int64

In [40]: obj.index=[7,8,7,7]
In [41]: obj[7]
Out[41]:
7    222
7    888
7    999
dtype: int64

In [42]: obj[7]=666
In [43]: obj
Out[43]:
7    666
8    666
7    666
7    666
dtype: int64

5.1.2 DataFrame
DataFrame表示的是矩阵的数据表,它包含已排序的列集合,每一列可以是不同的值类型(数值、字符串、布尔值等)。
DataFrame既有行索引也有列索引,它可以被视为一个共享相同索引的Series的字典。在DataFrame中,数据被存储为一个以上的二维块。有多种方式可以构建DataFrame,其中最常用的方式是利用包含等长度列表或NumPy数组的字典来形成DataFrame。
产生的DataFrame会自动为Sereies分配索引,并且列会按照排序的顺序排列:

In [44]: data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'],
    ...:         'year': [2000, 2001, 2002, 2001, 2002, 2003],
    ...:         'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}

In [45]: frame = pd.DataFrame(data)

In [47]: frame
Out[47]:
    state  year  pop
0    Ohio  2000  1.5
1    Ohio  2001  1.7
2    Ohio  2002  3.6
3  Nevada  2001  2.4
4  Nevada  2002  2.9
5  Nevada  2003  3.2

如果你指定了列的顺序,DataFrame的列将会按照指定顺序排列:

In [50]: pd.DataFrame(data, columns=['year', 'state', 'pop'])
Out[50]:
   year   state  pop
0  2000    Ohio  1.5
1  2001    Ohio  1.7
2  2002    Ohio  3.6
3  2001  Nevada  2.4
4  2002  Nevada  2.9
5  2003  Nevada  3.2

如果你传的列不包含在字典中,将会在结果中出现缺失值:

In [53]: frame2 = pd.DataFrame(data, columns=['year', 'state', 'pop', 'debt'],index=['one', 'two', 'three', 'four','five', 'six'])

In [54]: frame2
Out[54]:
       year   state  pop debt
one    2000    Ohio  1.5  NaN
two    2001    Ohio  1.7  NaN
three  2002    Ohio  3.6  NaN
four   2001  Nevada  2.4  NaN
five   2002  Nevada  2.9  NaN
six    2003  Nevada  3.2  NaN

In [55]: frame2.columns
Out[55]: Index(['year', 'state', 'pop', 'debt'], dtype='object')

DataFrame中的一列,可以按字典型标记或属性那样检索为Series。
注意:frame[colunm]对于任意列名均有效,但是frame.column只在列名是有效的Python变量名时有效。所以新建列只能用前者方法。

@给DataFrame的列赋值

列的引用是可以修改的。例如,1)空的’debt’列可以赋值为标量值 或 和DataFrame的长度相匹配的数组:

eg1: frame2['debt'] = 16.5
eg2: frame2['debt'] = np.arange(6.)

2)还可以通过Series给一列赋值,空缺的地方填充缺失值。

注意:从DataFrame中选取的列是数据的视图,而不是拷贝。因此,对Series的修改会映射到DataFrame中。
如果需要复制,则应当显式地使用Series的copy方法。

In [58]: val = pd.Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five'])
In [59]: frame2['debt'] = val
In [60]: frame2
Out[60]:
        year    state  pop  debt
one     2000     Ohio  1.5  NaN
two     2001     Ohio  1.7  -1.2
three   2002     Ohio  3.6  NaN
four    2001   Nevada  2.4  -1.5
five    2002   Nevada  2.9  -1.7

如果被赋值的列并不存在,则会生成一个新的列。del关键字 => 对DataFrame删除列

In [56]: frame2['eastern'] = frame2.state == 'Ohio'

In [57]: frame2
Out[57]:
       year   state  pop debt  eastern
one    2000    Ohio  1.5  NaN     True
two    2001    Ohio  1.7  NaN     True
three  2002    Ohio  3.6  NaN     True
four   2001  Nevada  2.4  NaN    False
five   2002  Nevada  2.9  NaN    False
six    2003  Nevada  3.2  NaN    False

In [58]: frame2.columns
Out[58]: Index(['year', 'state', 'pop', 'debt', 'eastern'], dtype='object')

In [59]: del frame2['eastern']

In [60]: frame2.columns
Out[60]: Index(['year', 'state', 'pop', 'debt'], dtype='object')

@将包含字典的嵌套字典赋值给DataFrame
=> pandas会将字典的键作为列,将内部字典的键作为行索引:

In [1]: pop = {'Nevada': {2001: 2.4, 2002: 2.9},
   ...: 'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}

In [3]: frame3 = pd.DataFrame(pop)
In [4]: frame3
Out[4]:
      Nevada  Ohio
2001     2.4   1.7
2002     2.9   3.6
2000     NaN   1.5

如果DataFrame的索引和列拥有name属性,则这些name属性也会被显示:

In [5]: frame3.index.name = 'year'; frame3.columns.name = 'state'
In [6]: frame3
Out[6]:
state  Nevada  Ohio
year
2001      2.4   1.7
2002      2.9   3.6
2000      NaN   1.5

DataFrame的values属性会将包含在DataFrame中的数据以二维ndarray的形式返回:

In [7]: frame3.values
Out[7]:
array([[2.4, 1.7],
       [2.9, 3.6],
       [nan, 1.5]])

5.1.3 索引对象
pandas中的索引对象是用于存储轴标签和其他元数据的(例如轴名称或标签)。
在构造Series或DataFrame时,你所使用的任意数组或标签序列都可以在内部转换为索引对象:

In [24]: obj = pd.Series(range(3), index=['a', 'b', 'c'])
In [25]: index = obj.index
In [26]: index
Out[26]: Index(['a', 'b', 'c'], dtype='object')

索引对象是不可变的,因此无法修改索引对象:
index[1] = 'd' =>  TypeError: Index does not support mutable operations

注意:使用 pd.Series(range(3), index=['a', 'd', 'c']) 看似改变达到改变的目的,实际是改变了obj.index指向的数组,可以使用id命令查看新的索引地址id(obj.index) 和之前的索引地址id(index),会发现二者不同。

In [28]: index1 = obj.index

In [29]: obj = pd.Series(range(3), index=['a', 'd', 'c'])

In [30]: obj
Out[30]:
a    0
d    1
c    2
dtype: int64

In [31]: id(obj.index)
Out[31]: 2334912679112

In [32]: id(index)
Out[32]: 2334912240584

可以使用pd.Index() 创建索引对象=>  eg: pd.Index(np.arange(3))

pandas索引对象长度固定,且可以包含重复标签。根据重复标签进行筛选,会选取所有重复标签对应的数据。

每个索引都有一些集合逻辑的方法和属性:

一些索引对象的方法和属性

 

5.2 基本功能

5.2.1 重建索引
reindex -> 该方法用于创建一个符合新索引的新对象

@reindex与Series
Series调用reindex方法时,会将数据按照新的索引进行排列,如果某个索引值之前并不存在,则会引入缺失值

In [34]: obj = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])
In [35]: obj
Out[35]:
d    4.5
b    7.2
a   -5.3
c    3.6
dtype: float64

In [36]: obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])
In [38]: obj2
Out[38]:
a   -5.3
b    7.2
c    3.6
d    4.5
e    NaN
dtype: float64

对于顺序数据,比如时间序列,在重建索引时可能会需要进行插值。method可选参数允许使用诸如ffill等方法在重建索引时插值,ffill方法会将值前向填充。

In [40]: obj3 = pd.Series(['blue', 'purple', 'yellow'], index=[0, 2, 4])
In [41]: obj3
Out[41]:
0      blue
2    purple
4    yellow
dtype: object

In [42]: obj3.reindex(range(6), method='ffill')
Out[42]:
0      blue
1      blue
2    purple
3    purple
4    yellow
5    yellow
dtype: object

@reindex与DataFrame
DataFrame中,reindex可以改变行索引和列索引。1)当仅传入一个序列时,结果中的行会重建索引

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

In [48]: frame
Out[48]:
   Ohio  Texas  California
a     0      1           2
c     3      4           5
d     6      7           8

2)列可以使用columns关键字重建索引

In [49]: states = ['Texas', 'Utah', 'California']

In [50]: frame.reindex(columns=states)
Out[50]:
   Texas  Utah  California
a      1   NaN           2
c      4   NaN           5
d      7   NaN           8

3)行列索引同时改变

In [51]: frame.reindex(['a', 'b', 'c', 'd'])
Out[51]:
   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

5.2.2 轴向上删除条目

drop方法会返回一个含有指示值或轴向上删除值的新对象。

【例】删除Series的行

In [3]: obj = pd.Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e'])

In [4]: obj.drop('c')
Out[4]:
a    0.0
b    1.0
d    3.0
e    4.0
dtype: float64

In [5]: obj
Out[5]:
a    0.0
b    1.0
c    2.0
d    3.0
e    4.0
dtype: float64

In [6]: new_obj = obj.drop('c')

In [7]: new_obj
Out[7]:
a    0.0
b    1.0
d    3.0
e    4.0
dtype: float64

【例】删除DataFrame的行/列

在调用drop时使用标签序列会根据行标签删除值(轴0)
 

In [8]: data = pd.DataFrame(np.arange(16).reshape((4, 4)),
   ...: index=['Ohio', 'Colorado', 'Utah', 'New York'],
   ...: columns=['one', 'two', 'three', 'four'])
In [9]: data
Out[9]:
          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

In [10]: data.drop(['Colorado', 'Ohio'])
Out[10]:
          one  two  three  four
Utah        8    9     10    11
New York   12   13     14    15
In [11]: data
Out[11]:
          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

通过传递axis=1或axis='columns’来从列中删除值
 

In [12]: data.drop('two', axis=1)
Out[12]:
          one  three  four
Ohio        0      2     3
Colorado    4      6     7
Utah        8     10    11
New York   12     14    15
In [13]: data
Out[13]:
          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

In [14]: data.drop(['two', 'four'], axis='columns')
Out[14]:
          one  three
Ohio        0      2
Colorado    4      6
Utah        8     10
New York   12     14

drop方法带上inplace属性,它会清除被删除的数据,直接操作原对象而不是返回新对象。

In [15]: obj
Out[15]:
a    0.0
b    1.0
c    2.0
d    3.0
e    4.0
dtype: float64

In [16]: obj.drop('c', inplace=True)

In [17]: obj
Out[17]:
a    0.0
b    1.0
d    3.0
e    4.0
dtype: float64

In [18]: data
Out[18]:
          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

In [19]: data.drop(['two', 'four'], axis='columns',inplace=True)

In [20]: data
Out[20]:
          one  three
Ohio        0      2
Colorado    4      6
Utah        8     10
New York   12     14

5.2.3 索引、选择与过滤

(1)Series

Series的索引(obj[...])与NumPy数组索引的功能类似,不过Series的索引值可以不仅仅是整数。

In [22]: obj = pd.Series(np.arange(4.), index=['a', 'b', 'c', 'd'])
In [23]: obj
Out[23]:
a    0.0
b    1.0
c    2.0
d    3.0
dtype: float64

In [24]: obj['b']
Out[24]: 1.0
In [25]: obj[1]
Out[25]: 1.0

In [26]: obj[:3]
Out[26]:
a    0.0
b    1.0
c    2.0
dtype: float64
In [27]: obj[2:4]
Out[27]:
c    2.0
d    3.0
dtype: float64

In [28]: obj[['b', 'a', 'd']]
Out[28]:
b    1.0
a    0.0
d    3.0
dtype: float64
In [30]: obj[[1, 0, 3]]
Out[30]:
b    1.0
a    0.0
d    3.0
dtype: float64

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

注意:Series使用索引进行切片是包含尾部的:

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

使用这些方法设值时会修改Series相应的部分,eg: obj['b':'c'] = 5

(2)DataFrame使用单个值或序列,可以从DataFrame中索引出一个或多个列

In [35]: data = pd.DataFrame(np.arange(16).reshape((4, 4)),
    ...: index=['Ohio', 'Colorado', 'Utah', 'New York'],
    ...: columns=['one', 'two', 'three', 'four'])

In [36]: data
Out[36]:
          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

In [37]: data['two']
Out[37]:
Ohio         1
Colorado     5
Utah         9
New York    13
Name: two, dtype: int32

In [39]: data[['three', 'one']]
Out[39]:
          three  one
Ohio          2    0
Colorado      6    4
Utah         10    8
New York     14   12

这种索引方式也有特殊案例。
【例1】可以根据一个布尔值数组切片或选择数据

In [45]: data[:2]
Out[45]:
          one  two  three  four
Ohio        0    1      2     3
Colorado    4    5      6     7

In [46]: data[2:]
Out[46]:
          one  two  three  four
Utah        8    9     10    11
New York   12   13     14    15

In [47]: data[data['three'] > 5]
Out[47]:
          one  two  three  four
Colorado    4    5      6     7
Utah        8    9     10    11
New York   12   13     14    15

注意:data[:2]是行选择语法,但data[2]不是 -> KeyError: 2

【例2】使用"布尔值DataFrame"进行索引(类似NumPy二维数组),其中"布尔值DataFrame"可以是对标量值进行比较产生的

In [48]: data[data < 5]
Out[48]:
          one  two  three  four
Ohio      0.0  1.0    2.0   3.0
Colorado  4.0  NaN    NaN   NaN
Utah      NaN  NaN    NaN   NaN
New York  NaN  NaN    NaN   NaN

In [49]: data < 5
Out[49]:
            one    two  three   four
Ohio       True   True   True   True
Colorado   True  False  False  False
Utah      False  False  False  False
New York  False  False  False  False

In [52]: data[data < 5] = 0
In [53]: data
Out[53]:
          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

@使用loc和iloc选择数据
=> 使用轴标签(loc)或整数标签(iloc)以NumPy风格的语法从DataFrame中选出数组的行和列的子集。

loc => 用于标签,iloc => 用于整数

使用loc选出单行单列的数据

In [56]: data.loc['Colorado', 'two']
Out[56]: 5

使用loc选出单行多列的数据

In [57]: data.loc['Colorado', ['two', 'three']]
Out[57]:
two      5
three    6
Name: Colorado, dtype: int32

使用iloc选出单行单列的数据

In [58]: data.iloc[1,1]
Out[58]: 5

使用iloc选出单行多列的数据

In [59]: data.iloc[2, [3, 0, 1]]
Out[59]:
four    11
one      8
two      9
Name: Utah, dtype: int32

使用iloc选出单行的完整数据

In [60]: data.iloc[2]
Out[60]:
one       8
two       9
three    10
four     11
Name: Utah, dtype: int32

指定的行列数据

In [61]: data.iloc[[1, 2], [3, 0, 1]]
Out[61]:
          four  one  two
Colorado     7    0    5
Utah        11    8    9

使用loc结合切片选出行

In [62]: data.loc[:'Utah', 'two']
Out[62]:
Ohio        0
Colorado    5
Utah        9
Name: two, dtype: int32

使用iloc结合过滤列的值选出行

In [63]: data.iloc[:, :3][data.three > 5]
Out[63]:
          one  two  three
Colorado    0    5      6
Utah        8    9     10
New York   12   13     14

5.2.5 算术和数据对齐
当你将对象相加时,
s1 + s2 -> Series如果存在索引对不同,返回索引对的并集
df1 + df2 -> DataFrame行和列上都会执行对齐

没有交叠的标签位置上,内部数据对齐会产生缺失值。

@使用填充值的算术方法
在两个不同的索引化对象之间进行算术操作时,可以使用特殊填充值。
比如当轴标签在一个对象中存在,在另一个对象中不存在时,将缺失值填充为0:
在df1上使用add方法,将df2和一个fill_value作为参数传入:df1.add(df2, fill_value=0)

@DataFrame和Series间的操作
DataFrame和Series间的算术操作与NumPy中不同维度数组间的操作类似。
首先,考虑二维数组和其中一行的运算:

In [3]: arr = np.arange(12).reshape((3, 4))

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

In [5]: arr[0]
Out[5]: array([0, 1, 2, 3])

In [6]: arr - arr[0]
Out[6]:
array([[0, 0, 0, 0],
       [4, 4, 4, 4],
       [8, 8, 8, 8]])

In [7]: arr + arr[0]
Out[7]:
array([[ 0,  2,  4,  6],
       [ 4,  6,  8, 10],
       [ 8, 10, 12, 14]])

当我们从arr中减去/加上arr[0]时,在每一行都进行了操作 => 广播机制
DataFrame和Series间的操作是类似的。

In [14]: frame = pd.DataFrame(np.arange(12.).reshape((4, 3)),columns=list('bde'),index=['Utah', 'Ohio', 'Texas', 'Oregon'])

In [15]: series = frame.iloc[0]

In [16]: frame
Out[16]:
          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

In [17]: series
Out[17]:
b    0.0
d    1.0
e    2.0
Name: Utah, dtype: float64

In [18]: frame - series
Out[18]:
          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的索引中,则对象会重建索引并形成联合:

In [19]: series2 = pd.Series(range(3), index=['b', 'e', 'f'])

In [20]: frame + series2
Out[20]:
          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

In [21]: frame - series2
Out[21]:
          b   d     e   f
Utah    0.0 NaN   1.0 NaN
Ohio    3.0 NaN   4.0 NaN
Texas   6.0 NaN   7.0 NaN
Oregon  9.0 NaN  10.0 NaN

如果要在列上进行广播(即以DataFrame的列作为单位进行操作),使用算术方法 frame.sub(series3, axis='index')。
说明:传递的axis值是用于匹配轴的。例子是在DataFrame的行索引上对行匹配(axis='index’或axis=0),并进行广播。

In [22]: series3 = frame['d']

In [23]: series3
Out[23]:
Utah       1.0
Ohio       4.0
Texas      7.0
Oregon    10.0
Name: d, dtype: float64

In [24]: frame.sub(series3, axis='index')
Out[24]:
          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

5.2.6 函数应用和映射
NumPy的通用函数(逐元素数组方法)对pandas对象也有效。
eg: frame = pd.DataFrame(np.random.randn(2, 3), columns=list('bde'),index=['Utah', 'Ohio'])
np.abs(frame) => 每个元素取绝对值

@DataFrame的apply方法
将函数应用到一行或一列的一维数组上 -> DataFrame的apply方法可以实现
【例】找到每列的极值

In [6]: frame = pd.DataFrame(np.arange(12).reshape(4, 3), columns=list('bde'),index=['Utah', 'Ohio', 'Texas', 'Oregon'
   ...: ])

In [7]: f = lambda x: x.max() - x.min()

In [8]: frame.apply(f)
Out[8]:
b    9
d    9
e    9
dtype: int64

In [9]: frame
Out[9]:
        b   d   e
Utah    0   1   2
Ohio    3   4   5
Texas   6   7   8
Oregon  9  10  11

这里的函数f,可以计算Series最大值和最小值的差,会被frame中的每一列调用一次。
结果是一个以frame的列作为索引的Series。
如果你传递axis='columns'给apply函数,函数将会被每行调用一次:

In [14]: frame.apply(f,axis='columns')
Out[14]:
Utah      2
Ohio      2
Texas     2
Oregon    2
dtype: int64

传递给apply的函数并不一定要返回一个标量值,也可以返回带有多个值的Series。

In [16]: frame
Out[16]:
               b         d         e
Utah    0.154905  0.849439  0.213608
Ohio    0.454309  2.043070 -1.523084
Texas   1.618059  0.051750  0.023853
Oregon -0.673935 -0.373966  2.711141

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

In [18]: frame.apply(f)
Out[18]:
            b         d         e
min -0.673935 -0.373966 -1.523084
max  1.618059  2.043070  2.711141

In [20]: frame.apply(f,axis='columns')
Out[20]:
             min       max
Utah    0.154905  0.849439
Ohio   -1.523084  2.043070
Texas   0.023853  1.618059
Oregon -0.673935  2.711141

@DataFrame的applymap方法
逐元素使用Python函数 -> DataFrame的applymap方法可以实现

【例】格式化字符串
 

In [21]: format = lambda x: '%.2f' % x

In [22]: frame.applymap(format)
Out[22]:
            b      d      e
Utah     0.15   0.85   0.21
Ohio     0.45   2.04  -1.52
Texas    1.62   0.05   0.02
Oregon  -0.67  -0.37   2.71

注:使用applymap作为函数名是因为Series有map方法,可以将一个逐元素的函数应用到Series上。

In [24]: frame['e'].map(format)
Out[24]:
Utah       0.21
Ohio      -1.52
Texas      0.02
Oregon     2.71
Name: e, dtype: object

5.2.7 排序和排名

@sort_index方法排序 ->使用sort_index方法,返回一个新的、排序好的对象

(1)Series

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

In [27]: obj
Out[27]:
d    0
a    1
b    2
c    3
dtype: int64

(2)DataFrame
在DataFrame中,可以在各个轴上按索引排序。
1)行索引升序排序

In [30]: frame = pd.DataFrame(np.arange(12).reshape((3, 4)),index=['three', 'one','four'],columns=['d', 'a', 'b', 'c'])
In [31]: frame.sort_index()
Out[31]:
       d  a   b   c
four   8  9  10  11
one    4  5   6   7
three  0  1   2   3


In [32]: frame.sort_index(axis=1)
Out[32]:
       a   b   c  d
three  1   2   3  0
one    5   6   7  4
four   9  10  11  8

数据默认会升序排序,也可以按照降序排序。
2)列索引降序排序

In [33]: frame.sort_index(axis=1, ascending=False)
Out[33]:
       d   c   b  a
three  0   3   2  1
one    4   7   6  5
four   8  11  10  9

@sort_values方法排序

(1)Series
根据Series的值进行排序,使用sort_values方法。

In [34]: obj = pd.Series([4, 7, -3, 2])

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

默认情况下,无论升序、降序 所有的缺失值(np.nan)都会被排序至Series的尾部:
(2)DataFrame
使用一列或多列作为键对DataFrame排序时。
=> 传递一个或多个列名给sort_values的可选参数by

In [38]: frame = pd.DataFrame({'b': [4, 7, -3, 2], 'a': [0, 1, 0, 1]})
In [39]: frame.sort_values(by='b')
Out[39]:
   b  a
2 -3  0
3  2  1
0  4  0
1  7  1

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

In [41]: frame.sort_values(by=['a', 'b'])
Out[41]:
   b  a
2 -3  0
0  4  0
3  2  1
1  7  1

@rank方法排名

(1)Series
Series和DataFrame的rank方法是实现排名的方法,1)默认情况下,rank通过将平均排名分配到每个组来打破平级关系:

In [42]: obj = pd.Series([7, -5, 7, 4, 2, 0, 4])

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

说明:对条目0和2设置的名次为6.5,(6+7)/2 =>平均排名6.5

2)排名也可以根据他们在数据中的观察顺序进行分配

In [217]: obj.rank(method='first')
Out[217]:
0     6.0
1     1.0
2     7.0
3     4.0
4     3.0
5     2.0
6     5.0
dtype: float64

说明:对条目0和2设置的名次为6和7,而不是之前的平均排名6.5,是因为在数据中标签0在标签2的前面。

3)按降序排名:

In [44]: obj.rank(ascending=False, method='max')
Out[44]:
0    2.0
1    7.0
2    2.0
3    4.0
4    5.0
5    6.0
6    4.0
dtype: float64

In [45]: obj.rank(ascending=False, method='min')
Out[45]:
0    1.0
1    7.0
2    1.0
3    3.0
4    5.0
5    6.0
6    3.0
dtype: float64

(2)DataFrameDataFrame可以对行或列计算排名。

In [46]: frame = pd.DataFrame({'b': [4.3, 7, -3, 2], 'a': [0, 1, 0, 1],'c': [-2, 5, 8, -2.5]})

In [47]: frame
Out[47]:
     b  a    c
0  4.3  0 -2.0
1  7.0  1  5.0
2 -3.0  0  8.0
3  2.0  1 -2.5

In [48]: frame.rank()
Out[48]:
     b    a    c
0  3.0  1.5  2.0
1  4.0  3.5  3.0
2  1.0  1.5  4.0
3  2.0  3.5  1.0

In [49]: frame.rank(axis='columns')
Out[49]:
     b    a    c
0  3.0  2.0  1.0
1  3.0  1.0  2.0
2  1.0  2.0  3.0
3  3.0  2.0  1.0

5.2.8 含有重复标签的轴索引
尽管很多pandas函数(比如reindex)需要标签是唯一的,但并不强制。
索引的is_unique属性可以告诉你它的标签是否唯一 -> eg: obj.index.is_unique
Series根据一个标签索引多个条目会返回一个序列,而单个条目会返回标量值。
相同的逻辑可以拓展到在DataFrame中进行行索引。

5.3 描述性统计的概述与计算

pandas对象装配了一个常用数学、统计学方法的集合。

(1)归约或汇总统计的类别

调用DataFrame的sum方法返回一个按列加和的Series(对每个列向量求和),传入axis='columns’或axis=1,按行加和

In [3]: df = pd.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'])

In [4]: df
Out[4]:
    one  two
a  1.40  NaN
b  7.10 -4.5
c   NaN  NaN
d  0.75 -1.3

In [5]: df.sum()
Out[5]:
one    9.25
two   -5.80
dtype: float64

In [6]: df.sum(axis='columns')
Out[6]:
a    1.40
b    2.60
c    0.00
d   -0.55
dtype: float64

除非整个切片上(在本例中是行或列)都是NA,否则NA值是被自动排除的。可以通过禁用skipna来实现不排除NA值。

In [7]: df.mean(axis='columns', skipna=False)
Out[7]:
a      NaN
b    1.300
c      NaN
d   -0.275
dtype: float64

一些方法,返回间接统计信息,比如idxmin和idxmax,最小值或最大值的索引值

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

(2)积累型方法

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

(3)describe一次性产生多个汇总统计

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

5.3.1 相关性和协方差

Series的corr方法计算的是两个Series中重叠的、非NA的、按索引对齐的值的相关性。相应地,cov计算的是协方差。

使用DataFrame的corrwith方法,你可以计算出DataFrame中的行或列与另一个序列或DataFrame的相关性。该方法传入一个Series时,会返回一个含有为每列计算相关性值的Series;传入一个DataFrame时,会计算匹配到列名的相关性数值。

5.3.2 唯一值、计数和成员属性
@unique给出Series中的唯一值

In [251]: obj = pd.Series(['c', 'a', 'd', 'a', 'a', 'b', 'b', 'c', 'c'])
In [252]: uniques = obj.unique()
In [253]: uniques
Out[253]: array(['c', 'a', 'd', 'b'], dtype=object)

唯一值并不一定按照排序好的顺序返回,可以用uniques. sort()进行排序。

@value_counts计算Series包含的值的个数

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

返回的Series会按照数量降序排序。不排序带上sort=False。

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

@isin执行向量化的成员属性检查,还可以将数据集以Series或DataFrame一列的形式过滤为数据集的值子集。

In [256]: obj
Out[256]:
0     c
1     a
2     d
3     a
4     a
5     b
6     b
7     c
8     c
dtype: object
In [257]: mask = obj.isin(['b', 'c'])
In [258]: mask
Out[258]:
0      True
1     False
2     False
3     False
4     False
5      True
6      True
7      True
8      True
dtype: bool
In [259]: obj[mask]
Out[259]:
0     c
5     b
6     b
7     c
8     c
dtype: object

@计算DataFrame多个相关列的直方图

将pandas.value_counts传入DataFrame的apply函数可以得到如下结果,行标签是所有列中出现的不同值,数值则是这些不同值在每个列中出现的次数。

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

In [14]: data
Out[14]:
   Qu1  Qu2  Qu3
0    1    2    1
1    3    3    5
2    4    1    2
3    3    2    4
4    4    3    4

In [15]: result = data.apply(pd.value_counts).fillna(0)

In [16]: result
Out[16]:
   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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章