【Pandas】北理工嵩天老师Python数据分析与展示之Pandas

Pandas

北理工Python数据分析及展示之Pandas。北理工嵩天老师的Python系列课数据分析与展示最后一章的内容。
加油!

什么是Pandas

Numpy的扩展,但是关注的重点与Numpy不同,Numpy注重的是数据的组织结构,提供更为便捷的数组运算。而Pandas的目标是进行数据分析,更注重数据与索引的关系。

引入Pandas

默认方法:

import pandas as pd

验证安装pandas是否成功:

In [1]: import pandas as pd

In [2]: d = pd.Series(range(20))

In [3]: d
Out[3]: 
0      0
1      1
2      2
3      3
4      4
5      5
6      6
7      7
8      8
9      9
10    10
11    11
12    12
13    13
14    14
15    15
16    16
17    17
18    18
19    19
dtype: int64

In [4]: d.cumsum()
Out[4]: 
0       0
1       1
2       3
3       6
4      10‵‵‵
5      15
6      21
7      28
8      36
9      45
10     55
11     66
12     78
13     91
14    105
15    120
16    136
17    153
18    171
19    190
dtype: int64

说明安装成功。

Series类型

由一维ndarray以及对应的索引组成。也就是说一个Series对象包含一个一维ndarray数组和一个index对象。

比如:

In [4]: a = pd.Series([9, 8, 7, 6])

In [5]: a
Out[5]: 
0    9
1    8
2    7
3    6
dtype: int64

左侧一列数据表示自动索引,0,1,2,3

右侧一列数据表示数组9,8,7,6

元素类型为np.int64

也可以自己定义索引:

In [6]: b = pd.Series([9, 8, 7, 6], index=['a', 'b', 'c', 'd'])

In [7]: b
Out[7]: 
a    9
b    8
c    7
d    6
dtype: int64

可以看到索引变成了a,b,c,d

Series的创建

可以从以下类型创建:

  • 列表

  • 标量

    In [9]: s = pd.Series(25, index=['a', 'b', 'c'])
    
    In [10]: s
    Out[10]: 
    a    25
    b    25
    c    25
    dtype: int64
    

    可以看到有3个值为25,索引不同的数据,在这里不能省略index=

  • 字典

    In [11]: d = pd.Series({'a':9, 'b':8, 'c':7})
    
    In [12]: d
    Out[12]: 
    a    9
    b    8
    c    7
    dtype: int64
    

    可以看到创建了顺序对应的Series。

    还可以这样:

    In [13]: e = pd.Series({'a':9, 'b':8, 'c':7}, index=['c', 'a', 'b', 'd'])
    
    In [14]: e
    Out[14]: 
    c    7.0
    a    9.0
    b    8.0
    d    NaN
    dtype: float64
    

    可以看到,自己指定索引时可以与之前的顺序不同,也可以增加索引。可以看作后面index参数是在选择字典中的数据。

  • ndarray

    In [15]: n = pd.Series(np.arange(5))
    
    In [16]: n
    Out[16]: 
    0    0
    1    1
    2    2
    3    3
    4    4
    dtype: int64
    
    In [17]: m = pd.Series(np.arange(5), index=np.arange(9, 4, -1))
    
    In [18]: m
    Out[18]: 
    9    0
    8    1
    7    2
    6    3
    5    4
    dtype: int64
    
  • 其他函数

    如range等。

Series基本操作

取数据:

In [22]: b.index
Out[22]: Index(['a', 'b', 'c', 'd'], dtype='object')

In [23]: b.values
Out[23]: array([9, 8, 7, 6])

index和values,index是一种类型专门保存索引。而values是ndarray类型。

索引:

In [24]: b[0]
Out[24]: 9

In [25]: b['a']
Out[25]: 9

In [30]: b[['a', 'b', 'c']]
Out[30]: 
a    9
b    8
c    7
dtype: int64

混合索引貌似在当前版本已经不支持了。

切片索引:

In [33]: b = pd.Series([9, 8, 7, 6], ['a', 'b', 'c', 'd'])

In [34]: b
Out[34]: 
a    9
b    8
c    7
d    6
dtype: int64

In [35]: b[3]
Out[35]: 6

In [36]: b[:3]
Out[36]: 
a    9
b    8
c    7
dtype: int64

In [37]: type(b[3])
Out[37]: numpy.int64

In [38]: type(b[:3])
Out[38]: pandas.core.series.Series

**注意:**切片索引出的数据还是Series类型。

Series类型也保留了numpy中的一些操作:

In [39]: b[b > b.median()]
Out[39]: 
a    9
b    8
dtype: int64

