• 数据分析之pandas教程-----概念篇


    目录

    pandas基本概念

    pandas数据结构剖析

    Series

    Series = 一组数据 + 数据标签

    如果从表格的角度来看, 就是表格里面的一列带着索引.

    from pandas import Series, DataFrame
    import pandas as pd
    import numpy as np
    
    obj = Series(data=[1, 2, 3, 4])
    print(obj)
    
    # 我们可以用values和index分别获取数据和标签
    print(obj.values)
    print(type(obj.values))
    print(obj.index)
    print(type(obj.index))
    
    0    1
    1    2
    2    3
    3    4
    dtype: int64
    [1 2 3 4]
    <class 'numpy.ndarray'>
    RangeIndex(start=0, stop=4, step=1)
    <class 'pandas.core.indexes.range.RangeIndex'>
    

    我们发现, 这个obj.values其实就是一个numpy对象, 而obj.index是一个index对象, 我们也可以在代码指定index:

    obj2 = Series(data=[1, 2, 3, 4], index=['a', 'b', 'c', 'd'], dtype=np.float32, name='test')
    print(obj2)
    
    a    1.0
    b    2.0
    c    3.0
    d    4.0
    Name: test, dtype: float32
    

    我们要注意, Series的标签和数据的对应关系, 不随运算而改变. 大部分在np里面可以使用的操作, 在Series上都是行得通的.

    print(obj2 * 2)
    print(obj2 ** 2)
    print(np.exp(obj2))
    
    a    2.0
    b    4.0
    c    6.0
    d    8.0
    Name: test, dtype: float32
    a     1.0
    b     4.0
    c     9.0
    d    16.0
    Name: test, dtype: float32
    a     2.718282
    b     7.389056
    c    20.085537
    d    54.598148
    Name: test, dtype: float32
    

    Series其实也可以看作是一个字典, 我们来看这么个例子:

    obj3 = Series({'a':1, 'b':2})
    print(obj3)
    print('a' in obj3)
    
    a    1
    b    2
    dtype: int64
    True
    

    我们照样可以改变索引:

    obj3 = Series({'a':1, 'b':2}, index=['a', 'c'])
    print(obj3)
    
    a    1.0
    c    NaN
    dtype: float64
    

    NaN表示缺失数据, 我们可以用isnull和notnull看来判断:

    print(pd.isnull(obj3))
    print(pd.notnull(obj3))
    
    a    False
    c     True
    dtype: bool
    a     True
    c    False
    dtype: bool
    

    我们来看一个加法的例子:

    a = Series([1, 2], index=['a', 'b'])
    b = Series([2, 3], index=['b', 'c'])
    print(a + b)
    
    a    NaN
    b    4.0
    c    NaN
    dtype: float64
    

    两个Series对象在做运算时, 会自动对齐.

    DataFrame

    DataFrame可以看作是一张表, 我们也可以把它看作是横向和纵向两个Series.

    构造DataFrame可以通过一个ndarray或者是list的字典来构造.

    data = {'a':[1, 2, 3], 'b':[4, 5, 6] }
    frame = DataFrame(data)
    print(frame)
    
       a  b
    0  1  4
    1  2  5
    2  3  6
    

    我们一样也可以指定index, 不过对于DataFrame, 要指定columns和index.

    frame = DataFrame(data, index=['A', 'B', 'C'], columns=['a', 'b', 'c'])
    print(frame)
    
       a  b    c
    A  1  4  NaN
    B  2  5  NaN
    C  3  6  NaN
    

    我们可以用一个二维ndarray来初始化DataFrame:

    data = np.random.randn(3, 3)
    frame = DataFrame(data)
    print(frame)
    
    print("-----------------------------------------------------------------")
    
    frame = DataFrame(data, index=['A', 'B', 'C'], columns=['a', 'b', 'c'])
    print(frame)
    
              0         1         2
    0 -0.219102 -1.849864 -0.545050
    1 -2.639734  0.489300  0.911258
    2  0.810350  0.383256 -0.815600
    -----------------------------------------------------------------
              a         b         c
    A -0.219102 -1.849864 -0.545050
    B -2.639734  0.489300  0.911258
    C  0.810350  0.383256 -0.815600
    

    我们用索引的方式, 可以获取到某一列, 作为Series.

    print(frame['a'])
    
    A   -0.219102
    B   -2.639734
    C    0.810350
    Name: a, dtype: float64
    

    我们发现, 这个Series的名字, 就是列名.

    如果我们要修改DataFrame的某个值, 怎么改呢? 我们先来看看怎么修改某一列的值.

    # 修改某一个列的值
    frame['a'] = [1,1,1]
    print(frame)
    
       a         b         c
    A  1 -1.849864 -0.545050
    B  1  0.489300  0.911258
    C  1  0.383256 -0.815600
    
    # 如果我们list的长度不符合, 就会报错
    frame['a'] = [1,1]
    
    ---------------------------------------------------------------------------
    
    ValueError                                Traceback (most recent call last)
    
    <ipython-input-81-54000a6faf10> in <module>()
          1 # 如果我们list的长度不符合, 就会报错
    ----> 2 frame['a'] = [1,1]
    
    
    d:anaconda3envs	ensorflow_gpulibsite-packagespandascoreframe.py in __setitem__(self, key, value)
       2329         else:
       2330             # set column
    -> 2331             self._set_item(key, value)
       2332 
       2333     def _setitem_slice(self, key, value):
    
    
    d:anaconda3envs	ensorflow_gpulibsite-packagespandascoreframe.py in _set_item(self, key, value)
       2395 
       2396         self._ensure_valid_index(value)
    -> 2397         value = self._sanitize_column(key, value)
       2398         NDFrame._set_item(self, key, value)
       2399 
    
    
    d:anaconda3envs	ensorflow_gpulibsite-packagespandascoreframe.py in _sanitize_column(self, key, value, broadcast)
       2566 
       2567             # turn me into an ndarray
    -> 2568             value = _sanitize_index(value, self.index, copy=False)
       2569             if not isinstance(value, (np.ndarray, Index)):
       2570                 if isinstance(value, list) and len(value) > 0:
    
    
    d:anaconda3envs	ensorflow_gpulibsite-packagespandascoreseries.py in _sanitize_index(data, index, copy)
       2877 
       2878     if len(data) != len(index):
    -> 2879         raise ValueError('Length of values does not match length of ' 'index')
       2880 
       2881     if isinstance(data, PeriodIndex):
    
    
    ValueError: Length of values does not match length of index
    
    # 对于这种情况, 我们可以用Series来搞定
    s = Series({'A':1, 'B':1})
    frame['a'] = s
    print(frame)
    
         a         b         c
    A  1.0 -1.849864 -0.545050
    B  1.0  0.489300  0.911258
    C  NaN  0.383256 -0.815600
    

    如果我们要新加一列, 可以这样写:

    frame['d'] = s
    print(frame)
    
         a         b         c    d
    A  1.0 -1.849864 -0.545050  1.0
    B  1.0  0.489300  0.911258  1.0
    C  NaN  0.383256 -0.815600  NaN
    

    如果我们要删除一列, 可以用del

    print(frame.columns)
    del frame['d']
    print(frame.columns)
    
    Index(['a', 'b', 'c', 'd'], dtype='object')
    Index(['a', 'b', 'c'], dtype='object')
    

    我们还可以用字典来初始化我们的DataFrame:

    data = {'a':{'A':1,'B':2}, 'b':{'A':3,'B':4}}
    frame = DataFrame(data)
    print(frame)
    print(frame.columns)
    print(frame.index)
    print(frame.values)
    
       a  b
    A  1  3
    B  2  4
    Index(['a', 'b'], dtype='object')
    Index(['A', 'B'], dtype='object')
    [[1 3]
     [2 4]]
    

    有Series的字典也可以初始化DataFrame, 我们这里不演示了, 留作作业.

    作业1: 用Series的字典初始化DataFrame.

    索引

    下面我们来里聊聊索引, 这个也是pandas中比较基本的一个概念.

    index = frame.index
    colunms = frame.columns
    print(type(colunms))
    print(type(index))
    print(index.name)
    print(colunms.name)
    
    <class 'pandas.core.indexes.base.Index'>
    <class 'pandas.core.indexes.base.Index'>
    None
    None
    

    我们可以把索引理解为 ** 不可变的hashset **

    print(index)
    
    Index(['A', 'B'], dtype='object')
    
    index[1]='D'
    
    ---------------------------------------------------------------------------
    
    TypeError                                 Traceback (most recent call last)
    
    <ipython-input-88-e57751cb899e> in <module>()
    ----> 1 index[1]='D'
    
    
    d:anaconda3envs	ensorflow_gpulibsite-packagespandascoreindexesase.py in __setitem__(self, key, value)
       1668 
       1669     def __setitem__(self, key, value):
    -> 1670         raise TypeError("Index does not support mutable operations")
       1671 
       1672     def __getitem__(self, key):
    
    
    TypeError: Index does not support mutable operations
    

    注意这行错误:
    Index does not support mutable operations

    此外, 索引也支持hashset类似的操作, 我们这里不提了.

    作业2: 熟悉index的操作函数.

    pandas基本操作

    我们这里来看看pands具体有哪些基本操作.

    重索引

    在已经有的索引的基础上改变索引的操作我们称为重索引.

    data = np.random.randn(3, 3)
    frame = DataFrame(data, index=['A', 'B', 'C'], columns=['a', 'b', 'c'])
    print(frame)
    
              a         b         c
    A -0.545762 -1.089096 -2.164863
    B -0.514410 -1.337000  0.434980
    C -1.729591 -1.060305 -0.218492
    
    # 将A, B, C重索引C, B, A
    frame = frame.reindex(index=['C', 'B', 'A'])
    print(frame)
    
              a         b         c
    C -1.729591 -1.060305 -0.218492
    B -0.514410 -1.337000  0.434980
    A -0.545762 -1.089096 -2.164863
    
    # 同时将列也索引成c, b, a
    frame = frame.reindex(index=['C', 'B', 'A'], columns=['c', 'b', 'a'])
    print(frame)
    
              c         b         a
    C -0.218492 -1.060305 -1.729591
    B  0.434980 -1.337000 -0.514410
    A -2.164863 -1.089096 -0.545762
    
    # 加入d 新的索引
    frame = frame.reindex(index=['C', 'B', 'A'], columns=['c', 'b', 'a', 'd'])
    print(frame)
    
              c         b         a   d
    C -0.218492 -1.060305 -1.729591 NaN
    B  0.434980 -1.337000 -0.514410 NaN
    A -2.164863 -1.089096 -0.545762 NaN
    
    # 将NaN值设置为0
    frame = frame.reindex(index=['C', 'B', 'A', 'D'], columns=['c', 'b', 'a', 'd'], fill_value=0)
    print(frame)
    
              c         b         a    d
    C -0.218492 -1.060305 -1.729591  NaN
    B  0.434980 -1.337000 -0.514410  NaN
    A -2.164863 -1.089096 -0.545762  NaN
    D  0.000000  0.000000  0.000000  0.0
    

    注意到, 因为d列已经是NaN里, 所以不会填充, 填充只发生在reindex的时候.

    丢弃一行或者一列

    我们可以很方便的丢弃一行或者一列:

    frame = frame.drop(['C', 'B'])
    print(frame)
    
              c         b         a    d
    A -2.164863 -1.089096 -0.545762  NaN
    D  0.000000  0.000000  0.000000  0.0
    
    # 丢弃一列
    frame = frame.drop([ 'd'], axis=1)
    print(frame)
    
              c         b         a
    A -2.164863 -1.089096 -0.545762
    D  0.000000  0.000000  0.000000
    
    数据选取

    我们用[]一般选取的是一列, 当然也有几种特殊的情况:

    data = np.random.randn(3, 3)
    frame = DataFrame(data, index=['A', 'B', 'C'], columns=['a', 'b', 'c'])
    print(frame[:2])
    print('-----------------------------------------------------------------')
    print(frame[1:2])
    
              a         b         c
    A  0.542189 -2.005171  1.265211
    B -0.145857 -0.054910 -1.277347
    -----------------------------------------------------------------
              a        b         c
    B -0.145857 -0.05491 -1.277347
    

    frame[:2]并不是大家理解中的倒数两列, 而是倒数两行. 也是奇葩, 作者真是脑子有坑.

    print(frame > 0.1)
    
           a      b      c
    A   True  False   True
    B  False  False  False
    C   True   True   True
    
    frame[frame > 0.1] = 0
    print(frame)
    
              a         b         c
    A  0.000000 -2.005171  0.000000
    B -0.145857 -0.054910 -1.277347
    C  0.000000  0.000000  0.000000
    

    如果我们要选取特定一行呢, 我们会用到loc和ix函数.

    print(frame.loc['A'])
    print("-----------------------------------------------------")
    print(frame.loc['A':'B'])
    print("-----------------------------------------------------")
    print(frame.loc['A', 'c'])
    print("-----------------------------------------------------")
    print(frame.loc['A':'B', 'b':'c'])
    print("-----------------------------------------------------")
    print(frame.ix[:2, :2])
    print("-----------------------------------------------------")
    print(frame.ix['A':'B', 'b':'c'])
    print("-----------------------------------------------------")
    print(frame.ix['B', 'b':'c'])
    
    a    0.000000
    b   -2.005171
    c    0.000000
    Name: A, dtype: float64
    -----------------------------------------------------
              a         b         c
    A  0.000000 -2.005171  0.000000
    B -0.145857 -0.054910 -1.277347
    -----------------------------------------------------
    0.0
    -----------------------------------------------------
              b         c
    A -2.005171  0.000000
    B -0.054910 -1.277347
    -----------------------------------------------------
              a         b
    A  0.000000 -2.005171
    B -0.145857 -0.054910
    -----------------------------------------------------
              b         c
    A -2.005171  0.000000
    B -0.054910 -1.277347
    -----------------------------------------------------
    b   -0.054910
    c   -1.277347
    Name: B, dtype: float64
    

    ** 注意: 对于tag, 我们两端点是可以取到的. **

    数据对齐

    我们会来讲讲数据对齐的问题, Series的对齐我们看过了, DataFrame会在行和列两个维度上进行对齐.

    data = np.random.randn(3, 3)
    
    a = DataFrame(data, index=['A', 'B', 'C'], columns=['a', 'b', 'c'])
    b = DataFrame(data, index=['A', 'B', 'C'], columns=['d', 'c', 'b'])
    
    print(a)
    print("-----------------------------------------------------------------")
    print(b)
    print("-----------------------------------------------------------------")
    print(a + b)
    
              a         b         c
    A  0.148959 -1.091292 -1.371497
    B  0.073900  0.339610  0.236825
    C  1.130694  0.069362  0.534634
    -----------------------------------------------------------------
              d         c         b
    A  0.148959 -1.091292 -1.371497
    B  0.073900  0.339610  0.236825
    C  1.130694  0.069362  0.534634
    -----------------------------------------------------------------
        a         b         c   d
    A NaN -2.462789 -2.462789 NaN
    B NaN  0.576435  0.576435 NaN
    C NaN  0.603996  0.603996 NaN
    
    # 设置缺失值
    print(a.add(b, fill_value=0))
    
              a         b         c         d
    A  0.148959 -2.462789 -2.462789  0.148959
    B  0.073900  0.576435  0.576435  0.073900
    C  1.130694  0.603996  0.603996  1.130694
    

    DataFrame和series相加, 这里会用到numpy里面提到过的广播机制. 大家可以去numpy里面看看:

    a = a.add(b, fill_value=0)
    print(a)
    print("-------------------------------------------------------")
    b = a.iloc [0]
    print(b)
    
              a         b         c         d
    A  0.148959 -2.462789 -2.462789  0.148959
    B  0.073900  0.576435  0.576435  0.073900
    C  1.130694  0.603996  0.603996  1.130694
    -------------------------------------------------------
    a    0.148959
    b   -2.462789
    c   -2.462789
    d    0.148959
    Name: A, dtype: float64
    

    我们注意到, a的大小是(3, 4), b的大小是(1,4), tail dimenson是一致的, 可以在其他维度上进行广播.

    print(a - b)
    
              a         b         c         d
    A  0.000000  0.000000  0.000000  0.000000
    B -0.075059  3.039224  3.039224 -0.075059
    C  0.981735  3.066785  3.066785  0.981735
    

    如果我们要在列上广播呢, 我们来看下面这个例子:

    b = a['b']
    print(b)
    print("-------------------------------------------------------")
    print(a - b) 
    
    A   -2.462789
    B    0.576435
    C    0.603996
    Name: b, dtype: float64
    -------------------------------------------------------
        A   B   C   a   b   c   d
    A NaN NaN NaN NaN NaN NaN NaN
    B NaN NaN NaN NaN NaN NaN NaN
    C NaN NaN NaN NaN NaN NaN NaN
    

    我们发现, 默认是在axis=1(横向)做减法的, 因为用了广播机制, 同时缺失值为NaN, 我们就得到了上述的结果, 但是这并不是我们想要的.

    我们可以设置需要广播以及运算的轴

    print(a.sub(b, axis=0))
    
              a    b    c         d
    A  2.611748  0.0  0.0  2.611748
    B -0.502535  0.0  0.0 -0.502535
    C  0.526698  0.0  0.0  0.526698
    

    axis=0表示纵向减法.

    pandas函数简单介绍

    这里我们会简单介绍一些pandas的一些函数, 我们来看看, DataFrame上可以定义哪些有趣的函数.

    apply和applymap函数

    首先, 我们来介绍一下apply函数, 这个函数可以把我们自定义的函数用在DataFrame的每一行或者每一列上, 我们来看一个例子.

    data = np.random.randn(3, 3)
    
    a = DataFrame(data, index=['A', 'B', 'C'], columns=['a', 'b', 'c'])
    
    print(a)
    
    print("------------------------------------------------------------------------")
    
    print(a.apply(np.max))
    print(a.apply(np.min))
    print(a.apply(lambda x: np.max(x) - np.min(x)))
    
    print("------------------------------------------------------------------------")
    a.loc['max'] = a.apply(np.max)
    a.loc['min'] = a.apply(np.min)
    a.loc['margin'] = a.apply(lambda x: np.max(x) - np.min(x))
    print(a)
    
              a         b         c
    A -0.137231 -2.008153 -0.766172
    B  0.473756 -0.071421  1.549933
    C  1.057641  0.375983 -0.647798
    ------------------------------------------------------------------------
    a    1.057641
    b    0.375983
    c    1.549933
    dtype: float64
    a   -0.137231
    b   -2.008153
    c   -0.766172
    dtype: float64
    a    1.194872
    b    2.384135
    c    2.316105
    dtype: float64
    ------------------------------------------------------------------------
                   a         b         c
    A      -0.137231 -2.008153 -0.766172
    B       0.473756 -0.071421  1.549933
    C       1.057641  0.375983 -0.647798
    max     1.057641  0.375983  1.549933
    min    -0.137231 -2.008153 -0.766172
    margin  1.194872  2.384135  2.316105
    
    
    a['max'] = a.apply(np.max, axis=1)
    a['min'] = a.apply(np.min, axis=1)
    a['margin'] = a.apply(lambda x: np.max(x) - np.min(x), axis=1)
    print(a)
    
                   a         b         c       max       min    margin
    A      -0.137231 -2.008153 -0.766172 -0.137231 -2.008153  1.870922
    B       0.473756 -0.071421  1.549933  1.549933 -0.071421  1.621354
    C       1.057641  0.375983 -0.647798  1.057641 -0.647798  1.705439
    max     1.057641  0.375983  1.549933  1.549933  0.375983  1.173950
    min    -0.137231 -2.008153 -0.766172 -0.137231 -2.008153  1.870922
    margin  1.194872  2.384135  2.316105  2.384135  1.194872  1.189263
    

    我们对轴要牢记, 0是在每一列上做, 1是在每一行上做. 这个例子希望大家好好理解.

    我们如果想元素级的调用我们的函数, 我们可以用函数applymap函数:

    print(a)
    
                   a         b         c       max       min    margin
    A      -0.137231 -2.008153 -0.766172 -0.137231 -2.008153  1.870922
    B       0.473756 -0.071421  1.549933  1.549933 -0.071421  1.621354
    C       1.057641  0.375983 -0.647798  1.057641 -0.647798  1.705439
    max     1.057641  0.375983  1.549933  1.549933  0.375983  1.173950
    min    -0.137231 -2.008153 -0.766172 -0.137231 -2.008153  1.870922
    margin  1.194872  2.384135  2.316105  2.384135  1.194872  1.189263
    

    如果我们想要把小数保留两位, 怎么搞呢, 我们可以看看在python中怎么保留两位小数的

    x = 0.123456
    print('%.2f' %  x)
    
    0.12
    

    我们可以这么来

    print(a)
    
    b = a.copy()
    
    
    b = b.applymap(lambda x: float('%.2f' %  x))
    print("---------------------------------------------------------------------------------------------------------")
    print(b)
    
                   a         b         c       max       min    margin
    A      -0.137231 -2.008153 -0.766172 -0.137231 -2.008153  1.870922
    B       0.473756 -0.071421  1.549933  1.549933 -0.071421  1.621354
    C       1.057641  0.375983 -0.647798  1.057641 -0.647798  1.705439
    max     1.057641  0.375983  1.549933  1.549933  0.375983  1.173950
    min    -0.137231 -2.008153 -0.766172 -0.137231 -2.008153  1.870922
    margin  1.194872  2.384135  2.316105  2.384135  1.194872  1.189263
    ---------------------------------------------------------------------------------------------------------
               a     b     c   max   min  margin
    A      -0.14 -2.01 -0.77 -0.14 -2.01    1.87
    B       0.47 -0.07  1.55  1.55 -0.07    1.62
    C       1.06  0.38 -0.65  1.06 -0.65    1.71
    max     1.06  0.38  1.55  1.55  0.38    1.17
    min    -0.14 -2.01 -0.77 -0.14 -2.01    1.87
    margin  1.19  2.38  2.32  2.38  1.19    1.19
    

    ** 作业3: 对整个表格的浮点数进行四舍五入. **

    排序函数

    排序一直是一个很重要的课题,

    a = Series(range(4), index=['a', 'c', 'b', 'd'])
    print(a)
    print("--------------------------------")
    print(a.sort_index())
    print("--------------------------------")
    print(a.sort_index(ascending=False))
    
    a    0
    c    1
    b    2
    d    3
    dtype: int32
    --------------------------------
    a    0
    b    2
    c    1
    d    3
    dtype: int32
    --------------------------------
    d    3
    c    1
    b    2
    a    0
    dtype: int32
    

    我们可以发现, sort_index这个函数在Series上是按照index来排序的.

    对于DataFrame来说, 我们可以按照某一列来排序, 用sort_values函数.

    data = np.random.randn(3, 3)
    
    a = DataFrame(data, index=['A', 'B', 'C'], columns=['a', 'b', 'c'])
    
    print(a)
    
    print('--------------------------------------------------------------------')
    
    print(a.sort_values(by='b'))
    
              a         b         c
    A -0.247148  0.117866  0.485004
    B -1.303519 -1.073757 -1.265169
    C  0.647247  1.171883 -0.301084
    --------------------------------------------------------------------
              a         b         c
    B -1.303519 -1.073757 -1.265169
    A -0.247148  0.117866  0.485004
    C  0.647247  1.171883 -0.301084
    

    另外, 我们要注意的是, 这个索引是可以用重复的, 我们可以来看看:

    data = np.random.randn(3, 3)
    
    a = DataFrame(data, index=['A', 'B', 'B'], columns=['a', 'b', 'c'])
    
    print(a.loc['B'])
    
              a         b         c
    B -0.364841  0.765296  1.869450
    B  0.624467  0.929586  0.673822
    
    汇总计算函数

    把一串数字经过计算变成一个数字, 这样的操作, 我们称之为汇总. 我们有很多的函数可以帮助我们完成汇总的操作,

    比如mean, sum, media等等, 下面我们来看看这些例子.

    data = {'a': list(range(1, 4)), 'b': list(range(1, 4)), 'c': list(range(1, 4))}
    
    frame = DataFrame(data, index=['A', 'B', 'C'])
    
    print(frame)
    
    print('--------------------------------------------------------------------------')
    
    # 把每一行加起来求和
    print(frame.sum())
    
    print('--------------------------------------------------------------------------')
    
    # 把每一列加起来求和
    print(frame.sum(axis=1))
    
    print('--------------------------------------------------------------------------')
    
    frame['sum'] = frame.sum(axis=1)
    frame.loc['sum'] = frame.sum()
    print(frame)
    
    print('--------------------------------------------------------------------------')
    
    frame = DataFrame(data, index=['A', 'B', 'C'])
    frame['sum'] = frame.median(axis=1)
    frame.loc['sum'] = frame.median()
    print(frame)
    
       a  b  c
    A  1  1  1
    B  2  2  2
    C  3  3  3
    --------------------------------------------------------------------------
    a    6
    b    6
    c    6
    dtype: int64
    --------------------------------------------------------------------------
    A    3
    B    6
    C    9
    dtype: int64
    --------------------------------------------------------------------------
         a  b  c  sum
    A    1  1  1    3
    B    2  2  2    6
    C    3  3  3    9
    sum  6  6  6   18
    --------------------------------------------------------------------------
           a    b    c  sum
    A    1.0  1.0  1.0  1.0
    B    2.0  2.0  2.0  2.0
    C    3.0  3.0  3.0  3.0
    sum  2.0  2.0  2.0  2.0
    

    在这里我们要单独讲一讲这个NaN的值的处理, NaN可以选择跳过, 也可以不跳过, 我们来看看:

    data = {'a': list(range(1, 4)), 'b': list(range(1, 4)), 'c': list(range(1, 4))}
    
    frame = DataFrame(data, index=['A', 'B', 'C'])
    
    frame['a']['A'] = np.nan
    
    print(frame)
    
    print(frame.sum())
    
         a  b  c
    A  NaN  1  1
    B  2.0  2  2
    C  3.0  3  3
    a    5.0
    b    6.0
    c    6.0
    dtype: float64
    

    我们发现, 这个NaN被略过去了, 我们也可以选择不略过去.

    print(frame.sum(skipna=False))
    
    a    NaN
    b    6.0
    c    6.0
    dtype: float64
    

    我们这里要提两个数学概念, 协方差和相关系数, 我们来看看这两个的定义:

    协方差:

    [Cov(X, Y) = E[(X - E[X])(Y - E[Y])] = frac{1}{n^2}sum_{i=1, j=1}^n(X_{i}Y_{j}-ar{X}ar{Y}) ]

    这是我们协方差的定义, 我们可以看看相关系数的定义:

    [ ho = frac{ Cov(X, Y)}{sigma_{X}sigma_{Y}} ]

    这样, 我们就把这两个概念用公式来表达出来了, 我们来看看具体怎么计算.

    data = np.random.randn(3, 3)
    
    a = DataFrame(data, index=['A', 'B', 'B'], columns=['a', 'b', 'c'])
    
    print(a.corr())
    
    print(a.cov())
    
              a         b         c
    a  1.000000 -0.804968 -0.630290
    b -0.804968  1.000000  0.046734
    c -0.630290  0.046734  1.000000
              a         b         c
    a  0.281901 -0.189824 -0.155039
    b -0.189824  0.197264  0.009616
    c -0.155039  0.009616  0.214637
    

    **作业4: 了解一下相关系数和协方差的数学意义.https://www.zhihu.com/question/20852004 **

    另外, 我们还有一个非常实用的函数, pd.value_counts

    data = {'a': list(range(1, 4)), 'b': list(range(1, 4)), 'c': list(range(1, 4))}
    
    frame = DataFrame(data, index=['A', 'B', 'C'])
    
    print(frame.apply(pd.value_counts))
    
       a  b  c
    3  1  1  1
    2  1  1  1
    1  1  1  1
    

    a, b c三列中, 1, 2, 3各出现1次.

    print(frame.apply(pd.value_counts, axis=1).fillna(0))
    
         1    2    3
    A  3.0  0.0  0.0
    B  0.0  3.0  0.0
    C  0.0  0.0  3.0
    

    A行1出现3次, B行2出现3次, C行3出现3次

    缺失值的处理

    我们这里要谈一个非常重要的概念, 缺失值的处理, 大致上看, 关于缺失值, 可以用丢弃和填充两种方法.

    因为我们拿到的数据, 不可能所有都是完整的, 所以我们需要对这些缺失值进行处理

    首先, 我们来看看怎么判断有缺失值, 我们可以用isnull来判断:

    data = np.random.randn(3, 3)
    
    a = DataFrame(data, index=['A', 'B', 'C'], columns=['a', 'b', 'c'])
    
    a['a']['A'] = None
    
    a['b']['C'] = None
    
    print(a)
    
              a         b         c
    A       NaN -1.577756  0.572846
    B -1.045493 -0.852665 -0.374464
    C -1.419523       NaN  0.267812
    
    print(a.isnull())
    
           a      b      c
    A   True  False  False
    B  False  False  False
    C  False   True  False
    

    进一步我们看看每一列都有多少NaN值.

    print(a.isnull().sum())
    print(a.isnull().sum(axis=1))
    
    a    1
    b    1
    c    0
    dtype: int64
    A    1
    B    0
    C    1
    dtype: int64
    

    我们可以过滤掉所有的有NaN的行或者列, 我们来看看:

    print(a.dropna())
    
    print("-------------------------------------")
    
    print(a.dropna(axis=1))
    
    print("-------------------------------------")
    
    print(a.dropna(how='all'))
    
              a         b         c
    B -1.045493 -0.852665 -0.374464
    -------------------------------------
              c
    A  0.572846
    B -0.374464
    C  0.267812
    -------------------------------------
              a         b         c
    A       NaN -1.577756  0.572846
    B -1.045493 -0.852665 -0.374464
    C -1.419523       NaN  0.267812
    

    我们来看看怎么对于缺失值来进行填充, fillna我们在前面已经看过一个具体的例子了, 我们来看看别的例子:

    print(a.fillna({'a':0, 'b':1})) # 这是用不同值对不同列进行na的填充
    
    print(a.fillna(Series({'a':0, 'b':1})))
    
              a         b         c
    A  0.000000 -1.577756  0.572846
    B -1.045493 -0.852665 -0.374464
    C -1.419523  1.000000  0.267812
              a         b         c
    A  0.000000 -1.577756  0.572846
    B -1.045493 -0.852665 -0.374464
    C -1.419523  1.000000  0.267812
    

    作业5: 熟悉一下fillna的method参数已经他们的用法.

    下面我们来看看怎么用各行的均值来填充缺失值.

    print(a.fillna(a.mean()))
    
              a         b         c
    A -1.232508 -1.577756  0.572846
    B -1.045493 -0.852665 -0.374464
    C -1.419523 -1.215210  0.267812
    

    注意到, 这个均值是沿着axis=0, 也就是把每行汇总计算得到的.

    整数索引

    我们这里要谈一个很有意思的问题, 来看看这么个例子:

    data = {'a': list(range(1, 4)), 'b': list(range(1, 4)), 'c': list(range(1, 4))}
    
    frame = DataFrame(data, index=['A', 'B', 'C'])
    
    print(frame.loc['A':'B'])
    print("--------------------------------------------")
    print(frame.iloc[0: 1, 0:1])
    print("--------------------------------------------")
    print(frame.loc['A':'B', 'a':'b'])
    
       a  b  c
    A  1  1  1
    B  2  2  2
    --------------------------------------------
       a
    A  1
    --------------------------------------------
       a  b
    A  1  1
    B  2  2
    

    我们发现, 对于标签, 我们两个端点都是可以取到的, 但是对于数字索引, 是前闭后开.

    但是, 如果是对于缩索引, 本身就是整数, 会发生什么呢?

    frame = DataFrame(data, index=[1, 2, 3])
    
    print(frame)
    
       a  b  c
    1  1  1  1
    2  2  2  2
    3  3  3  3
    
    print(frame.iloc[0: 1])
    
       a  b  c
    1  1  1  1
    
    print(frame.loc[1:2])
    
       a  b  c
    1  1  1  1
    2  2  2  2
    

    我们发现, 这个loc函数, 还是保留了标签, 把这个整数当做标签来处理, 两个端点都是闭的, 而iloc是当做整数索引来处理, 前闭后开.

  • 相关阅读:
    6.linux下指定项目使用特定jdk
    5.linux 执行shell报bad interpreter:No such file or directory错误
    定时任务基础版本
    同一台电脑安装两个jdk切换问题
    接口如何设计?安全如何保证?签名如何实现?防重如何实现?
    spring boot常见get 、post请求参数处理
    bat例子
    1.Volatile关键字详解
    1.linux目录
    解析xml报文,xml与map互转
  • 原文地址:https://www.cnblogs.com/songfy/p/8445236.html
Copyright © 2020-2023  润新知