pandas基础--基本功能

pandas含有是数据分析工作变得更快更简单的高级数据结构和操作工具,是基于numpy构建的。

本章节的代码引入pandas约定为:import pandas as pd,另外import numpy as np也会用到。

官方介绍:pandas - Python Data Analysis Library (pydata.org)

5 基本功能

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

5.1 重新索引

重新索引reindex,其作用是创建一个适应新索引的新对象。调用reindex将会根据新索引进行重排,如果某个索引值当前不存在,就引入缺失值。

 1 >>> obj = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])
 2 >>> obj
 3 d    4.5
 4 b    7.2
 5 a   -5.3
 6 c    3.6
 7 dtype: float64
 8 >>> obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e']) 
 9 >>> obj2
10 a   -5.3
11 b    7.2
12 c    3.6
13 d    4.5
14 e    NaN
15 dtype: float64
16 >>> obj.reindex(['a', 'b', 'c', 'd', 'e'], fill_value=0) 
17 a   -5.3
18 b    7.2
19 c    3.6
20 d    4.5
21 e    0.0
22 dtype: float64
23 >>>

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

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

下表是可用的method选项。

方法 说明
ffill或pad 前向填充(或搬运)值
bfill或backfill 后向填充(或搬运)值

对于DataFrame,reindex可以修改(行)索引、列,或两个都修改,如果仅传入一个序列,则会重新索引行。

 1 >>> frame = pd.DataFrame(np.arange(9).reshape((3, 3)), index=['a', 'c', 'd'], columns=['Ohio', 'Texas', 'California'])
 3 >>> frame
 4    Ohio  Texas  California
 5 a     0      1           2
 6 c     3      4           5
 7 d     6      7           8
 8 >>> frame2 = frame.reindex(['a', 'b', 'c', 'd'])  #重新索引行
 9 >>> frame2
10    Ohio  Texas  California
11 a   0.0    1.0         2.0
12 b   NaN    NaN         NaN
13 c   3.0    4.0         5.0
14 d   6.0    7.0         8.0
15 >>> states = ['Texas', 'Utah', 'California']
16 >>> frame.reindex(columns=states)  #使用columns关键字重新索引列
17    Texas  Utah  California
18 a      1   NaN           2
19 c      4   NaN           5
20 d      7   NaN           8
21 >>> frame.reindex(index=['a', 'b', 'c', 'd'], method='ffill')                 
22    Ohio  Texas  California
23 a     0      1           2
24 b     0      1           2
25 c     3      4           5
26 d     6      7           8

下表是reindex函数的各参数及说明。

参数 说明
index 用作索引的新序列,既可以是Index实例,也可以是其他序列型的python数据结构,Index会被完全使用,就像没有任何复制一样
method 插值(填充)方式,具体常见之前的表格
fill_value 在重新索引的过程中,需要引入缺失值时使用的替代值
limit 前向或后向填充时的最大填充量
level 在MultiIndex的指定级别上匹配简单索引,否则选取其子集
copy 默认为True,无论无何都复制,否则为False,则新旧相等就不复制

5.2 丢弃指定轴上的项

丢弃某条轴上的一个或多个项只要有一个索引数组或列表即可完成。由于需要执行一些数据整理和集合逻辑,所以drop方法返回的是一个在指定轴上删除了指定值的新对象。

 1 >>> obj = pd.Series(np.arange(5), index=['a', 'b', 'c', 'd', 'e'])
 2 >>> new_obj = obj.drop('c')
 3 >>> new_obj
 4 a    0
 5 b    1
 6 d    3
 7 e    4
 8 dtype: int32
 9 >>> obj.drop(['d', 'c'])
10 a    0
11 b    1
12 e    4
13 dtype: int32

对于DataFrame,可以删除任意轴上的索引值。

 1 >>> data = pd.DataFrame(np.arange(16).reshape((4, 4)), index=['Oh', 'Co', 'Ut', 'New'], columns=['one', 'two', 'three', 'four'])
 2 >>> data
 3      one  two  three  four
 4 Oh     0    1      2     3
 5 Co     4    5      6     7
 6 Ut     8    9     10    11
 7 New   12   13     14    15
 8 >>> data.drop('two', axis=1)
 9      one  three  four
10 Oh     0      2     3
11 Co     4      6     7
12 Ut     8     10    11
13 New   12     14    15
14 >>> data.drop(['two', 'four'], axis=1) 
15      one  three
16 Oh     0      2
17 Co     4      6
18 Ut     8     10
19 New   12     14

5.3 索引、选取和过滤

5.3.1 Series索引