In [40]: np.exp(b)
Out[40]: 
a    8103.083928
b    2980.957987
c    1096.633158
d     403.428793
dtype: float64

类似于字典的操作:

In [41]: b['b']
Out[41]: 8

In [42]: 'c' in b
Out[42]: True

In [43]: 0 in b
Out[43]: False

In [44]: b.get('f', 100)
Out[44]: 100

get成员函数如果有’f’则返回对应的值,没有返回100.

Series对齐问题:

In [45]: a = pd.Series([1, 2, 3], ['c', 'd', 'e'])

In [46]: b = pd.Series([9, 8, 7, 6], ['a', 'b', 'c', 'd'])

In [47]: a + b
Out[47]: 
a    NaN
b    NaN
c    8.0
d    8.0
e    NaN
dtype: float64

没有对应的值,结果为NaN,都有对应的值,则对应相加,也就是根据索引进行的运算。

Series的name属性以及索引的name属性:

In [48]: b.name

In [49]: b.name = 'Series对象'

In [50]: b.index.name = '索引列'

In [51]: b
Out[51]: 
索引列
a    9
b    8
c    7
d    6
Name: Series对象, dtype: int64

Series赋值:

In [56]: b['b']
Out[56]: 8

In [57]: b['a'] = 15

In [58]: b['b', 'c'] = 20
%也可以b[['b', 'c']] = 20

In [59]: b
Out[59]: 
索引列
a    15
b    20
c    20
d     6
Name: Series对象, dtype: int64

DataFrame类型

Series是一维数据构成,那DataFrame就是二维类型。

index代表行数据,axis=0;coloum代表列数据,axis=1。

DataFrame的创建

可以由:

  • 二维ndarray对象

    In [104]: d = pd.DataFrame(np.arange(10).reshape(2, 5))
    
    In [105]: d
    Out[105]: 
       0  1  2  3  4
    0  0  1  2  3  4
    1  5  6  7  8  9
    

    最左边的列和最上面的行都是自动索引。

  • 一维ndarray,列表,字典,元组或者Series构成的字典

    In [111]: dt = {'one': pd.Series([1, 2, 3], index = ['a', 'b', 'c']),
         ...: 'two': pd.Series([9, 8, 7, 6], index = ['a', 'b', 'c', 'd'])}
    
    In [112]: d = pd.DataFrame(dt)
    
    %行索引就是字典中Series中的index,列索引就是字典的键,没有值自动补齐,填充NaN
    In [113]: d
    Out[113]: 
       one  two
    a  1.0    9
    b  2.0    8
    c  3.0    7
    d  NaN    6
    
    %自定义列索引,three没有,自己不全NaN
    In [114]: pd.DataFrame(dt, index=['b', 'c', 'd'], columns=['two', 'three'])
    Out[114]: 
       two three
    b    8   NaN
    c    7   NaN
    d    6   NaN
    

    DataFrame关心数据,索引如果给定就用给定的,而行索引来自index,列索引来自字典的键。

    import numpy as np
    import pandas as pd 
    
    dl = {'城市': ['北京', '上海', '广州', '深圳', '沈阳'],
          '环比': [101.5, 101.2, 101.3, 102.0, 100.1],
          '同比': [120.7, 127.3, 119.4, 140.9, 101.4],
          '定基': [121.4, 127.8, 120.0, 145.5, 101.6]}
    
    d = pd.DataFrame(dl, index=['c1', 'c2', 'c3', 'c4', 'c5'])
    print(d)
    
    In [2]: d
    Out[2]: 
        城市     环比     同比     定基
    c1  北京  101.5  120.7  121.4
    c2  上海  101.2  127.3  127.8
    c3  广州  101.3  119.4  120.0
    c4  深圳  102.0  140.9  145.5
    c5  沈阳  100.1  101.4  101.6
    
    In [3]: d.index
    Out[3]: Index(['c1', 'c2', 'c3', 'c4', 'c5'], dtype='object')
    
    In [4]: d.columns
    Out[4]: Index(['城市', '环比', '同比', '定基'], dtype='object')
    
    In [5]: d.values
    Out[5]: 
    array([['北京', 101.5, 120.7, 121.4],
           ['上海', 101.2, 127.3, 127.8],
           ['广州', 101.3, 119.4, 120.0],
           ['深圳', 102.0, 140.9, 145.5],
           ['沈阳', 100.1, 101.4, 101.6]], dtype=object)
    

    这里虽然看着生成的DataFrame和之前的顺序相同,实则是无序的,因为字典是无序的。

    这里课程录制的时间有点早应该是2017年,课程录制完成后DataFrame的ix方法被弃用,改为更为精确的loc和iloc。

    loc方法用于根据行索引名字来索引,iloc根据行号索引:

    In [24]: d['同比']
    Out[24]: 
    c1    120.7
    c2    127.3
    c3    119.4
    c4    140.9
    c5    101.4
    Name: 同比, dtype: float64
    
    In [25]: d.loc['c2']
    Out[25]: 
    城市       上海
    环比    101.2
    同比    127.3
    定基    127.8
    Name: c2, dtype: object
    
    In [26]: d.iloc[1]
    Out[26]: 
    城市       上海
    环比    101.2
    同比    127.3
    定基    127.8
    Name: c2, dtype: object
    
    In [27]: d['同比']['c2']
    Out[27]: 127.3
    
  • Series类型

  • 其他的DataFrame类型

