前言

Numpy是一个开源的Python科学计算库,它是python科学计算库的基础库,许多其他著名的科学计算库如Pandas,Scikit-learn等都要用到Numpy库的一些功能。

本文主要内容如下:

  1. Numpy数组对象
  2. 创建ndarray数组
  3. Numpy的数值类型
  4. ndarray数组的属性
  5. ndarray数组的切片和索引
  6. 处理数组形状
  7. 数组的类型转换
  8. numpy常用统计函数
  9. 数组的广播

1 Numpy数组对象

Numpy中的多维数组称为ndarray,这是Numpy中最常见的数组对象。ndarray对象通常包含两个部分:

  • ndarray数据本身
  • 描述数据的元数据

Numpy数组的优势

  • Numpy数组通常是由相同种类的元素组成的,即数组中的数据项的类型一致。这样有一个好处,由于知道数组元素的类型相同,所以能快速确定存储数据所需空间的大小。
  • Numpy数组能够运用向量化运算来处理整个数组,速度较快;而Python的列表则通常需要借助循环语句遍历列表,运行效率相对来说要差。
  • Numpy使用了优化过的C API,运算速度较快

关于向量化和标量化运算,对比下面的参考例子就可以看出差异

  • 使用python的list进行循环遍历运算
def pySum():
a = list(range(10000))
b = list(range(10000))
c = []
for i in range(len(a)):
c.append(a[i]**2 + b[i]**2) return c
%timeit pySum()
10 loops, best of 3: 49.4 ms per loop
  • 使用numpy进行向量化运算
import numpy as np
def npSum():
a = np.arange(10000)
b = np.arange(10000)
c = a**2 + b**2
return c
%timeit npSum()
The slowest run took 262.56 times longer than the fastest. This could mean that an intermediate result is being cached.
1000 loops, best of 3: 128 µs per loop

从上面的运行结果可以看出,numpy的向量化运算的效率要远远高于python的循环遍历运算(效率相差好几百倍)
(1ms=1000µs)

2 创建ndarray数组

首先需要导入numpy库,在导入numpy库时通常使用“np”作为简写,这也是Numpy官方倡导的写法。

当然,你也可以选择其他简写的方式或者直接写numpy,但还是建议用“np”,这样你的程序能和大都数人的程序保持一致。

import numpy as np

创建ndarray数组的方式有很多种,这里介绍我使用的较多的几种:

Method 1: 基于list或tuple

# 一维数组

# 基于list
arr1 = np.array([1,2,3,4])
print(arr1) # 基于tuple
arr_tuple = np.array((1,2,3,4))
print(arr_tuple) # 二维数组 (2*3)
arr2 = np.array([[1,2,4], [3,4,5]])
arr2
[1 2 3 4]
[1 2 3 4]
array([[1, 2, 4],
[3, 4, 5]])

请注意:

  • 一维数组用print输出的时候为 [1 2 3 4],跟python的列表是有些差异的,没有“,
  • 在创建二维数组时,在每个子list外面还有一个”[]”,形式为“[[list1], [list2]]

Method 2: 基于np.arange

# 一维数组
arr1 = np.arange(5)
print(arr1) # 二维数组
arr2 = np.array([np.arange(3), np.arange(3)])
arr2
[0 1 2 3 4]
array([[0, 1, 2],
[0, 1, 2]])

Method 3: 基于arange以及reshape创建多维数组

