Numpy科学计算

NumPy介绍
 
NumPy(Numerical Python)是一个开源的Python科学计算库,用于快速处理任意维度的数组。
NumPy支持常见的数组和矩阵操作。对于同样的数值计算任务,使用Numpy比直接使用Python要简洁的多。
NumPy使用ndarray对象来处理多维数组,该对象是一个快速而灵活的大数据容器。

为什么要学NumPy

1. 快速
2. 方便
3. 科学计算的基础库

NumPy的优势

对于同样的数值计算任务,使用NumPy要比直接编写Python代码便捷得多;
NumPy中的数组的存储效率和输入输出性能均远远优于Python中等价的基本数据结构,且其能够提升的性能 是与数组中的元素成比例的;
NumPy的大部分代码都是用C语言写的,其底层算法在设计时就有着优异的性能,这使得NumPy比纯Python 代码高效得多。

ndarray与Python原生list运算效率对比

import random
import time
import numpy as np
a = []
for i in range(100000000):
    a.append(random.random())
t1 = time.time()
sum1=sum(a)
t2=time.time()
b=np.array(a)
t4=time.time()
sum3=np.sum(b)
t5=time.time()
print(t2-t1, t5-t4)
输出:
8.297281980514526 1.7647507190704346
t2-t1为使用python自带的求和函数消耗的时间,t5-t4为使用numpy求和消耗的时间,结论为: ndarray的计算速度要快很多,更高效。

 创建一维数组

import numpy as np
list1 = [1,2,3,4]
oneArray = np.array(list1)
print(type(oneArray))
print(oneArray)
输出:
<class 'numpy.ndarray'>
[1 2 3 4]
import numpy as np
# 创建数组的多种形式
# 1. 直接传入列表的方式
t1 = np.array([1,2,3])
print(t1)
print(type(t1))

# 2. 传入range生成序列
t2 = np.array(range(10))
print(t2)
print(type(t2))

# 3. 使用numpy自带的np.arange()生成数组
t3 = np.arange(0,10,2)
print(t3)
print(type(t3))
输出:
[1 2 3]
<class 'numpy.ndarray'>
[0 1 2 3 4 5 6 7 8 9]
<class 'numpy.ndarray'>
[0 2 4 6 8]
<class 'numpy.ndarray'>

 创建二位数组

import numpy as np
list2 = [[1,2],[3,4],[5,6]]
twoArray = np.array(list2)
print(twoArray)
#返回数组类型
print(twoArray.ndim)
#返回数组形状
print(twoArray.shape)
#返回数组的元素个数
print(twoArray.size)
输出:
[[1 2]
 [3 4]
 [5 6]]
2
(3, 2)
6

 调整数组形状

#二维变三维
import numpy as np four = np.array([[1,2,3],[4,5,6]]) # 修改的是原有的 four.shape = (3,2) print(four) print("-"*20) # 返回一个新的数组 five = four.reshape(3,2) print(five) 输出: [[1 2] [3 4] [5 6]] -------------------- [[1 2] [3 4] [5 6]]

#多维变一维
import numpy as np
four = np.array([[1,2,3],[4,5,6]])
# 将多维变成一维数组
five = four.reshape((6,),order='F')
# 默认情况下‘C’以行为主的顺序展开,‘F’(Fortran风格)意味着以列的顺序展开
six = four.flatten(order='F')
print(five)
print(six)
输出:
[1 4 2 5 3 6]
[1 4 2 5 3 6]

 数组转换为list

import numpy as np
a= np.array([9, 12, 88, 14, 25])
list_a = a.tolist()
print(list_a)
print(type(list_a))
输出:
[9, 12, 88, 14, 25]
<class 'list'>

NumPy的数据类型