Pandas相关操作

重新索引

reindex函数:

In [28]: d
Out[28]: 
    城市     环比     同比     定基
c1  北京  101.5  120.7  121.4
c2  上海  101.2  127.3  127.8
c3  广州  101.3  119.4  120.0
c4  深圳  102.0  140.9  145.5
c5  沈阳  100.1  101.4  101.6

In [29]: d = d.reindex(index=['c5', 'c4', 'c3', 'c2', 'c1'])

In [30]: d
Out[30]: 
    城市     环比     同比     定基
c5  沈阳  100.1  101.4  101.6
c4  深圳  102.0  140.9  145.5
c3  广州  101.3  119.4  120.0
c2  上海  101.2  127.3  127.8
c1  北京  101.5  120.7  121.4

reindex参数解释(不全,全部自己看帮助文档)

args comment
index, columns 新的行列自定义索引
fill_value 重新索引中,用于填充确实位置的值
method 填充方法,ffill当前值向前填充,bfill向后填充
limit 最大填充量
copy 默认True,生成新对象,否则,如果新旧相等,不生成新对象

fill_value参数实例:

In [3]: newc = d.columns.insert(4, '新增')

In [4]: newd = d.reindex(columns=newc, fill_value=200)

In [5]: newd
Out[5]: 
    城市     环比     同比     定基   新增
c1  北京  101.5  120.7  121.4  200
c2  上海  101.2  127.3  127.8  200
c3  广州  101.3  119.4  120.0  200
c4  深圳  102.0  140.9  145.5  200
c5  沈阳  100.1  101.4  101.6  200

Index对象

Index对象是不可改变的。

Index对象常用的方法:

method comment
.append(idx) 链接另一个Index对象,产生新的Index对象
.diff(idx) 计算差集,产生新的Index对象
.intersection(idx) 计算交集
.union(idx) 计算并集
.delete(loc) 删除loc位置处的元素
.insert(loc, e) 在loc位置增加一个元素e

这里在跑课程中的实例时出现了问题:

In [36]: nc = d.columns.delete(2)

In [37]: ni = d.index.insert(5, 'c0')

In [38]: nd = d.reindex(index=ni, columns=nc, method='ffill')
#这一句会报错,错误原因是索引不是单调的,所以填充失败。经查资料,该问题暂时无法解决,可能是因为删除引起的,只好先删除,再调用填充方法。

In [39]: nc = d.columns.delete(2)

In [40]: ni = d.index.insert(5, 'c0')

In [41]: nd = d.reindex(index=ni, columns=nc)

In [42]: nd.ffill()
Out[42]: 
    城市     环比     定基
c5  沈阳  100.1  101.6
c4  深圳  102.0  145.5
c3  广州  101.3  120.0
c2  上海  101.2  127.8
c1  北京  101.5  121.4
c0  北京  101.5  121.4

删除索引对象

.drop

In [53]: a
Out[53]: 
a    9
b    8
c    7
d    6
dtype: int64

In [54]: a.drop(['b' ,'c'])
Out[54]: 
a    9
d    6
dtype: int64


In [61]: d
Out[61]: 
    城市     环比     同比     定基
c5  沈阳  100.1  101.4  101.6
c4  深圳  102.0  140.9  145.5
c3  广州  101.3  119.4  120.0
c2  上海  101.2  127.3  127.8
c1  北京  101.5  120.7  121.4

In [62]: d.drop('c5')
Out[62]: 
    城市     环比     同比     定基
c4  深圳  102.0  140.9  145.5
c3  广州  101.3  119.4  120.0
c2  上海  101.2  127.3  127.8
c1  北京  101.5  120.7  121.4

In [63]: d.drop('同比', axis=1)#注意:这里要指定axis,否则会认为删除的是0轴上的元素
Out[63]: 
    城市     环比     定基