Series索引(obj[…])的工作方式类似于NumPy数组的索引,只不过Series的索引值不是整数。

 1 >>> obj = pd.Series(np.arange(4), index=['a', 'b', 'c', 'd'])
 2 >>> obj['b'] 
 3 1
 4 >>> obj[1]   
 5 1
 6 >>> obj[2:4] 
 7 c    2
 8 d    3
 9 dtype: int32
10 >>> obj[['b', 'a', 'd']] 
11 b    1
12 a    0
13 d    3
14 dtype: int32
15 >>> obj[[1, 3]]          
16 b    1
17 d    3
18 dtype: int32
19 >>> obj[obj < 2] 
20 a    0
21 b    1
22 dtype: int32
23 >>>

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

 1 >>> obj
 2 a    0
 3 b    1
 4 c    2
 5 d    3
 6 dtype: int32
 7 >>> obj['b':'d']
 8 b    1
 9 c    2
10 d    3
11 dtype: int32
12 >>> obj['b':'d'] = 5  #赋值操作
13 >>> obj
14 a    0
15 b    5
16 c    5
17 d    5
18 dtype: int32

5.3.2 DataFrame索引

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

 1 >>> data
 2      one  two  three  four
 3 Oh     0    1      2     3
 4 Co     4    5      6     7
 5 Ut     8    9     10    11
 6 New   12   13     14    15
 7 >>> data['two'] 
 8 Oh      1
 9 Co      5
10 Ut      9
11 New    13
12 Name: two, dtype: int32
13 >>> data[['three', 'one']] 
14      three  one
15 Oh       2    0
16 Co       6    4
17 Ut      10    8
18 New     14   12
19 >>> data[:2]   # 通过切片选取行
20     one  two  three  four
21 Oh    0    1      2     3
22 Co    4    5      6     7
23 >>> data[data['three'] > 5]  #通过布尔型数组选取行
24      one  two  three  four
25 Co     4    5      6     7
26 Ut     8    9     10    11
27 New   12   13     14    15
28 >>> data < 5
29        one    two  three   four
30 Oh    True   True   True   True
31 Co    True  False  False  False
32 Ut   False  False  False  False
33 New  False  False  False  False
34 >>> data[data < 5] = 0  #通过布尔型数组选取行
35 >>> data
36      one  two  three  four
37 Oh     0    0      0     0
38 Co     0    5      6     7
39 Ut     8    9     10    11
40 New   12   13     14    15
41 >>>

DataFrame的索引选项如下表所示:

类型 说明
obj[val] 选取DataFrame的单个列或一组列,在一些特殊情况下会比较方便:布尔型数组(过滤行)、切片(行切片)、布尔型DataFrame(根据条件设置值)
reindex方法 将一个或多个轴匹配到新索引
xs 根据标签选取单行或单列,返回一个Series

5.4 算术运算和数据对齐

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

自动的数据对齐操作在不重叠的索引处引入了NaN值,缺失值会在算术运算过程中传播。

 1 >>> s1 = pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd']) 
 2 >>> s2 = pd.Series([5, 6, 7, 8], index = ['a', 'c', 'e', 'f'])
 3 >>> s1 + s2  #加法操作
 4 a    6.0
 5 b    NaN
 6 c    9.0
 7 d    NaN
 8 e    NaN
 9 f    NaN
10 dtype: float64
11 >>>

对于DataFrame,对齐操作会同时发生在行和列上。它们相加后会返回一个新的DataFrame,其索引和列为原来那两个DataFrame的并集

 1 >>> df1 = pd.DataFrame(np.arange(9).reshape((3, 3)), columns=list('bcd'), index=['one', 'two', 'three'])
 3 >>> df2 = pd.DataFrame(np.arange(4).reshape((2, 2)), columns=list('be'), index=['two', 'four'])
 4 >>> df1
 5        b  c  d
 6 one    0  1  2
 7 two    3  4  5
 8 three  6  7  8
 9 >>> df2
10       b  e
11 two   0  1
12 four  2  3
13 >>> df1 + df2  #相加
14          b   c   d   e
15 four   NaN NaN NaN NaN
16 one    NaN NaN NaN NaN
17 three  NaN NaN NaN NaN
18 two    3.0 NaN NaN NaN
19 >>>

5.5 在算术方法中填充值

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

 1 >>> df1
 2        b  c  d
 3 one    0  1  2
 4 two    3  4  5
 5 three  6  7  8
 6 >>> df2
 7       b  e
 8 two   0  1
 9 four  2  3
