01_Python NumPy数组

2019.3.23

因为自己没什么动力,真的很久没有顺着自己的心思来学习了,趁着有数据分析的课,今天一大早起来学习一下Numpy库的使用。特以此文记录学习进度。


Numpy

一.ndarray数组的创建


1. 概述

numpy官网

NumPy是使用Python进行科学计算的基础包它包含其他内容:一个强大的N维数组对象、复杂的(广播)功能、用于集成C / C ++和Fortran代码的工具、有用的线性代数,傅里叶变换和随机数功能除了明显的科学用途外,NumPy还可以用作通用数据的高效多维容器。可以定义任意数据类型。这使NumPy能够无缝快速地与各种数据库集成Numpy具有两类对象,分别是ndarray(N-dimensional Array Object)以及ufunc(Universal Function Object),前者类似于多维数组,后者则是可以对前者操作的函数。



2. 基本方法


  1. numpy.array(object, dtype=None, copy=True, order='K', subok=False, ndmin=0)

numpy.array()是最原始的手动生成ndarray对象的方法。其中的object 需传入一个数组对象(n维)。注:当ndarray的维度过大时,numpy的输出会折叠中间结果。如果想要取消折叠。需要这样设置

np.set_printoptions(threshold=np.nan)
# Use the numpy.array to create the ndarray
import numpy as np
array1 = np.array([[1, 2, 3], [4, 5, 6]]) #必须传入一个列表或数组
"""Output: 
[[1 2 3]
 [4 5 6]]
"""
  • 常用属性

    常用属性 属性说明
    ndim 矩阵的秩,即轴的数量或维度的数量
    shape 数组的维度,对于矩阵,n 行 m 列
    size 数组元素的总个数,相当于 .shape 中 nm 的值*
    dtype ndarray 对象的元素类型
    real ndarray元素的实部
    imag ndarray 元素的虚部
  • 使用样例

    # Use the numpy.array to create the ndarray
    import numpy as np
    array1 = np.array([[1, 2, 3], [4, 5, 6]])
    print(array1.ndim)
    """ Output: 2 """
    

  1. arange([start]stop[,step], dtype=Nope)

numpy.arange()用于生成一个指定步长的等差数组其做法与range()相似,包括start而不包括stop。其中start和step为可选参数,默认start为0,step为1;stop指定了区间的结束(开区间);dtype默认为Nope可惜的是,无法指定其形状shape,故只能通过修改shape的值的方法来生成多维数组。

  • 使用样例

    # Use the numpy.array to create the ndarray
    import numpy as np
    print("利用arange()来创建一个ndarray:", np.arange(0, 1, 0.1))
    """ Output: 利用arange()来创建一个ndarray: [0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9] """
    

  1. numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)

numpy.logspace()用于创建一个等比数组其中start, stop 都是必须给出的参数,表示区间(规则与range()相同)。num表示元素的个数,默认50。在闭合区间[start,stop]或半开区间[start,stop]中存在数量等间距的样本(取决于端点是True还是False)


  1. numpy.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=0)

numpy.logspace()与numpy.lonspqce()的区别在于,前者多了一个参数base,这意味着numpy.logspace()是根据10为底数来创建等比数组的(当然,可以传入别的值作为底),start与stop将被理解为“在[10^start, 10^stop]区间内构建等比数组”


  1. 几个构建特殊矩阵数组的函数(不予以例子说明)

numpy.zeros()需要一个元组类似于(3,4)来指定形状,元素全部用0充填
numpy.ones()需要一个元组类似于(3,4)来指定形状,元素全部用1充填
numpy.eye()只需传入一个代表维数的int型整数即可,生成一个单位n维矩阵
numpy.diag()需要传入一个具有n个元素的一维数组, 生成一个n维的,对角线上的元素依次为传入的一维数组的元素的矩阵(类似于对角矩阵)



二.Numpy的各种操作方式


  1. 矩阵运算
import numpy as np
a = np.array([20, 30, 40, 50])
b = np.arange(4)
print(a-b)
""" Output: [20 29 38 47] """
print(b**2)
""" Output: [0 1 4 9] """
print(10*np.sin(a))
""" Output: array([ 9.12945251, -9.88031624,  7.4511316 , -2.62374854]) """
print(a<35)
""" Output: [ True  True False False] """

与大部分的数学语言(如MATLAB)不同,Numpy中的乘号(*) 的数组运算是求元素积,而不是数量积(矩阵相乘)。如果需要求数量积,就需要使用@或者dot()。其他的诸如加减除(+ - /)等运算符,均在Numpy中通用。还有一些诸如求和,求最大最小值的函数也可用(sum(), min()等)。