c5  沈阳  100.1  101.6
c4  深圳  102.0  145.5
c3  广州  101.3  120.0
c2  上海  101.2  127.8
c1  北京  101.5  121.4

Pandas相关运算

广播

广播

In [107]: a = np.arange(10, 20).reshape(2, 5)

In [108]: b = np.arange(22, 32).reshape(2, 5)

In [109]: a + b
Out[109]: 
array([[32, 34, 36, 38, 40],
       [42, 44, 46, 48, 50]])

In [110]: a + 1.0/b
Out[110]: 
array([[10.04545455, 11.04347826, 12.04166667, 13.04      , 14.03846154],
       [15.03703704, 16.03571429, 17.03448276, 18.03333333, 19.03225806]])
#这里1.0/b就用到了广播
In [112]: a = np.arange(0, 10).reshape(2, 5)

In [113]: 2*a
Out[113]: 
array([[ 0,  2,  4,  6,  8],
       [10, 12, 14, 16, 18]])
#这里也用到了广播

广播是指在numpy数组间,就算不同形也可以计算的性质,在Pandas中DataFrame和Series也有类似的性质。当然可以广播进行广播是有前提的,要符合广播机制。

广播机制

若两个数组维度不同,但是后缘维度的轴长相同,或者其中有一个轴长为1,则广播兼容

后缘维度:从数组的shape元组后面数就叫后缘维度。

In [112]: a = np.arange(0, 10).reshape(2, 5)

In [113]: 2*a
Out[113]: 
array([[ 0,  2,  4,  6,  8],
       [10, 12, 14, 16, 18]])
#后缘维度为5

In [116]: b = np.arange(10)

In [117]: b.shape
Out[117]: (10,)
#后缘维度10

后缘维度相同:

In [121]: arr1 = np.array([[0, 0, 0], [1, 1, 1,], [2, 2, 2], [3, 3, 3]])

In [122]: arr2 = np.array([1, 2, 3])

In [123]: print(arr1.shape, arr2.shape)
(4, 3) (3,)

In [124]: arr_sum = arr1 + arr2

In [125]: arr_sum
Out[125]: 
array([[1, 2, 3],
       [2, 3, 4],
       [3, 4, 5],
       [4, 5, 6]])

$$
\begin{bmatrix}
0 & 0 & 0\
1 & 1 & 1\
2 & 2 & 2\
3 & 3 & 3
\end{bmatrix}
+
\begin{bmatrix}
1 & 2 & 3\
\textcolor{blue} 1 & \textcolor{blue}2 & \textcolor{blue}3\
\textcolor{blue} 1 & \textcolor{blue}2 & \textcolor{blue}3\
\textcolor{blue} 1 & \textcolor{blue}2 & \textcolor{blue}3\
\end{bmatrix}

\begin{bmatrix}
1 & 2 & 3\
2 & 3 & 4\
3 & 4 & 5\
4 & 5 & 6
\end{bmatrix}
$$

后缘维度中有1:

In [130]: arr1 = np.array([[0, 0, 0], [1, 1, 1,], [2, 2, 2,], [3, 3, 3]])

In [131]: arr2 = np.array([[1], [2], [3], [4]])

In [132]: print(arr1.shape, arr2.shape)
(4, 3) (4, 1)

In [133]: arr1+arr2
Out[133]: 
array([[1, 1, 1],
       [3, 3, 3],
       [5, 5, 5],
       [7, 7, 7]])

$$
\begin{bmatrix}
0 & 0 & 0\
1 & 1 & 1\
2 & 2 & 2\
3 & 3 & 3
\end{bmatrix}
+
\begin{bmatrix}
1 & \textcolor{blue} 1 & \textcolor{blue} 1\
2 & \textcolor{blue} 2 & \textcolor{blue} 2\
3 & \textcolor{blue} 3 & \textcolor{blue} 3\
4 & \textcolor{blue} 4 & \textcolor{blue} 4\
\end{bmatrix}

\begin{bmatrix}
1 & 1 & 1\
3 & 3 & 3\
5 & 5 & 5\
7 & 7 & 7
\end{bmatrix}
$$

Pandas运算法则

  • 算数运算根据索引进行运算,补齐后进行运算,默认浮点数
  • 补齐时缺项填充NaN
  • 不同维进行广播运算
  • 使用±*/符号进行运算产生新的对象

算数运算:

In [135]: a = pd.DataFrame(np.arange(12).reshape(3, 4))

In [136]: b = pd.DataFrame(np.arange(20).reshape(4, 5))