import numpy as np
import random
f = np.array([1,2,3,4,5], dtype = np.int16)
# 返回数组中每个元素的字节单位长度
print(f.itemsize)
# 获取数据类型
print(f.dtype)
# 调整数据类型
f1 = f.astype(np.int64)
print(f1.dtype)
# 拓展随机生成小数
# 使用python语法,保留两位
print(round(random.random(),2))
arr = np.array([random.random() for i in range(10)]) # 取小数点后两位
print(np.round(arr,2))
输出:
2
int16
int64
0.02
[0.72 0.02 0.93 0.99 0.12 0.16 0.19 0.25 0.89 0. ]

数组的计算

import numpy as np
import random
t1 = np.arange(24).reshape((6,4))
print(t1)
print("-"*20)
print(t1+2)
print("-"*20)
print(t1*2)
print("-"*20)
print(t1/2)
输出:
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]
 [16 17 18 19]
 [20 21 22 23]]
--------------------
[[ 2  3  4  5]
 [ 6  7  8  9]
 [10 11 12 13]
 [14 15 16 17]
 [18 19 20 21]
 [22 23 24 25]]
--------------------
[[ 0  2  4  6]
 [ 8 10 12 14]
 [16 18 20 22]
 [24 26 28 30]
 [32 34 36 38]
 [40 42 44 46]]
--------------------
[[ 0.   0.5  1.   1.5]
 [ 2.   2.5  3.   3.5]
 [ 4.   4.5  5.   5.5]
 [ 6.   6.5  7.   7.5]
 [ 8.   8.5  9.   9.5]
 [10.  10.5 11.  11.5]]
#同种形状的数组(对应位置进行计算操作)
import numpy as np
import random
t1 = np.arange(24).reshape((6,4))
t2 = np.arange(100,124).reshape((6,4))
print(t1+t2)
print("-"*20)
print(t1*t2)
输出:
[[100 102 104 106]
[108 110 112 114]
[116 118 120 122]
[124 126 128 130]
[132 134 136 138]
[140 142 144 146]]
--------------------
[[ 0 101 204 309]
[ 416 525 636 749]
[ 864 981 1100 1221]
[1344 1469 1596 1725]
[1856 1989 2124 2261]
[2400 2541 2684 2829]]
import numpy as np
import random
t1 = np.arange(24).reshape((4,6))
t2 = np.arange(0,6)
print(t1)
print("-"*20)
print(t2)
print("-"*20)
print(t1-t2)
输出:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
--------------------
[0 1 2 3 4 5]
--------------------
[[ 0 0 0 0 0 0]
[ 6 6 6 6 6 6]
[12 12 12 12 12 12]
[18 18 18 18 18 18]]
#列形状相同(会与每一个相同维度的数组的对应位相操作)
import numpy as np
import random
t1 = np.arange(24).reshape((4, 6))
t2 = np.arange(4).reshape((4, 1))
print(t1)
print("-"*20)
print(t2)
print("-"*20)
print(t1-t2)
输出:
[[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]
 [12 13 14 15 16 17]
 [18 19 20 21 22 23]]
--------------------
[[0]
 [1]
 [2]
 [3]]
--------------------
[[ 0  1  2  3  4  5]
 [ 5  6  7  8  9 10]
 [10 11 12 13 14 15]
 [15 16 17 18 19 20]]

 数组中轴的计算

import numpy as np
a = np.array([[1,2,3],[4,5,6]])
print(np.sum(a,axis=0)) #0轴
print(np.sum(a,axis = 1)) #1轴
输出:
[5 7 9]
[ 6 15]

import numpy as np
a = np.arange(27).reshape((3,3,3))
b = np.sum(a, axis=0)
print(a)
print("-"*20)
print(b)
输出:
[[[ 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 25 26]]]
--------------------
[[27 30 33]
[36 39 42]
[45 48 51]]

数组的索引和切片