import numpy as np
A = np.array([[1, 1],  [0, 1]]) 
B = np.array([[2, 0],  [3, 4]])
print(A * B)
""" Output: 
[[2, 0]
 [0, 4]]
"""
print(A @ B)
""" Output: 
[[5, 4]
 [3, 4]]
"""
print(A.dot(B)) 
""" Output:
[5, 4]
 [3, 4]]
"""

  1. 通用函数

一些通用的数学函数,例如sin、cos、exp等,此类函数被称作 通用函数,其操作的对象也是数组的元素,即元素积之类的。

import numpy as np
B = np.arange(3)
print(np.exp(B))
""" Output: [1.         2.71828183 7.3890561 ] """
print(np.sqrt(B))
""" Output: [0.         1.         1.41421356] """

  1. 索引

ndarray的索引使用方法与列表的写法相近。如果是多维的数组则每一维的索引用逗号分隔。 其中还有一种比较有趣的写法--- 省略号:表示全集(即那个维度的全部元素)。索引甚至可以是一个数组,表示一次索引多个值、还可以是布尔表达式。 还有更多的高级玩法就不一一演示了。

import numpy as np
a = np.arange(10)**3 # 幂的写法,表示3次方
print(a[2:5])
""" Output: [ 8 27 64] """
def f(x, y):
  return 10*x + y
# fromfunction()可以从一个函数中获得数据来创建ndarray
b = np.fromfunction(f, (5, 4), dtype=int) 
print(b[1:3, 2:3])
"""Output:
[[12]
 [22]]
"""
print(b[:2 ,...]) #表示第二维输出全部元素
"""Output:
[[ 0  1  2  3]
 [10 11 12 13]]
"""
print(b[..., :2]) #表示第一维输出所有元素
"""Output:
[[ 0  1]
 [10 11]
 [20 21]
 [30 31]
 [40 41]]
"""

  1. 遍历

对一个多维的ndarray对象使用迭代器的话,默认是遍历一行。

import numpy as np
def f(x, y):
  return 10*x + y
b = np.fromfunction(f, (5, 4), dtype=int) 
for row in b:
  print(row)
"""Output:
[0 1 2 3]
[10 11 12 13]
[20 21 22 23]
[30 31 32 33]
[40 41 42 43]
"""
for elements in b.flat:
    print(elements)
"""Output:
0
1
2
3
...
"""

  1. 维度控制

numpy中有很多函数可以改变一个ndarray的维度。以下列出几个常用的。

  • ravel(): 对多维的矩阵进行降到一维的操作。并且,numpy.ravel()返回的是视图,会影响原始矩阵。
  • flatten():功能与ravel()一致。但其是对矩阵的一个深拷贝进行操作,所以不会改变原矩阵。(不予以例子)
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
print(a) # 输出原矩阵
"""Output:
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]
"""
a = a.ravel()
print(a) #输出降维的矩阵,发现确实改变了原矩阵
"""Output: [ 1  2  3  4  5  6  7  8  9 10 11 12] """
  • reshape()与resize():两者的功能都是将矩阵改变成指定的维度。reshape()传入一个元组,表示指定的维度(要合理);resize()需要传入矩阵,和一个指定的元组。区别是,resize()会改变原矩阵。
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
print(a.reshape(3, 4))
"""Output:
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
"""Output:
print(a) # 原数组并没有被改变
"""Output:
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]
"""
print(np.resize(a, (3, 4))) # 必须这样来调用
"""Output:
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
"""
print(a) # 原矩阵被改变
"""Output:
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
"""
print(a.reshape(2, -1)) # 可以传入-1,numpy会自动计算剩下的维度,但还是要合理
"""Output:
[[ 1  2  3  4  5  6]
 [ 7  8  9 10 11 12]]
"""

  1. 复制

一般的矩阵复制并不会复制任何内存(只是改变了标签名)。 而视图(view)是矩阵的一个浅拷贝,虽不是原矩阵(即会另外分配内存),但对视图的操作会影响到原矩阵。 深复制则是另外分配内存,把原矩阵所有值复制过来,操作不会改变原矩阵。

import numpy as np
a = np.arange(12).reshape(3, 4)
b = a
b is a # True表示b和a是同一个内存对象
"""Output: True """
c = a.view()
c is a # c并不和a是同一个对象
"""Output: False """ 
print(a) # 输出原矩阵
"""Output:
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
"""
c[0, 0] = 111
print(a) # 改变视图,原矩阵元素改变
"""Output:
[[111   1   2   3]
 [  4   5   6   7]
 [  8   9  10  11]]
"""
b = a.copy()
b is a # 深拷贝不是同一对象
"""Output: False """
b[0, 0] = 222
print(a) # 深拷贝的操作不会改变原矩阵
"""Output:
[[111   1   2   3]
 [  4   5   6   7]
 [  8   9  10  11]]
"""