10 >>> df1.add(df2, fill_value=0)
11          b    c    d    e
12 four   2.0  NaN  NaN  3.0
13 one    0.0  1.0  2.0  NaN
14 three  6.0  7.0  8.0  NaN
15 two    3.0  4.0  5.0  1.0
16 >>> df1.add(df2, fill_value=1) 
17          b    c    d    e
18 four   3.0  NaN  NaN  4.0
19 one    1.0  2.0  3.0  NaN
20 three  7.0  8.0  9.0  NaN
21 two    3.0  5.0  6.0  2.0
22 >>> df1.reindex(columns=df2.columns, fill_value=0) 
23        b  e
24 one    0  0
25 two    3  0
26 three  6  0

灵活的算术方法如下表所示:

方法 说明
add 用于加法(+)的方法
sub 用于减法(-)的方法
div 用于除法(/)的方法
mul 用于乘法(*)的方法

5.6 DataFrame和Series之间的运算

DataFrame和Series之间的运算由明确的规定。例如计算一个二维数组与其某行之间的差。

 1 >>> arr = np.arange(12).reshape((3, 4))
 2 >>> arr
 3 array([[ 0,  1,  2,  3],
 4        [ 4,  5,  6,  7],
 5        [ 8,  9, 10, 11]])
 6 >>> arr[0]
 7 array([0, 1, 2, 3])
 8 >>> arr - arr[0]  #会进行广播
 9 array([[0, 0, 0, 0],
10        [4, 4, 4, 4],
11        [8, 8, 8, 8]])

DataFrame和Series之间的运算会将Series的索引匹配到DataFrame的列,然后沿着一直向下广播。

 1 >>> frame = pd.DataFrame(np.arange(12).reshape((4, 3)), columns=list('bde'), index=['Ut', 'Oh', 'Te', 'Or'])
 2 >>> frame
 3     b   d   e
 4 Ut  0   1   2
 5 Oh  3   4   5
 6 Te  6   7   8
 7 Or  9  10  11
 8 >>> series = pd.Series(np.arange(3), index=['b', 'd', 'e'])
 9 >>> series
10 b    0
11 d    1
12 e    2
13 dtype: int32
14 >>> frame - series 
15     b  d  e
16 Ut  0  0  0
17 Oh  3  3  3
18 Te  6  6  6
19 Or  9  9  9
20 >>>

如果某个索引值在DataFrame的列或Series的索引中找不到,则参与运算的两个对象就会被重新索引以形成并集

 1 >>> series2 = pd.Series(range(3), index=list('bef'))
 2 >>> series2
 3 b    0
 4 e    1
 5 f    2
 6 dtype: int64
 7 >>> frame
 8     b   d   e
 9 Ut  0   1   2
10 Oh  3   4   5
11 Te  6   7   8
12 Or  9  10  11
13 >>> frame + series2
14       b   d     e   f
15 Ut  0.0 NaN   3.0 NaN
16 Oh  3.0 NaN   6.0 NaN
17 Te  6.0 NaN   9.0 NaN
18 Or  9.0 NaN  12.0 NaN
19 >>>

如果希望匹配行且在列上广播,则必须使用算术运算方法。

 1 >>> series3 = frame['d']
 2 >>> frame
 3     b   d   e
 4 Ut  0   1   2
 5 Oh  3   4   5
 6 Te  6   7   8
 7 Or  9  10  11
 8 >>> series3
 9 Ut     1
10 Oh     4
11 Te     7
12 Or    10
13 Name: d, dtype: int32
14 >>> frame.sub(series3, axis=0) 
15     b  d  e
16 Ut -1  0  1
17 Oh -1  0  1
18 Te -1  0  1
19 Or -1  0  1

5.7 函数应用和映射

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

 1 >>> frame
 2     b  d   e
 3 Ut  0 -3   2
 4 Oh  3 -3   5
 5 Te  6 -3   8
 6 Or  9 -3  11
 7 >>> np.abs(frame) 
 8     b  d   e
 9 Ut  0  3   2
10 Oh  3  3   5
11 Te  6  3   8
12 Or  9  3  11

另一个常见操作,将函数应用到各列或行所形成的一维数组上。DataFrame的apply方法可实现此功能。

 1 >>> f = lambda x: x.max() - x.min() 
 2 >>> frame
 3     b  d   e
 4 Ut  0 -3   2
 5 Oh  3 -3   5
 6 Te  6 -3   8
 7 Or  9 -3  11
 8 >>> frame.apply(f)
 9 b    9
10 d    0
11 e    9
12 dtype: int64
13 >>> frame.apply(f, axis=1) 
14 Ut     5
15 Oh     8
16 Te    11
17 Or    14
18 dtype: int64
19 >>>

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

 1 >>> def f(x):
 2 ...     return pd.Series([x.min(), x.max()], index=['min', 'max'])
 3 ... 
 4 >>> frame
 5     b  d   e
 6 Ut  0 -3   2
 7 Oh  3 -3   5
 8 Te  6 -3   8
 9 Or  9 -3  11