#一维数组的操作方法
import numpy as np
a = np.arange(10)
# 冒号分隔切片参数 start:stop:step 来进行切片操作
print(a[2:7:2])# 从索引 2 开始到索引 7 停止,间隔为 2
# 如果只放置一个参数,如 [2],将返回与该索引相对应的单个元素
print(a[2],a)
# 如果为 [2:],表示从该索引开始以后的所有项都将被提取
print(a[2:])
输出:
[2 4 6]
2 [0 1 2 3 4 5 6 7 8 9]
[2 3 4 5 6 7 8 9]
#多维数组的操作方法
import numpy as np
t1 = np.arange(24).reshape(4,6)
print(t1)
print('-'*20)
print(t1[1]) # 取一行(一行代表是一条数据,索引也是从0开始的)
print(t1[1,:]) # 取一行
输出:
[[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]
 [12 13 14 15 16 17]
 [18 19 20 21 22 23]]
--------------------
[ 6  7  8  9 10 11]
[ 6  7  8  9 10 11]
print(t1[1:])# 取连续的多行 print(t1[1:3,:])# 取连续的多行
输出:
[[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
print(t1[[0,2,3]])# 取不连续的多行 print(t1[[0,2,3],:])# 取不连续的多行
输出:
[[ 0 1 2 3 4 5]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
print(t1[:,1])# 取一列
输出:
[ 1 7 13 19]
print(t1[:,1:])# 连续的多列
输出:
[[ 1 2 3 4 5]
[ 7 8 9 10 11]
[13 14 15 16 17]
[19 20 21 22 23]]
print(t1[:,[0,2,3]])# 取不连续的多列
输出:
[[ 0 2 3]
[ 6 8 9]
[12 14 15]
[18 20 21]]
print(t1[2,3])# # 取某一个值,三行四列
输出:
15
print(t1[[0,1,1]])
print('-'*20)
print(t1[[0,1,1],[0,1,3]])# 取多个不连续的值,[[行,行。。。],[列,列。。。]]
输出:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[ 6 7 8 9 10 11]]
--------------------
[0 7 9]

 数组中数值修改

import numpy as np
t = np.arange(24).reshape(4,6)
# 修改某一行的值
t[1,:]=0
(t)
# 修改某一列的值
t[:,1]=0
# 修改连续多行
t[1:3,:]=0
# 修改多行多列,取第二行到第四行,第三列到第五列
t[1:4,2:5]=0
# 修改多个不相邻的点
t[[0,1],[0,3]]=0
# 可以根据条件修改,比如讲小于10的值改掉
t[t<10]=0
# 使用逻辑判断
# np.logical_and  &
# np.logical_or   |
# np.logical_not  ~
t[(t>2)&(t<6)]=0
t[(t<2)|(t>6)]=0
t[~(t>6)]=0
# 拓展
# 三目运算( np.where(condition, x, y)满足条件(condition),输出x,不满足输出y。)) 
score = np.array([[80,88],[82,81],[75,81]])
result = np.where(score>80,True,False)
print(result)

数组的添加、删除和去重

添加

#append方法
  '''
  参数说明:

  arr:输入数组
  values:要向arr添加的值,需要和arr形状相同(除了要添加的轴)
  axis:默认为 None。当axis无定义时,是横向加成,返回总是为一维数组!当axis有定义的时候,分别为0和1的时候。当 axis有定义的时候,分别为0和1的时候(列数要相同)。当axis为1时,数组是加在右边(行数要相同)。
  '''

import numpy as np
a = np.array([[1,2,3],[4,5,6]])
print ('第一个数组:')
print (a)
print ('\n')
print ('向数组添加元素:')
print (np.append(a, [7,8,9]))
print ('\n')
print ('沿轴 0 添加元素:')
print (np.append(a, [[7,8,9]],axis = 0))
print ('\n')
print ('沿轴 1 添加元素:')
print (np.append(a, [[5,5,5],[7,8,9]],axis = 1))
输出:
第一个数组:
[[1 2 3]
[4 5 6]]

向数组添加元素:
[1 2 3 4 5 6 7 8 9]

沿轴 0 添加元素:
[[1 2 3]
[4 5 6]
[7 8 9]]

沿轴 1 添加元素:
[[1 2 3 5 5 5]
[4 5 6 7 8 9]]

 

#insert方法
import numpy as np
a = np.array([[1,2],[3,4],[5,6]])
print ('第一个数组:')
print (a)
print ('\n')
print ('未传递 Axis 参数。 在插入之前输入数组会被展开。')
print (np.insert(a,3,[11,12]))
print ('\n')
print ('传递了 Axis 参数。 会广播值数组来配输入数组。')
print ('沿轴 0 广播:')
print (np.insert(a,1,[11],axis = 0))
print ('\n')
print ('沿轴 1 广播:')
print (np.insert(a,1,11,axis = 1))
输出:
第一个数组:
[[1 2]
 [3 4]
 [5 6]]

未传递 Axis 参数。 在插入之前输入数组会被展开。
[ 1  2  3 11 12  4  5  6]

传递了 Axis 参数。 会广播值数组来配输入数组。
沿轴 0 广播:
[[ 1  2]
 [11 11]
 [ 3  4]
 [ 5  6]]

沿轴 1 广播:
[[ 1 11  2]
 [ 3 11  4]
 [ 5 11  6]]

删除

import numpy as np
a = np.arange(12).reshape(3,4)
print ('第一个数组:')
print (a)
print ('\n')
print ('未传递 Axis 参数。 在删除之前输入数组会被展开。')
print (np.delete(a,5))
print ('\n')
print ('删除每一行中的第二列:')
print (np.delete(a,1,axis = 1))
print ('\n')
输出:
第一个数组:
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]

未传递 Axis 参数。 在删除之前输入数组会被展开。
[ 0  1  2  3  4  6  7  8  9 10 11]

删除每一行中的第二列:
[[ 0  2  3]
 [ 4  6  7]
 [ 8 10 11]]

去重 

# numpy.unique 函数用于去除数组中的重复元素。
'''
arr:输入数组,如果不是一维数组则会展开 return_index:如果为true,返回新列表元素在旧列表中的位置(下标),并以列表形式储 return_inverse:如果为true,返回旧列表元素在新列表中的位置(下标),并以列表形式储 return_counts:如果为true,返回去重数组中的元素在原数组中的出现次数
'''
import numpy as np
a = np.array([5,2,6,2,7,5,6,8,2,9])
print ('第一个数组:')
print (a)
print ('\n')
print ('第一个数组的去重值:')
u = np.unique(a)
print (u)
print ('\n')
print ('去重数组的索引数组:')
u,indices = np.unique(a, return_index = True)
print (indices)
print ('\n')
print ('我们可以看到每个和原数组下标对应的数值:')
print (a)
print ('\n')
print ('去重数组的下标:')
u,indices = np.unique(a,return_inverse = True)
print (u)
print (indices)
print ('\n')
print ('返回去重元素的重复数量:')
u,indices = np.unique(a,return_counts = True)
print (u)
print (indices)
输出:
第一个数组:
[5 2 6 2 7 5 6 8 2 9]

第一个数组的去重值:
[2 5 6 7 8 9]

去重数组的索引数组:
[1 0 2 4 7 9]

我们可以看到每个和原数组下标对应的数值:
[5 2 6 2 7 5 6 8 2 9]

去重数组的下标:
[2 5 6 7 8 9]
[1 0 2 0 3 1 2 4 0 5]

返回去重元素的重复数量:
[2 5 6 7 8 9]
[3 2 2 1 1 1]

 numpy的计算

import numpy as np
score = np.array([[80,88],[82,81],[75,81]])
# 1. 获取所有数据最大值
result = np.max(score)

# 2. 获取某一个轴上的数据最大值
result = np.max(score,axis=0)
# 3. 获取最小值
result = np.min(score)
# 4. 获取某一个轴上的数据最小值
result = np.min(score,axis=0)
# 5. 数据的比较
result = np.maximum([-2, -1, 0, 1, 2], 0) # 第一个参数中的每一个数与第二个参数比较返回大的
result = np.minimum([-2, -1, 0, 1, 2], 0) # 第一个参数中的每一个数与第二个参数比较返回小的
result = np.maximum([-2, -1, 0, 1, 2], [1,2,3,4,5]) # 接受的两个参数,也可以大小一致;第二个参数只是一个单独的值时,其实是用到了维度的广播机制;
# 6. 求平均值
result = np.mean(score) # 获取所有数据的平均值
result = np.mean(score,axis=0) # 获取某一行或者某一列的平均值
# 7. 返回给定axis上的累计和
arr = np.array([[1,2,3], [4,5,6]])
print(arr)
print(arr.cumsum(0))
# 8. argmin求最小值索引
result = np.argmin(score,axis=0)
# 9. 求每一列的标准差
# 标准差是一组数据平均值分散程度的一种度量。一个较大的标准差,代表大部分数值和其平均值之间差异较大; # 一个较小的标准差,代表这些数据较接近平均值反应出数据的波动稳定情况,越大表示波动越大,越不稳定。
result = np.std(score,axis=0)
#10. 极值
result=np.ptp(score,axis=None)#就是最大值和最小值的差

通用函数

数组的拼接

import numpy as np
# 1. 根据轴连接的数组序列
a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])
# 要求a,b两个数组的维度相同
print ('沿轴 0 连接两个数组:')
print (np.concatenate((a,b),axis= 0))
print ('\n')
print ('沿轴 1 连接两个数组:')
print (np.concatenate((a,b),axis = 1))
# 2. 根据轴进行堆叠
print ('沿轴 0 连接两个数组:')
print (np.stack((a,b),axis= 0))
print ('\n')
print ('沿轴 1 连接两个数组:')
print (np.stack((a,b),axis = 1))
# 3. 矩阵垂直拼接
v1 = [[0,1,2,3,4,5],
      [6,7,8,9,10,11]]