# 创建三维数组
arr = np.arange(24).reshape(2,3,4)
arr
array([[[ 0,  1,  2,  3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]], [[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
  • 请注意:arange的长度与ndarray的维度的乘积要相等,即 24 = 2X3X4

  • 其他创建ndarray的方法,各位小伙伴们自己可以研究下。

3 Numpy的数值类型

Numpy的数值类型如下:

每一种数据类型都有相应的数据转换函数,参考示例如下:

np.int8(12.334)
12
np.float64(12)
12.0
np.float(True)
1.0
bool(1)
True

在创建ndarray数组时,可以指定数值类型:

a = np.arange(5, dtype=float)
a
array([ 0.,  1.,  2.,  3.,  4.])
  • 请注意,复数不能转换成为整数类型或者浮点数,比如下面的代码会运行出错

# float(42 + 1j)

4 ndarray数组的属性

  • dtype属性,ndarray数组的数据类型,数据类型的种类,前面已描述。
np.arange(4, dtype=float)
array([ 0.,  1.,  2.,  3.])
# 'D'表示复数类型
np.arange(4, dtype='D')
array([ 0.+0.j,  1.+0.j,  2.+0.j,  3.+0.j])
np.array([1.22,3.45,6.779], dtype='int8')
array([1, 3, 6], dtype=int8)
  • ndim属性,数组维度的数量
a = np.array([[1,2,3], [7,8,9]])
a.ndim
2
  • shape属性,数组对象的尺度,对于矩阵,即n行m列,shape是一个元组(tuple)
a.shape
(2, 3)
  • size属性用来保存元素的数量,相当于shape中nXm的值
a.size
6
  • itemsize属性返回数组中各个元素所占用的字节数大小。
a.itemsize
4
  • nbytes属性,如果想知道整个数组所需的字节数量,可以使用nbytes属性。其值等于数组的size属性值乘以itemsize属性值。
a.nbytes
24
a.size*a.itemsize
24
  • T属性,数组转置
b = np.arange(24).reshape(4,6)
b
array([[ 0,  1,  2,  3,  4,  5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
b.T
array([[ 0,  6, 12, 18],
[ 1, 7, 13, 19],
[ 2, 8, 14, 20],
[ 3, 9, 15, 21],
[ 4, 10, 16, 22],
[ 5, 11, 17, 23]])
  • 复数的实部和虚部属性,real和imag属性
d = np.array([1.2+2j, 2+3j])
d
array([ 1.2+2.j,  2.0+3.j])

real属性返回数组的实部

d.real
array([ 1.2,  2. ])

imag属性返回数组的虚部

d.imag
array([ 2.,  3.])
  • flat属性,返回一个numpy.flatiter对象,即可迭代的对象。
e = np.arange(6).reshape(2,3)
e
array([[0, 1, 2],
[3, 4, 5]])
f = e.flat
f
<numpy.flatiter at 0x65eaca0>
for item in f:
print(item)
0
1
2
3
4
5

可通过位置进行索引,如下:

f[2]
2
f[[1,4]]
array([1, 4])

也可以进行赋值

e.flat=7
e
array([[7, 7, 7],
[7, 7, 7]])
e.flat[[1,4]]=1
e
array([[7, 1, 7],
[7, 1, 7]])

下图是对ndarray各种属性的一个小结

5 ndarray数组的切片和索引

  • 一维数组

一维数组的切片和索引与python的list索引类似。

a =  np.arange(7)
a
array([0, 1, 2, 3, 4, 5, 6])
a[1:4]
array([1, 2, 3])
# 每间隔2个取一个数
a[ : 6: 2]
array([0, 2, 4])
  • 二维数组的切片和索引,如下所示:

插播一条硬广:技术文章转发太多。本文涉及的代码量比较多,如需要查看源代码,请在微信公众号“Python数据之道”(ID:PyDataRoad)后台回复关键字“2017026”。

6 处理数组形状

6.1 形状转换

  • reshape()和resize()
b.reshape(4,3)
array([[ 0,  1,  2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
b
array([[ 0,  1,  2,  3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
b.resize(4,3)
b
array([[ 0,  1,  2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])

函数resize()的作用跟reshape()类似,但是会改变所作用的数组,相当于有inplace=True的效果

  • ravel()和flatten(),将多维数组转换成一维数组,如下:
b.ravel()
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
b.flatten()
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
b
array([[ 0,  1,  2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])

两者的区别在于返回拷贝(copy)还是返回视图(view),flatten()返回一份拷贝,需要分配新的内存空间,对拷贝所做的修改不会影响原始矩阵,而ravel()返回的是视图(view),会影响原始矩阵。

参考如下代码:

  • 用tuple指定数组的形状,如下:
b.shape=(2,6)
b
array([[ 0,  1, 20,  3,  4,  5],
[ 6, 7, 8, 9, 10, 11]])
  • 转置

前面描述了数组转置的属性(T),也可以通过transpose()函数来实现

b.transpose()
array([[ 0,  6],
[ 1, 7],
[20, 8],
[ 3, 9],
[ 4, 10],
[ 5, 11]])

6.2 堆叠数组

b
array([[ 0,  1, 20,  3,  4,  5],
[ 6, 7, 8, 9, 10, 11]])
c = b*2
c
array([[ 0,  2, 40,  6,  8, 10],
[12, 14, 16, 18, 20, 22]])
  • 水平叠加

hstack()

np.hstack((b,c))
array([[ 0,  1, 20,  3,  4,  5,  0,  2, 40,  6,  8, 10],
[ 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22]])

column_stack()函数以列方式对数组进行叠加,功能类似hstack()

np.column_stack((b,c))
array([[ 0,  1, 20,  3,  4,  5,  0,  2, 40,  6,  8, 10],
[ 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22]])
  • 垂直叠加

vstack()

np.vstack((b,c))
array([[ 0,  1, 20,  3,  4,  5],
[ 6, 7, 8, 9, 10, 11],
[ 0, 2, 40, 6, 8, 10],
[12, 14, 16, 18, 20, 22]])

row_stack()函数以行方式对数组进行叠加,功能类似vstack()

np.row_stack((b,c))
array([[ 0,  1, 20,  3,  4,  5],
[ 6, 7, 8, 9, 10, 11],
[ 0, 2, 40, 6, 8, 10],
[12, 14, 16, 18, 20, 22]])
  • concatenate()方法,通过设置axis的值来设置叠加方向

axis=1时,沿水平方向叠加

axis=0时,沿垂直方向叠加

np.concatenate((b,c),axis=1)
array([[ 0,  1, 20,  3,  4,  5,  0,  2, 40,  6,  8, 10],
[ 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22]])
np.concatenate((b,c),axis=0)
array([[ 0,  1, 20,  3,  4,  5],
[ 6, 7, 8, 9, 10, 11],
[ 0, 2, 40, 6, 8, 10],
[12, 14, 16, 18, 20, 22]])

由于针对数组的轴为0或1的方向经常会混淆,通过示意图,或许可以更好的理解。

关于数组的轴方向示意图,以及叠加的示意图,如下:

深度叠加

这个有点烧脑,举个例子如下,自己可以体会下:

arr_dstack = np.dstack((b,c))
print(arr_dstack.shape)
arr_dstack
(2, 6, 2)

array([[[ 0,  0],
[ 1, 2],
[20, 40],
[ 3, 6],
[ 4, 8],
[ 5, 10]], [[ 6, 12],
[ 7, 14],
[ 8, 16],
[ 9, 18],
[10, 20],
[11, 22]]])

叠加前,b和c均是shape为(2,6)的二维数组,叠加后,arr_dstack是shape为(2,6,2)的三维数组。

深度叠加的示意图如下:

6.3 数组的拆分

跟数组的叠加类似,数组的拆分可以分为横向拆分、纵向拆分以及深度拆分。

涉及的函数为 hsplit()、vsplit()、dsplit() 以及split()

b
array([[ 0,  1, 20,  3,  4,  5],
[ 6, 7, 8, 9, 10, 11]])
  • 沿横向轴拆分(axis=1)
np.hsplit(b, 2)
[array([[ 0,  1, 20],
[ 6, 7, 8]]), array([[ 3, 4, 5],
[ 9, 10, 11]])]
np.split(b,2, axis=1)
[array([[ 0,  1, 20],
[ 6, 7, 8]]), array([[ 3, 4, 5],
[ 9, 10, 11]])]
  • 沿纵向轴拆分(axis=0)
np.vsplit(b, 2)
[array([[ 0,  1, 20,  3,  4,  5]]), array([[ 6,  7,  8,  9, 10, 11]])]
np.split(b,2,axis=0)
[array([[ 0,  1, 20,  3,  4,  5]]), array([[ 6,  7,  8,  9, 10, 11]])]
  • 深度拆分
arr_dstack
array([[[ 0,  0],
[ 1, 2],
[20, 40],
[ 3, 6],
[ 4, 8],
[ 5, 10]], [[ 6, 12],
[ 7, 14],
[ 8, 16],
[ 9, 18],
[10, 20],
[11, 22]]])
np.dsplit(arr_dstack,2)
[array([[[ 0],
[ 1],
[20],
[ 3],
[ 4],
[ 5]], [[ 6],
[ 7],
[ 8],
[ 9],
[10],
[11]]]), array([[[ 0],
[ 2],
[40],
[ 6],
[ 8],
[10]], [[12],
[14],
[16],
[18],
[20],
[22]]])]

拆分的结果是原来的三维数组拆分成为两个二维数组。

这个烧脑的拆分过程可以自行分析下~~

7 数组的类型转换

  • 数组转换成list,使用tolist()
b
array([[ 0,  1, 20,  3,  4,  5],
[ 6, 7, 8, 9, 10, 11]])
b.tolist()
[[0, 1, 20, 3, 4, 5], [6, 7, 8, 9, 10, 11]]
  • 转换成指定类型,astype()函数
b.astype(float)
array([[  0.,   1.,  20.,   3.,   4.,   5.],
[ 6., 7., 8., 9., 10., 11.]])

8 numpy常用统计函数

常用的函数如下:

请注意函数在使用时需要指定axis轴的方向,若不指定,默认统计整个数组。

  • np.sum(),返回求和
  • np.mean(),返回均值
  • np.max(),返回最大值
  • np.min(),返回最小值
  • np.ptp(),数组沿指定轴返回最大值减去最小值,即(max-min)
  • np.std(),返回标准偏差(standard deviation)
  • np.var(),返回方差(variance)
  • np.cumsum(),返回累加值
  • np.cumprod(),返回累乘积值
b
array([[ 0,  1, 20,  3,  4,  5],
[ 6, 7, 8, 9, 10, 11]])
np.max(b)
20
# 沿axis=1轴方向统计
np.max(b,axis=1)
array([20, 11])
# 沿axis=0轴方向统计
np.max(b,axis=0)
array([ 6,  7, 20,  9, 10, 11])
np.min(b)
0
  • np.ptp(),返回整个数组的最大值减去最小值,如下:
np.ptp(b)
20
# 沿axis=0轴方向
np.ptp(b, axis=0)
array([ 6,  6, 12,  6,  6,  6])
# 沿axis=1轴方向
np.ptp(b, axis=1)
array([20,  5])
  • np.cumsum(),沿指定轴方向进行累加
b.resize(4,3)
b
array([[ 0,  1, 20],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
np.cumsum(b, axis=1)
array([[ 0,  1, 21],
[ 3, 7, 12],
[ 6, 13, 21],
[ 9, 19, 30]], dtype=int32)
np.cumsum(b, axis=0)
array([[ 0,  1, 20],
[ 3, 5, 25],
[ 9, 12, 33],
[18, 22, 44]], dtype=int32)
  • np.cumprod(),沿指定轴方向进行累乘积 (Return the cumulative product of the elements along the given axis)
np.cumprod(b,axis=1)
array([[  0,   0,   0],
[ 3, 12, 60],
[ 6, 42, 336],
[ 9, 90, 990]], dtype=int32)
np.cumprod(b,axis=0)
array([[   0,    1,   20],
[ 0, 4, 100],
[ 0, 28, 800],
[ 0, 280, 8800]], dtype=int32)

9 数组的广播

当数组跟一个标量进行数学运算时,标量需要根据数组的形状进行扩展,然后执行运算。

这个扩展的过程称为“广播(broadcasting)”

b
array([[ 0,  1, 20],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
d = b + 2
d
array([[ 2,  3, 22],
[ 5, 6, 7],
[ 8, 9, 10],
[11, 12, 13]])

写在最后

numpy涵盖的内容其实是非常丰富的,本文仅仅介绍了numpy一些常用的基本功能,算是对numpy的一个入门级的简单的较为全面的描述。

numpy官方的《Numpy Reference》文档,光页面数量就有1500+页,如想要系统的学习numpy,建议仔细阅读官方的参考文档,可在其官方网站进行查阅。当然,资料都是英文版的,可能看起来难度稍微大点,看习惯了就好。

本文涉及的代码量比较多,如需要查看源代码,请在微信公众号“Python数据之道”(ID:PyDataRoad)后台回复关键字“2017026”。

Python:一篇文章掌握Numpy的基本用法的更多相关文章

  1. 一篇文章掌握 Python 内置 zip() 的全部内容

    一篇文章掌握 Python 内置 zip() 的全部内容 zip() 是 Python 中最好用的内置类型之一,它可以接收多个可迭代对象参数,再返回一个迭代器,可以把不同可迭代对象的元素组合起来. 我 ...

  2. 《python for data analysis》第四章,numpy的基本使用

    <利用python进行数据分析>第四章的程序,介绍了numpy的基本使用方法.(第三章为Ipython的基本使用) 科学计算.常用函数.数组处理.线性代数运算.随机模块…… # -*- c ...

  3. Python Numpy shape 基础用法(转自他人的博客,如涉及到侵权,请联系我)

    Python Numpy shape 基础用法 shape函数是numpy.core.fromnumeric中的函数,它的功能是读取矩阵的长度,比如shape[0]就是读取矩阵第一维度的长度.它的输入 ...

  4. 一篇文章教会你利用Python网络爬虫获取电影天堂视频下载链接

    [一.项目背景] 相信大家都有一种头疼的体验,要下载电影特别费劲,对吧?要一部一部的下载,而且不能直观的知道最近电影更新的状态. 今天小编以电影天堂为例,带大家更直观的去看自己喜欢的电影,并且下载下来 ...

  5. (转) TensorFlow深度学习,一篇文章就够了

    TensorFlow深度学习,一篇文章就够了 2016/09/22 · IT技术 · TensorFlow, 深度学习 分享到:6   原文出处: 我爱计算机 (@tobe迪豪 )    作者: 陈迪 ...

  6. TensorFlow深度学习,一篇文章就够了

    http://blog.jobbole.com/105602/ 作者: 陈迪豪,就职小米科技,深度学习工程师,TensorFlow代码提交者. TensorFlow深度学习框架 Google不仅是大数 ...

  7. Python爬虫进阶四之PySpider的用法

    审时度势 PySpider 是一个我个人认为非常方便并且功能强大的爬虫框架,支持多线程爬取.JS动态解析,提供了可操作界面.出错重试.定时爬取等等的功能,使用非常人性化. 本篇内容通过跟我做一个好玩的 ...

  8. Python中生成器和yield语句的用法详解

    Python中生成器和yield语句的用法详解 在开始课程之前,我要求学生们填写一份调查表,这个调查表反映了它们对Python中一些概念的理解情况.一些话题("if/else控制流" ...

  9. 浅谈python的第三方库——numpy(终)

    本文作为numpy系列的总结篇,继续介绍numpy中常见的使用小贴士 1 手动转换矩阵规格 转换矩阵规格,就是在保持原矩阵的元素数量和内容不变的情况下,改变原矩阵的行列数目.比如,在得到一个5x4的矩 ...

随机推荐

  1. bzoj2876 [Noi2012]骑行川藏

    Description 蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨.川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的体力十分有限,因 ...

  2. ie8兼容background-size属性

    满心欢喜地写代码,最后测试兼容性的时候发现Logo图片在IE8下特别大.明显是background-size在ie8一下不兼容. 我懂得,IE8还是个孩子,我就加几句你独有的代码让你兼容吧,司空见惯了 ...

  3. shapeless官方指南翻译总结

    今天抽空把之前翻译的<The Type Astronaut's Guide to Shapeless>一书放到了Gitbook上,将其开源供所有人阅读并希望大家能够提出宝贵意见,地址为sh ...

  4. Java设计模式随笔

    大家都知道Java23种设计模式,大神总结如下: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接 ...

  5. 再议Unity优化

    0x00 前言 在很长一段时间里,Unity项目的开发者的优化指南上基本都会有一条关于使用GetCompnent方法获取组件的条目(例如14年我的这篇博客<深入浅出聊Unity3D项目优化:从D ...

  6. OC—Setter、Getter

    一.本篇以Setter和Getter 来进行成员变量的赋值. 二.Setter 与 Getter 1. 命名规范 为对象中的某个实例变量赋值的方法称为修改方法,用来修改对象的状态这类修改方法称为set ...

  7. FAILED: SemanticException [Error 10096]: Dynamic partition strict mode

    因为动态分区只能在非严格模式进行... 修改为非严格模式后即可! set hive.exec.dynamic.partition.mode

  8. win彩 百款皮肤任选任换.可视化

  9. redis-key相关命令

    本篇主要介绍和redis的key进行操作的相关命令. 命令 描述 复杂度 返回值 DEL key [key ...] 删除给定的一个或多个 key .不存在的 key 会被忽略.删除单个列表.集合.有 ...

  10. SpringData系列二 Repository接口

    本节主要介绍Repository接口规范,及其子接口 Repository是一个空接口,即标准接口 若我们定义的接口继承了Repository,则该接口会被IOC容器识别为一个Repositoty B ...