10 >>> frame.apply(f)
11      b  d   e
12 min  0 -3   2
13 max  9 -3  11
14 >>>

元素级的python函数也是可以使用的。例如求frame中各个浮点值的格式化字符串,使用applymap即可。

1 >>> format = lambda x: '%.2f' % x
2 >>> frame.applymap(format) 
3        b      d      e
4 Ut  0.00  -3.00   2.00
5 Oh  3.00  -3.00   5.00
6 Te  6.00  -3.00   8.00
7 Or  9.00  -3.00  11.00

5.8 排序和排名

5.8.1 排序

根据条件对数据集排序(sorting)也是一种重要的内置运算。

要对行或列索引进行排序(按字典顺序),可使用sort_index方法,它返回的是一个已排序的新对象。

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

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

 1 >>> frame = pd.DataFrame(np.arange(8).reshape((2, 4)), index=['three', 'one'], columns=['d', 'e', 'b', 'c'])
 2 >>> frame.sort_index()
 3        d  e  b  c
 4 one    4  5  6  7
 5 three  0  1  2  3
 6 >>> frame.sort_index(axis=1)  #对轴1进行排序
 7        b  c  d  e
 8 three  2  3  0  1
 9 one    6  7  4  5
10 >>> frame.sort_index(axis=1, ascending=False)  #默认为升序,改为降序
11        e  d  c  b
12 three  1  0  3  2
13 one    5  4  7  6
14 >>>

5.8.2 排名

排名跟排序密切相关,且它会增加一个排名值(从1开始,一直到数组中有效数据的数量)。使用的是rank方法,rank是通过“为各组分配一个平均排名”的方式破坏平级关系的。

可参考我的另一篇博客:pandas rank()函数简介 - zhengcixi - 博客园 (cnblogs.com)

官方文档:pandas.DataFrame.rank — pandas 1.3.4 documentation (pydata.org)

这里有点不好理解,可按照下图理解。

img

method参数说明。

method 说明
‘average’ 默认,在相等分组中,为各个值分配平均排名
‘min’ 使用整个分组的最小排名
‘max’ 使用整个分组的最大排名
‘first’ 按值在原始数据中出现顺序分配排名

示例:

 1 >>> obj = pd.Series([7, -5, 7, 4, 2, 0, 4]) 
 2 >>> obj.rank()
 3 0    6.5
 4 1    1.0
 5 2    6.5
 6 3    4.5
 7 4    3.0
 8 5    2.0
 9 6    4.5
10 dtype: float64
11 >>> obj
12 0    7
13 1   -5
14 2    7
15 3    4
16 4    2
17 5    0
18 6    4
19 dtype: int64
20 >>> obj.rank(method='first')  #根据值在原数据中出现的顺序给出排名
21 0    6.0
22 1    1.0
23 2    7.0
24 3    4.0
25 4    3.0
26 5    2.0
27 6    5.0
28 dtype: float64
29 >>> obj.rank(ascending=False, method='max')  #按降序进行排名
30 0    2.0
31 1    7.0
32 2    2.0
33 3    4.0
34 4    5.0
35 5    6.0
36 6    4.0
37 dtype: float64

DataFrame可以在行或列上计算排名:

 1 >>> frame = pd.DataFrame({'b': [4.3, 7, -3, 2], 'a': [0, 1, 0, 1], 'c': [-2, 5, 8, -2.5]}) 
 2 >>> frame
 3      b  a    c
 4 0  4.3  0 -2.0
 5 1  7.0  1  5.0
 6 2 -3.0  0  8.0
 7 3  2.0  1 -2.5
 8 >>> frame.rank(axis=1)  
 9      b    a    c
10 0  3.0  2.0  1.0
11 1  3.0  1.0  2.0
12 2  1.0  2.0  3.0
13 3  3.0  2.0  1.0

5.9 带有重复值的轴索引

pandas并不强制要求轴标签唯一。对于带有重复值的索引,数据选取的型位将会有所不同。如果某个索引对应多个值,则返回一个Series;而对应单个值的,则返回一个标量值。DataFrame也是如此。

 1 >>> obj = pd.Series(range(5), index=['a', 'a', 'b', 'b', 'c'])
 2 >>> obj
 3 a    0
 4 a    1
 5 b    2
 6 b    3
 7 c    4
 8 dtype: int64
 9 >>> obj.index.is_unique
10 False
11 >>> obj['a']           
12 a    0
13 a    1
14 dtype: int64
15 >>> obj['c'] 
16 4
posted @ 2020-02-03 00:07  zhengcixi  阅读(297)  评论(0编辑  收藏  举报
回到顶部