v2 = [[12,13,14,15,16,17],
      [18,19,20,21,22,23]]
result = np.vstack((v1,v2))
print(result)
# 4. 矩阵水平拼接
v1 = [[0,1,2,3,4,5],
      [6,7,8,9,10,11]]
v2 = [[12,13,14,15,16,17],
      [18,19,20,21,22,23]]
result = np.hstack((v1,v2))
print(result)
输出:
沿轴 0 连接两个数组:
[[1 2]
 [3 4]
 [5 6]
 [7 8]]

沿轴 1 连接两个数组:
[[1 2 5 6]
 [3 4 7 8]]
沿轴 0 连接两个数组:
[[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]]

沿轴 1 连接两个数组:
[[[1 2]
  [5 6]]

 [[3 4]
  [7 8]]]
[[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]
 [12 13 14 15 16 17]
 [18 19 20 21 22 23]]
[[ 0  1  2  3  4  5 12 13 14 15 16 17]
 [ 6  7  8  9 10 11 18 19 20 21 22 23]]

数组的分割

import numpy as np
# 1. 将一个数组分割为多个子数组
'''
参数说明:
ary:被分割的数组 indices_or_sections:果是一个整数,就用该数平均切分,如果是一个数组,为沿轴切分的位置(左开右闭) axis:沿着哪个维度进行切向,默认为0,横向切分。为1时,纵向切分
'''
arr = np.arange(9).reshape(3,3)
print ('将数组分为三个大小相等的子数组:')
b = np.split(arr,3)
print (b)
#2.numpy.hsplit 函数用于水平分割数组,通过指定要返回的相同形状的数组数量来拆分原数组。 # floor() 返回数字的下舍整数。 col方向
harr = np.floor(10 * np.random.random((2, 6)))
print ('原array:')
print(harr)
print ('拆分后:')
print(np.hsplit(harr, 3))
# 3.numpy.vsplit 沿着垂直轴分割 row方向
a = np.arange(16).reshape(4,4)
print ('第一个数组:')
print (a)
print ('\n')
print ('竖直分割:')
b = np.vsplit(a,2)
print (b)
输出:
将数组分为三个大小相等的子数组:
[array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]
原array:
[[1. 4. 9. 3. 7. 2.]
 [3. 4. 3. 1. 6. 3.]]