In [137]: a
Out[137]: 
   0  1   2   3
0  0  1   2   3
1  4  5   6   7
2  8  9  10  11

In [138]: b
Out[138]: 
    0   1   2   3   4
0   0   1   2   3   4
1   5   6   7   8   9
2  10  11  12  13  14
3  15  16  17  18  19

In [139]: a + b
Out[139]: 
      0     1     2     3   4
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

In [140]: a * b
Out[140]: 
      0     1      2      3   4
0   0.0   1.0    4.0    9.0 NaN
1  20.0  30.0   42.0   56.0 NaN
2  80.0  99.0  120.0  143.0 NaN
3   NaN   NaN    NaN    NaN NaN

方法形式:

method comment
.add(d, **argws) 加法,带可选参数
.sub(d, **argws) 减肥,带可选参数
.mul(d, **argws) 乘法,带可选参数
.div(d, **argws) 除法,带可选参数

这种形式相对于符号运算形式是有优点的,可以看到符号形式在自动补齐的地方全是NaN,这种可以指定填充字符:

In [141]: b.add(a, fill_value=100)
Out[141]: 
       0      1      2      3      4
0    0.0    2.0    4.0    6.0  104.0
1    9.0   11.0   13.0   15.0  109.0
2   18.0   20.0   22.0   24.0  114.0
3  115.0  116.0  117.0  118.0  119.0

In [142]: a.mul(b, fill_value=0)
Out[142]: 
      0     1      2      3    4
0   0.0   1.0    4.0    9.0  0.0
1  20.0  30.0   42.0   56.0  0.0
2  80.0  99.0  120.0  143.0  0.0
3   0.0   0.0    0.0    0.0  0.0
#使用fill_value补齐数值

不同维度(类型)的运算

注意Pandas的广播机制和numpy不同

默认在1轴广播,不同维也可广播,填充NaN

In [160]: b
Out[160]: 
    0   1   2   3   4
0   0   1   2   3   4
1   5   6   7   8   9
2  10  11  12  13  14
3  15  16  17  18  19

In [161]: c
Out[161]: 
0    0
1    1
2    2
3    3
dtype: int64

In [162]: b - c
Out[162]: 
      0     1     2     3   4
0   0.0   0.0   0.0   0.0 NaN
1   5.0   5.0   5.0   5.0 NaN
2  10.0  10.0  10.0  10.0 NaN
3  15.0  15.0  15.0  15.0 NaN

可以指定0轴广播:

In [164]: b.sub(c, axis=0)
Out[164]: 
    0   1   2   3   4
0   0   1   2   3   4
1   4   5   6   7   8
2   8   9  10  11  12
3  12  13  14  15  16

比较运算,产生bool对象:

In [165]: a = pd.DataFrame(np.arange(12).reshape(3, 4))

In [166]: a
Out[166]: 
   0  1   2   3
0  0  1   2   3
1  4  5   6   7
2  8  9  10  11

In [167]: d = pd.DataFrame(np.arange(12, 0, -1).reshape(3, 4))

In [168]: d
Out[168]: 
    0   1   2  3
0  12  11  10  9
1   8   7   6  5
2   4   3   2  1

In [169]: a > d
Out[169]: 
       0      1      2      3
0  False  False  False  False
1  False  False  False   True
2   True   True   True   True

In [170]: a == d
Out[170]: 
       0      1      2      3
0  False  False  False  False
1  False  False   True  False
2  False  False  False  False 

比较运算与算数运算不同的是,比较运算只能比较相同索引的元素,不进行补齐。

二维一维,一维零维间为广播运算。使用符号进行的比较运算产生bool对象。

In [179]: a = pd.DataFrame(np.arange(12).reshape(3, 4))

In [180]: a
Out[180]: 
   0  1   2   3
0  0  1   2   3
1  4  5   6   7
2  8  9  10  11

In [181]: c = pd.Series(np.arange(4))

In [182]: c
Out[182]: 
0    0
1    1
2    2
3    3
dtype: int64

In [183]: a > c
Out[183]: 
       0      1      2      3
0  False  False  False  False
1   True   True   True   True
2   True   True   True   True

In [184]: c > 0
Out[184]: 
0    False
1     True
2     True
3     True
dtype: bool
#1轴广播运算,与0维数的运算

Pandas库数据分析

看到这里,我觉得目前没必要继续下去了,要回归主线AI了。接下俩可能会看看Pytorch,OpenCV,接着看学了一半的C++,并且开个矩阵论和自动驾驶原理的头。

你可能感兴趣的:(python,数据分析,数据挖掘)