V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
bboyliu
V2EX  ›  Python

Scipy & Numpy 操作多维数组

  •  1
     
  •   bboyliu · 2016-03-02 18:48:46 +08:00 · 3392 次点击
    这是一个创建于 3217 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Arrays 是 Scipy 的 核心数据类型( Numpy 是 Scipy 的子集, 可以以同样的方式来访问数组对象。所以,这里将一致使用 Scipy 来介绍如何操作 数组对象)。严格来讲,数组对象的类型是 ndarray , 即 n-dimentional array 。通过 引入 scipy 模块,便可操作访问 数组对象。数组对象 类似与 Python Lists , 不同的是,数组对象是多维的数组,支持简洁有效的数组级别的操作。

    数据结构图

    Anatomy of an array

    引入 Scipy 模块

    >>> import scipy
    

    构建数组

    • 利用 scipy.array(alist) 构建多维数组
      ```

      a = scipy.array([[1, 2, 3], [4, 5, 6]]) # 构建 2 * 3 数组
      array([[1, 2, 3],[4, 5, 6]])

      b = scipy.array([i * i for i in range(10) if i % 2 == 1]) # 构建 1 * 10 的随机数组请查看
      array([ 1, 9, 25, 49, 81])

      c = b.tolist() # 转换成 python list
      [1, 9, 25, 49, 81]

      ```

    • 通过 scipy.zeros(shape, dtype=float) 构建数组对象

      返回 一个 shape 指定的 数组,并填充值 0 到所有元素。
      ```

      a = scipy.zeros(100) # 构建 1 * 100 数组
      array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])

      b = scipy.zeros((2, 8), int) # 构建 2 * 8 数组
      array([[0, 0, 0, 0, 0, 0, 0, 0],
      [0, 0, 0, 0, 0, 0, 0, 0]])

      c = scipy.zeros((2, 2, 2), int) # 构建 2 * 2 * 2 数组
      array(
      [
      [
      [0, 0],
      [0, 0]
      ],
      [
      [0, 0],
      [0, 0]
      ]
      ]
      )
      ```

    • 通过 scipy.ones(shape, dtype=float) 构建数组对象

      返回 一个 shape 指定的 数组,并填充值 1 到所有元素。
      ```

      scipy.ones(5) # 构建 1 * 5 的数组, 并填充 1. 到数组中
      array([ 1., 1., 1., 1., 1.])

      scipy.ones(10, int) # 构建 1 * 10 的数组, 并填充 1 到数组中
      array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])

      scipy.pi * scipy.ones((5, 5)) # 构建 5 * 5 的数组, 并填充 pi 到数组中
      array([[ 3.14159265, 3.14159265, 3.14159265, 3.14159265, 3.14159265],
      [ 3.14159265, 3.14159265, 3.14159265, 3.14159265, 3.14159265],
      [ 3.14159265, 3.14159265, 3.14159265, 3.14159265, 3.14159265],
      [ 3.14159265, 3.14159265, 3.14159265, 3.14159265, 3.14159265],
      [ 3.14159265, 3.14159265, 3.14159265, 3.14159265, 3.14159265]])

    • 通过 scipy.eye(N, M=None, k-0, dtype=float) 构建数组对象

      返回一个 2-D(二维) 数组, k 对角线上是 1 , 其他元素都是 0, M 默认是 N
      ```

      scipy.eye(5, 5, 1, int)
      array([[0, 1, 0, 0, 0],
      [0, 0, 1, 0, 0],
      [0, 0, 0, 1, 0],
      [0, 0, 0, 0, 1],
      [0, 0, 0, 0, 0]])

      scipy.eye(10, 10, 1, int) + scipy.eye(10, 10, -1, int)
      array([[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
      [1, 0, 1, 0, 0, 0, 0, 0, 0, 0],
      [0, 1, 0, 1, 0, 0, 0, 0, 0, 0],
      [0, 0, 1, 0, 1, 0, 0, 0, 0, 0],
      [0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
      [0, 0, 0, 0, 1, 0, 1, 0, 0, 0],
      [0, 0, 0, 0, 0, 1, 0, 1, 0, 0],
      [0, 0, 0, 0, 0, 0, 1, 0, 1, 0],
      [0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
      [0, 0, 0, 0, 0, 0, 0, 0, 1, 0]])
      ```

    • 通过 scipe.transpose(a) 构建数组

      返回一个 指定 数组的 转置 数组

      >>> a = scipy.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
      >>> scipy.transpose(a)
      array([[ 1,  6],
             [ 2,  7],
             [ 3,  8],
             [ 4,  9],
             [ 5, 10]])
      >>> a.T                    # 等价于  scipy.transpose(a)
      array([[ 1,  6],
         [ 2,  7],
         [ 3,  8],
         [ 4,  9],
         [ 5, 10]])
      
    • 通过 scipy.arange(start, stop, increment) 构建数组对象

      返回 1 * N 维数组, 其值的生成 等同于 Python range 函数

      >>> scipy.arange(3)
      array([0, 1, 2])
      
      >>> scipy.arange(1, 10, 2)
      array([1, 3, 5, 7, 9])
      
    • 通过 scipy.linspace(start, stop, num_elements) 构建数组对象

    • 通过 scipy.random 随机数组构造器 构建数组对象

      >>> scipy.random.random((5, 5))    # 5 * 5 数组, 每个元素的值是 [0., 1.)的随机数
      array([[ 0.54835728,  0.68842299,  0.27092076,  0.97736089,  0.70871043],
             [ 0.75544761,  0.68802281,  0.67291087,  0.27854031,  0.48492923],
             [ 0.48325973,  0.99010961,  0.84767   ,  0.94258563,  0.99792361],
             [ 0.27465145,  0.61586656,  0.59351729,  0.73674333,  0.80784786],
             [ 0.08397848,  0.77584239,  0.65946262,  0.11980866,  0.47662084]])
      
      >>> scipy.random.randint(0, 10, (5, 5)) # 5 * 5 数组,每个元素的值是 [ 0 , 10 )的随机数
      array([[8, 3, 0, 3, 3],
             [5, 9, 9, 8, 7],
             [2, 0, 0, 5, 4],
             [2, 6, 2, 3, 3],
             [8, 8, 8, 5, 5]])
      

    数组索引

    • 多维数组 索引

      >>> a = scipy.random.randint(1, 10, (5, 5, 5))
      array([[[7, 4, 5, 7, 2],
              [7, 9, 5, 4, 1],
              [2, 8, 5, 6, 4],
              [4, 5, 3, 3, 1],
              [8, 6, 9, 9, 2]],
      
             [[3, 7, 3, 4, 7],
              [1, 7, 1, 2, 1],
              [3, 9, 4, 9, 1],
              [7, 6, 7, 9, 6],
              [4, 5, 6, 8, 4]],
      
             [[2, 1, 8, 9, 4],
              [1, 7, 9, 3, 3],
              [8, 6, 1, 6, 7],
              [1, 2, 7, 5, 5],
              [9, 9, 5, 7, 8]],
      
             [[6, 6, 7, 4, 8],
              [3, 4, 3, 1, 1],
              [5, 8, 1, 4, 6],
              [2, 9, 8, 1, 7],
              [9, 7, 4, 1, 1]],
      
             [[4, 9, 7, 6, 6],
              [9, 8, 5, 2, 7],
              [3, 7, 3, 1, 3],
              [2, 9, 6, 1, 4],
              [3, 3, 7, 1, 8]]])
      
      >>> a[1, 3, 4]
      7
      
      Error: language "请查看" is not supported
    • 反向索引

      >>> a = scipy.random.randint(1, 10, (5, 5))
      array([[7, 9, 1, 8, 3],
             [8, 4, 1, 4, 1],
             [9, 7, 5, 1, 2],
             [7, 4, 7, 3, 9],
             [7, 7, 6, 3, 8]])
      
      >>> a[-1, -2]
      3
      

    数组切片

    ```
    >>> a = scipy.random.randint(1, 10, (5, 5))
    array([[2, 9, 2, 6, 4],
           [3, 4, 3, 7, 5],
           [8, 6, 4, 1, 3],
           [5, 9, 2, 3, 5],
           [7, 9, 4, 2, 7]])
    
    >>> a[1:3, 2:4]
    array([[3, 7],
          [4, 1]])
    
    >>> a[:3, 2:]
    array([[2, 6, 4],
           [3, 7, 5],
           [4, 1, 3]])
    ```
    

    加减乘除

    >>> a = scipy.ones((3, 3), int)
    >>> b = 2 * scipy.ones((3, 3), int)
    >>> a + b
    array([[3, 3, 3],
           [3, 3, 3],
           [3, 3, 3]])
    
    >>> a * b
    array([[2, 2, 2],
           [2, 2, 2],
           [2, 2, 2]])
    
    >>> c = scipy.random.randint(1, 10, (3, 3))
    array([[3, 6, 4],
           [6, 2, 8],
           [2, 1, 9]])
    >>> b * c
    array([[ 4,  4,  2],
           [18, 14,  6],
           [16,  6,  2]])
    

    数组 三角函数 处理

    >>> a = scipy.ones((3, 3))
    >>> scipy.sin(a)
    array([[ 0.84147098,  0.84147098,  0.84147098],
           [ 0.84147098,  0.84147098,  0.84147098],
           [ 0.84147098,  0.84147098,  0.84147098]])
    
    >>> scipy.cos(a)
    array([[ 0.54030231,  0.54030231,  0.54030231],
           [ 0.54030231,  0.54030231,  0.54030231],
           [ 0.54030231,  0.54030231,  0.54030231]])
    

    数组求和

    • 简单的求和

      >>> a = scipy.random.randint(1, 10, (3, 3)) 
      array([[3, 6, 4],
             [6, 2, 8],
             [2, 1, 9]])
      
      >>> scipy.sum(a)                  # 返回所有元素的和
      36
      
      >> scipy.sum(a, 0)                # 按照 axis = 0 (参考数据结构图) 的 求和 
      array([19, 9, 21])
      
      >>> scipy.sum(a, 1)               # 按照 axis = 1 (参考数据结构图) 的 求和
      array([13, 16, 12])
      
    • 平均值

      >>> a = scipy.random.randint(1, 10, (3, 3)) 
      array([[9, 4, 5],
             [2, 4, 5],
             [3, 4, 3]]) 
      
      >>> scipy.mean(a, 0) # 求平均值
      array([ 4.66666667,  4.        ,  4.33333333])
      
      >>> scipy.std(a, 0)  # 求标准差      
      array([ 3.09120617,  0.        ,  0.94280904])
      
    • 累加

      >>> a = scipy.random.randint(1, 10, (3, 3)) 
      array([[9, 4, 5],
             [2, 4, 5],
             [3, 4, 3]]) 
      
      >>> scipy.cumsum(a, 0) # 按照 axis = 0 累加
      array([[ 9,  4,  5],
             [11,  8, 10],
             [14, 12, 13]])
      
      >>> scipy.cumsum(a)
      array([ 9, 13, 18, 20, 24, 29, 32, 36, 39])
      

    其他有用的方法,请查看 Numpy Example

    翻译自refer article

    第 1 条附言  ·  2016-03-02 21:52:44 +08:00

    感谢 knightdf 的指正,以下为对本文的修正:

    修正内容一:

    构建数组

    • 利用 scipy.array(alist) 构建多维数组
    >>> a = scipy.array([[1, 2, 3], [4, 5, 6]]) # 构建 2 * 3 数组
    array([[1, 2, 3],[4, 5, 6]])
    
    >>> b = scipy.array([i * i for i in range(10) if i % 2 == 1]) # # 构建 1 * 5 的数组,且每项为 10 以内 被 2 除 模为 1 的数的平方。
    array([ 1, 9, 25, 49, 81])
    
    >>> c = b.tolist() # 转换成 python list
    [1, 9, 25, 49, 81]
    
    • 通过 scipy.zeros(shape, dtype=float) 构建数组对象

    返回 一个 shape 指定的 数组,并填充值 0 到所有元素。

    >>> a = scipy.zeros(100) # 构建 1 * 100 数组
    array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
    
    >>> b = scipy.zeros((2, 8), int) # 构建 2 * 8 数组
    array([[0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0]])
    
    >>> c = scipy.zeros((2, 2, 2), int) # 构建 2 * 2 * 2 数组
    array([[[0, 0],
          [0, 0]],
    
          [[0, 0],
          [0, 0]]])
    
    • 通过 scipy.ones(shape, dtype=float) 构建数组对象

    返回 一个 shape 指定的 数组,并填充值 1 到所有元素。

    >>> scipy.ones(5) # 构建 1 * 5 的数组, 并填充 1. 到数组中
    array([ 1., 1., 1., 1., 1.])
    
    >>> scipy.ones(10, int) # 构建 1 * 10 的数组, 并填充 1 到数组中
    array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
    
    >>> scipy.pi * scipy.ones((5, 5)) # 构建 5 * 5 的数组, 并填充 pi 到数组中
    array([[ 3.14159265, 3.14159265, 3.14159265, 3.14159265, 3.14159265],
          [ 3.14159265, 3.14159265, 3.14159265, 3.14159265, 3.14159265],
          [ 3.14159265, 3.14159265, 3.14159265, 3.14159265, 3.14159265],
          [ 3.14159265, 3.14159265, 3.14159265, 3.14159265, 3.14159265],
          [ 3.14159265, 3.14159265, 3.14159265, 3.14159265, 3.14159265]])
    

    修正内容二:

    求和

    >>> a = scipy.random.randint(1, 10, (3, 3)) 
    array([[3, 6, 4],
           [6, 2, 8],
           [2, 1, 9]])
    
    >>> scipy.sum(a)                  # 返回所有元素的和
    36
    
    >> scipy.sum(a, 0)                # 按照 axis = 0 (参考数据结构图) 的 求和 
    array([11, 9, 21])
    
    >>> scipy.sum(a, 1)               # 按照 axis = 1 (参考数据结构图) 的 求和
    array([13, 16, 12])
    
    4 条回复    2016-03-02 22:08:02 +08:00
    knightdf
        1
    knightdf  
       2016-03-02 19:37:48 +08:00   ❤️ 1
    b = scipy.array([i * i for i in range(10) if i % 2 == 1]) # 构建 1 * 10
    bboyliu
        2
    bboyliu  
    OP
       2016-03-02 20:55:36 +08:00   ❤️ 1
    @knightdf 第一次在 V2EX 上发文章,不能修改,另外,文章还有很多地方排版都不好,没办法修改了。*** 依旧谢谢你的指正 ***!!!

    针对你发的代码,正确的描述为:

    ```
    # 构建 1 * 5 的数组,且每项为 10 以内 被 2 除 模为 1 的数的平方。
    b = scipy.array([i * i for i in range(10) if i % 2 == 1])
    ```
    knightdf
        3
    knightdf  
       2016-03-02 21:00:51 +08:00   ❤️ 1
    @bboyliu 其实还有。。
    >> scipy.sum(a, 0) # 按照 axis = 0 (参考数据结构图) 的 求和
    array([19, 9, 21])
    这个 19 是怎么来的。。。。
    Kilerd
        4
    Kilerd  
       2016-03-02 22:08:02 +08:00
    没有养成发文章之前先预览的好习惯(并不是特指在 V2 )
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   881 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 20:37 · PVG 04:37 · LAX 12:37 · JFK 15:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.