拆分后:
[array([[1., 4.],
       [3., 4.]]), array([[9., 3.],
       [3., 1.]]), array([[7., 2.],
       [6., 3.]])]
第一个数组:
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]

竖直分割:
[array([[0, 1, 2, 3],
       [4, 5, 6, 7]]), array([[ 8,  9, 10, 11],
       [12, 13, 14, 15]])] 

 数组中的nan和inf

import numpy as np
# 创建一个nan和inf
a = np.nan
b = np.inf
print(a,type(a))
print(b,type(b))
# --判断数组中为nan的个数(注意:float类型的数据才能赋值nan)
t = np.arange(24,dtype=float).reshape(4,6)
# 可以使用np.count_nonzero() 来判断非零的个数
print(np.count_nonzero(t))
# 将三行四列的数改成nan
t[3,4] = np.nan
# 并且 np.nan != np.nan 结果 是TRUE
# 所以我们可以使用这两个结合使用判断nan的个数
print(np.count_nonzero(t != t))
# 注意: nan和任何数计算都为nan
print(np.sum(t,axis=0))
# 将nan替换为0
t[np.isnan(t)] = 0
print(t)
#----------练习: 处理数组中nan
t = np.arange(24).reshape(4,6).astype('float')
# 将数组中的一部分替换nan
t[1,3:] = np.nan
print(t)
输出:
nan <class 'float'>
inf <class 'float'>
23
1
[36. 40. 44. 48. nan 56.]
[[ 0.  1.  2.  3.  4.  5.]
 [ 6.  7.  8.  9. 10. 11.]
 [12. 13. 14. 15. 16. 17.]
 [18. 19. 20. 21.  0. 23.]]
