美文网首页
python数据探索(1)—numpy

python数据探索(1)—numpy

作者: zhfish | 来源:发表于2018-06-05 16:33 被阅读0次

    本篇文章是python数据探索系列扫盲文章的第一篇,主要和各位朋友探讨一下numpy,后续文章会陆续介绍pandas以及Matplotlib。如有疏漏不当的地方,请留言或私信我。共同进步!
    在处理一些数据时,我们常常会需要处理数组,而使用原生的array显然会比较慢。numpy有许多用 C 语言实现的底层函数,所以我们选择使用numpy进行数据探索。

    一、数组基础

    首先,我们明确一下研究对象——数组。在numpy里我们操作的对象就是ndarrays多维数组。我们假想一个使用环境,比如读取一个股票数据。为了
    更快的使用体验,我们决定使用numpy。那么我们怎么读取这份数据呢?这涉及到numpy创建数组吧!我们来讲一下:

    # 1D Array
    a = np.array([0, 1, 2, 3, 4])
    b = np.array((0, 1, 2, 3, 4))
    c = np.arange(5)
    d = np.linspace(0, 2*np.pi, 5)
    
    print(a) # >>>[0 1 2 3 4]
    print(b) # >>>[0 1 2 3 4]
    print(c) # >>>[0 1 2 3 4]
    print(d) # >>>[ 0.          1.57079633  3.14159265  4.71238898  6.28318531]
    print(a[3]) # >>>3
    

    我们还可以使用dtype为数据指定类型。比如:

    a = np.array([2,23,4],dtype=np.int)
    print(a.dtype)
    # int 64
    

    可以指定如float(64位)int32、int32等等数据类型。
    还有一些特殊的数组,比如全零

    a = np.zeros((3,4)) # 数据全为0,3行4列
    """
    array([[ 0.,  0.,  0.,  0.],
           [ 0.,  0.,  0.,  0.],
           [ 0.,  0.,  0.,  0.]])
    """
    

    创建全一数组, 同时也能指定这些特定数据的 dtype:

    a = np.ones((3,4),dtype = np.int)   # 数据为1,3行4列
    """
    array([[1, 1, 1, 1],
           [1, 1, 1, 1],
           [1, 1, 1, 1]])
    """
    

    怎么读取文件呢?一句代码可以搞定,a就是numpy数组:

        a = numpy.loadtxt('haha.txt')  
    

    举个例子。
    以载入苹果公司的历史股价数据为例。股价数据存储在CSV文件中,第一列为股票代码以标识股票(苹果公司股票代码为AAPL),第二列为dd-mm-yyyy格式的日期,第三列为空,随后各列依次是开盘价、最高价、最低价和收盘价,最后一列为当日的成交量。下面为一行数据:

    AAPL,28-01-2011, ,344.17,344.4,333.53,336.1,21144800

    将收盘价和成交量分别载入到两个数组中,代码如下所示:

    >>> a,b=np.loadtxt("./data.csv",
    ...                delimiter=',',usecols=(6,7),unpack=True)
    >>> print a
    [ 336.1   339.32  345.03  344.32  343.44  346.5   351.88  355.2   358.16
      354.54  356.85  359.18  359.9   363.13  358.3   350.56  338.61  342.62
      342.88  348.16  353.21  349.31  352.12  359.56  360.    355.36  355.76
      352.47  346.67  351.99]
    

    delimiter=’,’表示用逗号作为分隔符,usecols=(6,7)表示一个元组,用来指明获取哪些列的字段,unpack=True是说拆分存储不同的数据,即分别将收盘价和日成交量赋值给a和b。

    现在菜已经洗好了,我们需要进行进一步的清洗。我们要做到“指哪打哪”,挑选我们真正需要的东西。
    我们先定义一个多维矩阵。多维数组切片比一维数组要复杂一点,同时它也是你在用 NumPy 的时候经常会用到的。

    # MD Array,
    a = np.array([[11, 12, 13, 14, 15],
                  [16, 17, 18, 19, 20],
                  [21, 22, 23, 24, 25],
                  [26, 27, 28 ,29, 30],
                  [31, 32, 33, 34, 35]])
    
    print(a[2,4]) # >>>25
    

    我们开始挑选我们需要的数据,其实无非就是某些数,某些行,某些列,某些块。

    # MD slicing
    print(a[0, 1:4]) # >>>[12 13 14]
    print(a[1:4, 0]) # >>>[16 21 26]
    print(a[::2,::2]) # >>>[[11 13 15]
                      #     [21 23 25]
                      #     [31 33 35]]
    print(a[:, 1]) # >>>[12 17 22 27 32]
    

    用一张图来说明情况。


    image.png

    二、数组信息获取

    还是承接上文的数据,我们获得了“我们想要的数组”,那么我们总得看看我们切的数据对不对吧?那最简单的方法就是获取下信息看看。我们可以这么做:

    # Array properties
    a = np.array([[11, 12, 13, 14, 15],
                  [16, 17, 18, 19, 20],
                  [21, 22, 23, 24, 25],
                  [26, 27, 28 ,29, 30],
                  [31, 32, 33, 34, 35]])
    
    print(type(a)) # >>><class 'numpy.ndarray'>
    print(a.dtype) # >>>int64
    print(a.size) # >>>25
    print(a.shape) # >>>(5, 5)
    print(a.itemsize) # >>>8
    print(a.ndim) # >>>2
    print(a.nbytes) # >>>200
    

    其它信息都很直观,'itemsize' 属性是每一个条目所占的字节。这个数组的数据类型是 int64,一个 int64 的大小是 64 比特,8 比特为 1 字节,64 除以 8 就得到了它的字节数,8 字节。

    三、使用数组

    既然获得的我们想要的数组。接下来我们就能对数组进行操作了。
    那么有哪些运算呢?我们来看看基本的操作。

    # Basic Operators
    >>> import numpy as np
    >>> a = np.arange(25)
    >>> print(a)
    [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
     24]
    >>> a = a.reshape((5,5))
    >>> print(a)
    [[ 0  1  2  3  4]
     [ 5  6  7  8  9]
     [10 11 12 13 14]
     [15 16 17 18 19]
     [20 21 22 23 24]]
    >>> b = np.array([10, 62, 1, 14, 2, 56, 79, 2, 1, 45,
    ...               4, 92, 5, 55, 63, 43, 35, 6, 53, 24,
    ...               56, 3, 56, 44, 78])
    >>> b = b.reshape((5,5))
    >>> print(a + b)
    [[ 10  63   3  17   6]
     [ 61  85   9   9  54]
     [ 14 103  17  68  77]
     [ 58  51  23  71  43]
     [ 76  24  78  67 102]]
    >>> print(a - b)
    [[-10 -61   1 -11   2]
     [-51 -73   5   7 -36]
     [  6 -81   7 -42 -49]
     [-28 -19  11 -35  -5]
     [-36  18 -34 -21 -54]]
    >>> print(a * b)
    [[   0   62    2   42    8]
     [ 280  474   14    8  405]
     [  40 1012   60  715  882]
     [ 645  560  102  954  456]
     [1120   63 1232 1012 1872]]
    >>> print(a / b)
    [[0.         0.01612903 2.         0.21428571 2.        ]
     [0.08928571 0.07594937 3.5        8.         0.2       ]
     [2.5        0.11956522 2.4        0.23636364 0.22222222]
     [0.34883721 0.45714286 2.83333333 0.33962264 0.79166667]
     [0.35714286 7.         0.39285714 0.52272727 0.30769231]]
    >>> print(a ** 2)
    [[  0   1   4   9  16]
     [ 25  36  49  64  81]
     [100 121 144 169 196]
     [225 256 289 324 361]
     [400 441 484 529 576]]
    >>> print(a < b)
    [[ True  True False  True False]
     [ True  True False False  True]
     [False  True False  True  True]
     [ True  True False  True  True]
     [ True False  True  True  True]]
    >>> print(a.dot(b))
    [[ 417  380  254  446  555]
     [1262 1735  604 1281 1615]
     [2107 3090  954 2116 2675]
     [2952 4445 1304 2951 3735]
     [3797 5800 1654 3786 4795]]
    
    

    除了 dot() 之外,这些操作符都是对数组进行逐元素运算。比如 (a, b, c) + (d, e, f) 的结果就是 (a+d, b+e, c+f)。它将分别对每一个元素进行配对,然后对它们进行运算。它返回的结果是一个数组。注意,当使用逻辑运算符比如 “<” 和 “>” 的时候,返回的将是一个布尔型数组。dot() 函数计算两个数组的点积。它返回的是一个标量(只有大小没有方向的一个值)而不是数组。
    dot() 函数有时候也称为点积。理解这个函数的最好方法就是看下边它的计算过程。
    盗图一张,在此感谢编程派的作者!


    image.png

    其它一些运算符:

    # dot, sum, min, max, cumsum
    a = np.arange(10)
    
    print(a.sum()) # >>>45
    print(a.min()) # >>>0
    print(a.max()) # >>>9
    print(a.cumsum()) # >>>[ 0  1  3  6 10 15 21 28 36 45]
    

    cumsum() 就是一个累加计算并且保存每次累加的结果,返回值就是包含所有累加结果的一个列表。比如 np.array([1, 2, 3, 4, 5]).cumsum() = [1, 3, 6, 10, 15]

    四、高级索引

    这个直接看例子吧!

    # Fancy indexing
    a = np.arange(0, 100, 10)
    indices = [1, 5, -1]
    b = a[indices]
    print(a) # >>>[ 0 10 20 30 40 50 60 70 80 90]
    print(b) # >>>[10 50 90]
    

    布尔屏蔽(boolean masking)
    布尔屏蔽是一个奇妙的特性,它允许我们根据指定条件获取数组中的元素。简单说,就是设置一个约束条件比如:mask=(a<0)用mask做下标,这样在检索的时候,都会检查一遍约束条件,这样就可以选出想要的结果。

    # Boolean masking
    import matplotlib.pyplot as plt
    
    a = np.linspace(0, 2 * np.pi, 50)
    b = np.sin(a)
    plt.plot(a,b)
    mask = b >= 0
    plt.plot(a[mask], b[mask], 'bo')
    mask = (b >= 0) & (a <= np.pi / 2)
    plt.plot(a[mask], b[mask], 'go')
    plt.show()
    

    上边的代码展示了实现布尔屏蔽。你需要做的就是传递给数组一个与它有关的条件式,然后它就会返回给定条件下为真的值。

    上边的例子将会生成下边这幅图,上面的点点就是筛选出的结果:


    image.png

    缺省索引是从多维数组的第一维获取索引和切片便捷方法。例如,你有一个数组 a = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]],那么 a[3] 将会返回数组第一维中索引值为 3 的元素,这里的结果是 4。

    # Incomplete Indexing
    a = np.arange(0, 100, 10)
    b = a[:5]
    c = a[a >= 50]
    print(b) # >>>[ 0 10 20 30 40]
    print(c) # >>>[50 60 70 80 90]
    

    where() 函数是另外一个根据条件返回数组中的值的有效方法。只需要把条件传递给它,它就会返回一个使得条件为真的元素的列表。

    # Where
    a = np.arange(0, 100, 10)
    b = np.where(a < 50) 
    c = np.where(a >= 50)[0]
    print(b) # >>>(array([0, 1, 2, 3, 4]),)
    print(c) # >>>[5 6 7 8 9]
    

    参考:
    编程派教程
    http://codingpy.com/article/an-introduction-to-numpy/
    莫烦的教程
    https://morvanzhou.github.io/tutorials/data-manipulation/np-pd/

    相关文章

      网友评论

          本文标题:python数据探索(1)—numpy

          本文链接:https://www.haomeiwen.com/subject/qczesftx.html