更多的进阶功能:
官方教程
函数详细说明文档及手册



三.实例联系:康威生命棋(用Numpy和pygame模拟)

剑桥大学 约翰·何顿·康威(John Horton Conway) 教授设计了一个叫做“生命游戏”的计算机程序,生命游戏是一个二维网格游戏,这个网格中每个方格居住着一个活着或死了的细胞。一个细胞在下一个时刻的生死取决于相邻8个方格中活着或死了的细胞的数量。如果相邻方格活着的细胞数量过多,这个细胞会因为资源匮乏而在下一个时刻死去;相反,如果周围活细胞过少,这个细胞会因为孤单而死去。

大致规则
(1)当前细胞为死亡状态时,当周围有3个存活细胞时,则迭代后该细胞变成存活状态(模拟繁殖);若原先为生,则保持不变。
(2)当前细胞为存活状态时,当周围的邻居细胞低于两个(不包含两个)存活时,该细胞变成死亡状态(模拟生命数量稀少)。
(3)当前细胞为存活状态时,当周围有两个或3个存活细胞时,该细胞保持原样。
(4)当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成死亡状态(模拟生命数量过多)。

这里就不多说什么了,直接上训练的代码。

import sys
import numpy as np # numpy用于存储康威生命棋的矩阵
import pygame # pygame可以提供游戏窗口


def life_step(x, y, world):
    # sum(a[, axis, dtype, out, keepdims]) 给定轴上的数组元素的总和
    neighbours = np.sum(world[x-1:x+2, y-1:y+2])-world[x, y]
    if world[x, y] == 1 and not 2 <= neighbours <= 3:
         return 0
    elif neighbours == 3:
         return 1
    return world[x, y]


def main():
    screen_size = 500
    tile_size = 10
    background_color = (0, 0, 0)
    cell_color = (255, 55, 255)
    pygame.init()
    screen = pygame.display.set_mode((screen_size, screen_size))
    pygame.display.set_caption('Convay\'s Game of Life')
    clock = pygame.time.Clock()
    world = np.random.choice(a=[0], size=(screen_size // tile_size + 1, screen_size // tile_size+1))
    gun = [(5, 1), (5, 2), (6, 1), (6, 2), (5, 11), (6, 11), (7, 11), (4, 12),
              (3, 13), (3, 14), (8, 12), (9, 13), (9, 14), (6, 15), (4, 16), (5, 17),
              (6, 17), (7, 17), (6, 18), (8, 16), (3, 21), (4, 21), (5, 21), (3, 22),
              (4, 22), (5, 22), (2, 23), (6, 23), (1, 25), (2, 25), (6, 25), (7, 25),
              (3, 35), (4, 35), (3, 36), (4, 36)]

    # 根据gun里的元素,将world相应位置的元素设置为1
    for i, j in gun:
        world[j, i] = 1

    fps = 0
    epoch = 0

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
        pygame.display.set_caption("Convay\'s Game of Life /" + str(fps) +"FPS /" + str(epoch) + "epoch")
        screen.fill(background_color)
        new_world = np.copy(world)
        for (x, y), value in np.ndenumerate(world):
            new_world[x, y] = life_step(x, y, world)
            if new_world[x, y] == 1:
                pygame.draw.rect(screen, cell_color, (tile_size*(x-1), tile_size*(y-1), tile_size, tile_size), 0)
        world = new_world
        epoch += 1
        pygame.display.update()
        clock.tick(fps)


if __name__ == '__main__':
    main()

运行截图

康威生命棋01.png
康威生命棋02.png


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容

  • 基础篇NumPy的主要对象是同种元素的多维数组。这是一个所有的元素都是一种类型、通过一个正整数元组索引的元素表格(...
    oyan99阅读 5,120评论 0 18
  • 先决条件 在阅读这个教程之前,你多少需要知道点python。如果你想从新回忆下,请看看Python Tutoria...
    舒map阅读 2,572评论 1 13
  • NumPy是Python中关于科学计算的一个类库,在这里简单介绍一下。 来源:https://docs.scipy...
    灰太狼_black阅读 1,227评论 0 5
  • 介绍 NumPy 是一个 Python 包。 它代表 “Numeric Python”。 它是一个由多维数组对象和...
    喔蕾喔蕾喔蕾蕾蕾阅读 1,770评论 0 5
  • 一、numpy概述 numpy(Numerical Python)提供了python对多维数组对象的支持:ndar...
    L_steven的猫阅读 3,461评论 1 24