[[ 0.  1.  2.  3.  4.  5.]
 [ 6.  7.  8. nan nan nan]
 [12. 13. 14. 15. 16. 17.]
 [18. 19. 20. 21. 22. 23.]]

 二维数组的转换

import numpy as np
#对换数组的维度
a = np.arange(12).reshape(3,4)
print ('原数组:')
print (a )
print ('\n')
print ('对换数组:')
print (np.transpose(a))
# 与transpose一致
a = np.arange(12).reshape(3,4)
print ('原数组:')
print (a)
print ('\n')
print ('转置数组:')
print (a.T)
# 函数用于交换数组的两个轴
t1 = np.arange(24).reshape(4,6)
re = t1.swapaxes(1,0)
print ('原数组:')
print (t1)
print ('\n')
print ('调用 swapaxes 函数后的数组:')
print (re)
输出:
原数组:
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]

对换数组:
[[ 0  4  8]
 [ 1  5  9]
 [ 2  6 10]
 [ 3  7 11]]
原数组:
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]

转置数组:
[[ 0  4  8]
 [ 1  5  9]
 [ 2  6 10]
 [ 3  7 11]]
原数组:
[[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]
 [12 13 14 15 16 17]
 [18 19 20 21 22 23]]

调用 swapaxes 函数后的数组:
[[ 0  6 12 18]
 [ 1  7 13 19]
 [ 2  8 14 20]
 [ 3  9 15 21]
 [ 4 10 16 22]
 [ 5 11 17 23]]

 

posted @ 2019-07-28 14:48  imcati  阅读(400)  评论(0编辑  收藏  举报