Numpy基础

本文内容源自《利用Python进行数据分析》一书,更多内容见:
Numpy可视化博客
https://jalammar.github.io/visual-numpy

一、NumPy的ndarray

NumPy最重要的一个特点就是其N维数组对象(即ndarray) ,它是一个通用的同构数据多维容器,也就是说,其中的所有元素必须是相同类型的.每个数组都有一个shape(一个表示各维度大小的元组)和一个dtype(一个用于说明数组数据类型的对象)
首先用np.array()创建ndarray

>>> import numpy as np
>>> data = [[1,2,3,4],[5,6,7,8]];
>>> arr = np.array(data);
>>> arr
array([[1, 2, 3, 4],
       [5, 6, 7, 8]])

然后输出shapedtype ,注意arr.shape()是错误的.

>>> arr.shape
(2, 4)
>>> arr.dtype
dtype('int32')

二、创建ndarray

创建数组最简单的办法就是使用np.array()函数,它接收一切序列型的对象(创建其它数组),然后产生一个新的含有传入数据的NumPy数组.
示例1

>>> data = [1,2,3,4]
>>> arr = np.array(data)
>>> arr
array([1, 2, 3, 4])

示例2
如上面展示的嵌套序列(由一组等长列表组成的列表)

>>> data = [[1,2,3,4],[5,6,7,8]];
>>> arr = np.array(data);
>>> arr
array([[1, 2, 3, 4],
       [5, 6, 7, 8]])

示例3
zeros创建指定长度或形状全为0数组
ones创建指定长度或形状全为1的数组

>>> np.zeros(10)
array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.])

>>> np.zeros((3,6))
array([[ 0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.]])
       
>>> np.ones((2,3,2))
array([[[ 1.,  1.],
        [ 1.,  1.],
        [ 1.,  1.]],

       [[ 1.,  1.],
        [ 1.,  1.],
        [ 1.,  1.]]])

示例4
arange创建等差数组,是Python内置函数range的数组版:

>>> np.arange(10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

reshape 可以重新定义其形状

>>> mat = np.arange(12).reshape((3,4))
>>> mat
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

示例5
数组排序 np.sort(arr,axis=0)或者arr.sort(axis=0)(后者测试有问题) : 逐行由大到小排序,np.argsort(arr,axis)返回排序的索引.

>>> arr
array([[14, 13, 12, 11],
       [10,  9,  8,  7],
       [ 6,  5,  4,  3]])
       
>>> np.sort(c,axis=0)
array([[ 6,  5,  4,  3],
       [10,  9,  8,  7],
       [14, 13, 12, 11]])
>>> np.sort(c,axis=1)
array([[11, 12, 13, 14],
       [ 7,  8,  9, 10],
       [ 3,  4,  5,  6]])

>>> np.argsort(a)
array([[3, 2, 1, 0],
       [3, 2, 1, 0],
       [3, 2, 1, 0]], dtype=int64)

三、ndarray的数据类型

3.1 数据类型查看 dtype

dtype是一个特殊的对象,它含有ndarray将一块内存解释为特定数据类型所需信息,创建ndarray时可以指定数据类型

>>> arr = np.array([1,2,4],dtype=np.int32)
>>> arr.dtype
dtype('int32')
>>> arr
array([1, 2, 4])

3.2 数据类型转换 astype()

1.可以通过ndarray的 astype() 方法显式地转换为其dtype

>>> arr = np.array([1,2,3,4,5])
>>> arr.dtype
dtype('int32')
>>> float_arr = arr.astype(np.float64)
>>> float_arr
array([ 1.,  2.,  3.,  4.,  5.])
>>> float_arr.dtype
dtype('float64')

2.如果将浮点数转换成整数,则小数部分将会被截断

>>> arr = np.array([3.7,2.5,2.6])
>>> arr
array([ 3.7,  2.5,  2.6])

>>> arr.astype(np.int32)
array([3, 2, 2])

四、Numpy随机数

Python 生成单个随机数

随机整数:

import random

#生成0-20之间随机整数
>>> import random
>>> random.randint(0,20)
9
>>> random.randint(0,20)
1

随机浮点数:

>>> import random

>>> random.random()
0.5750683162290557

>>> random.uniform(1,10)
1.537218811475957

随机字符:

>>> random.choice('abcdefg$%^&*')
'$'
>>> random.choice('abcdefg$%^&*')
'c'

随机字符串:

>>> random.choice(['apple','peach','banana'])
'banana'

Numpy生成随机数组

1.rand(d0,d1…dn) 根据d0-dn创建随机数数组,浮点数,[0,1),均匀分布

>>> import numpy as np 
>>> a = np.random.rand(3,4,5) # 3个4行5列的矩阵
>>> a
array([[[ 0.82052522,  0.39772757,  0.10702767,  0.8500243 ,  0.0990338 ],
        [ 0.41688268,  0.81852505,  0.37949649,  0.30477787,  0.89358199],
        [ 0.29684884,  0.34452373,  0.80421074,  0.40758698,  0.33536057],
        [ 0.73658926,  0.97701813,  0.57473218,  0.32008441,  0.3855367 ]],

       [[ 0.94558899,  0.38385689,  0.86562463,  0.88437479,  0.65539631],
        [ 0.33358347,  0.75279117,  0.20435261,  0.47775278,  0.26806775],
        [ 0.76751492,  0.39889982,  0.55444728,  0.1457183 ,  0.16721214],
        [ 0.96924537,  0.96858455,  0.38874238,  0.68661647,  0.42201225]],

       [[ 0.14854302,  0.9057184 ,  0.32156218,  0.42248953,  0.51643453],
        [ 0.67239167,  0.70776545,  0.13228446,  0.48603424,  0.57457654],
        [ 0.92464257,  0.89040427,  0.54697102,  0.91909625,  0.64871797],
        [ 0.05623798,  0.90024524,  0.2178354 ,  0.02516971,  0.08885865]]])

2.randn(d0,d1…dn) 根据d0-dn创建随机数数组,标准正态分布

>>> sn = np.random.randn(3,4,5) # 3个4行5列的
>>> sn
array([[[ 0.86337373, -1.28532967,  2.22071546,  0.57320661,  0.20942383],
        [-0.45122977,  1.41654004,  0.40633233, -1.03517127, -1.00214081],
        [-1.33099737, -0.10849854, -0.10623566, -1.40064714,  0.56515491],
        [-1.95891391,  1.26105515,  1.84718306, -0.59877648,  0.14339642]],

       [[-1.6822221 , -0.73728456, -0.61499899, -0.62996666,  0.07878297],
        [-0.01023083, -1.13038369, -1.39895922, -0.53454577,  1.54093765],
        [-0.57146229, -0.42142275, -1.10270702, -0.7692162 , -1.17711295],
        [-0.19241645, -1.29446225,  0.9771069 , -2.82338869, -0.26035278]],

       [[-0.25134972,  1.82536516, -0.28314402, -0.74347928, -0.05876521],
        [-0.16721582,  0.93229841, -0.30961706,  0.50778018, -0.54840238],
        [-0.72032043,  0.1800224 ,  1.18602988, -1.42246267, -0.30880924],
        [ 0.33634607,  1.7428904 ,  0.15975399,  0.04358346,  0.74270667]]])
>>> 

3.randint(low,high,size=(3,4)) 根据shape创建随机整数或整数数组,范围是 [low,high)

>>> b =  np.random.randint(100,200,(3,4))
>>> b
array([[162, 101, 114, 108],
       [133, 191, 150, 102],
       [153, 150, 163, 176]])

五、Numpy乘法

数组与标量的算术运算也会将那个标量值传播到各个元素
数乘

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

相减

>>> arr1 - arr 
array([[12, 12, 12, 12],
       [12, 12, 12, 12],
       [12, 12, 12, 12]])

相乘

>>> arr
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> arr1
array([[12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23]])
>>> arr * arr1
array([[  0,  13,  28,  45],
       [ 64,  85, 108, 133],
       [160, 189, 220, 253]])

元素乘法:np.multiply(a,b)
矩阵乘法:np.dot(a,b) 或 np.matmul(a,b) 或 a.dot(b)

(元素乘法(哈达玛(Hadamard)) 就是对应位置元素相乘,不是线性代数中常用的加和那种!)
唯独注意:*在 np.array 中重载为元素乘法(即对应元素相乘不加和),在 np.matrix 中重载为矩阵乘法!

>>> aa
array([[1],
       [2]])
>>> a
array([1, 2])
>>> aa * a
array([[1, 2],
       [2, 4]])
A = np.array([[1, 2],
              [3, 4]])
B = np.array([[5, 6],
              [7, 8]])
>>> A * B
array([[ 5, 12],
       [21, 32]])
       
>>> np.dot(A, B) # 和下面结果相等
array([[19, 22],
       [43, 50]])
       
>>> np.mat(A) * np.mat(B)     
matrix([[19, 22],
        [43, 50]])         

计算矩阵n次幂

def func(num):
    a = np.array([[1,0,2],[0,-1,1],[0,1,0]])
    I = np.eye(3)
    n = 1
    for n in range(int(num)):
        I = np.dot(I,a)
        n = n+1
    return I

例题 最小多项式
在这里插入图片描述

import numpy as np

a = np.array([[1,0,2],[0,-1,1],[0,1,0]])
I = np.eye(3)

print(np.dot(np.dot(a,a),a))

test_a = a-I
test_b = np.dot(a,a)+a-I

def func(num):
    a = np.array([[1,0,2],[0,-1,1],[0,1,0]])
    I = np.eye(3)
    n = 1
    for n in range(int(num)):
        I = np.dot(I,a)
        n = n + 1
    return I

# 计算结果
print(2*func(8)-3*func(5)+func(4)+func(2)-4*I)
# 验证
print(24*func(2) -37*a +10*I)

五、数学计算 Math

矩阵求逆

>> np.linalg.inv(A)
array([[-2. ,  1. ],
       [ 1.5, -0.5]])

数学函数

>>> a = np.array([10,20,30,40,50])
>>> a
array([10, 20, 30, 40, 50])

三角函数

>>> a = np.array([10,20,30,40,50])
>>> a
array([10, 20, 30, 40, 50])

>>> np.sin(a)
array([-0.54402111,  0.91294525, -0.98803162,  0.74511316, -0.26237485])

以自然对数函数为底数的指数函数

>>> a = np.array([10,20,30,40,50])
>>> a
array([10, 20, 30, 40, 50])

>>> np.exp(a)
array([  2.20264658e+04,   4.85165195e+08,   1.06864746e+13,
         2.35385267e+17,   5.18470553e+21])

数组的方根的运算(开平方)

>>> b = np.array([4,9])
>>> np.sqrt(b)
array([ 2.,  3.])

数组的方根的运算(立方): 注意是对每个元素进行计算

>>> a = np.array([[1,2],[3,4]])
>>> a
array([[1, 2],
       [3, 4]])
>>> np.power(a,2)
array([[ 1,  4],
       [ 9, 16]], dtype=int32)
>>> np.power(a,3)
array([[ 1,  8],
       [27, 64]], dtype=int32)

统计数组各列的中位数 (以下均用a这个数组)

>>> a = np.array(([1, 4, 3], [6, 2, 9], [4, 7, 2]))
>>> a
array([[1, 4, 3],
       [6, 2, 9],
       [4, 7, 2]])
       
>>> np.median(a,axis=0)
array([ 4.,  4.,  3.])

统计数组各行的算术平均值

>>> np.mean(a,axis=1)
array([ 2.66666667,  5.66666667,  4.33333333])

统计数组各列的加权平均值

>>> np.average(a,axis=0)
array([ 3.66666667,  4.33333333,  4.66666667])

统计数组各行的方差

>>> np.var(a,axis=1)
array([ 1.55555556,  8.22222222,  4.22222222])

统计数组各列的标准偏差

>>> np.std(a,axis=0)
array([ 2.05480467,  2.05480467,  3.09120617])



六、进阶练习题

使用数字 0 将一个全为 1 的 5x5 二维数组包围

>>> Z = np.ones((5,5))
>>> np.pad(Z, pad_width=1, mode='constant', constant_values=0)
array([[ 0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  1.,  1.,  1.,  1.,  1.,  0.],
       [ 0.,  1.,  1.,  1.,  1.,  1.,  0.],
       [ 0.,  1.,  1.,  1.,  1.,  1.,  0.],
       [ 0.,  1.,  1.,  1.,  1.,  1.,  0.],
       [ 0.,  1.,  1.,  1.,  1.,  1.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.]])

创建一个 5x5 的二维数组,并设置值 1, 2, 3, 4 落在其对角线下方

>>> np.diag(1+np.arange(4),k=-1)
array([[0, 0, 0, 0, 0],
       [1, 0, 0, 0, 0],
       [0, 2, 0, 0, 0],
       [0, 0, 3, 0, 0],
       [0, 0, 0, 4, 0]])

Python中双冒号的作用[::]
Python序列切片地址可以写为==[开始:结束:步长]==,其中的开始和结束可以省略.(可以用上面的的对角矩阵测试)

找出两个数组中相同的元素np.intersect1d(a,b)

>>> a = np.array(([1, 4, 3], [6, 2, 9], [4, 7, 2]))
>>> a
array([[1, 4, 3],
       [6, 2, 9],
       [4, 7, 2]])
>>> b= np.array([[12,3,4],[45,32,65],[48,8,34]])
>>> b
array([[12,  3,  4],
       [45, 32, 65],
       [48,  8, 34]])
       
>>> np.intersect1d(a,b)
array([3, 4])

将二维数组的前两行进行顺序交换
(注意A[[0,1]], A[[1,0]] 这种索引方法)

>>> A = np.arange(25).reshape(5,5)
>>> A
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, 24]])
       
>>> A[[0,1]]
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])

>>> A[[1,0]]
array([[5, 6, 7, 8, 9],
       [0, 1, 2, 3, 4]])
       
>>> A[[0,1]] = A[[1,0]]  # 完成交换
>>> A
array([[ 5,  6,  7,  8,  9],
       [ 0,  1,  2,  3,  4],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24]])

找出随机一维数组中出现频率最高的值(只能是一维数组)

Z = np.random.randint(0,10,50)
print("随机一维数组:", Z)
np.bincount(Z).argmax()

获得二维数组点积结果的对角线数组

>>> B = np.random.randint(0,6,(2,2))
>>> A = np.random.randint(0,6,(2,2))

>>> np.diag(np.dot(A,B)) # 方式一
array([8, 3])

>>> np.sum(A*B.T,axis=1) # 方式二:快
array([8, 3])

切片

一维数组

一维数组跟Python列表的功能差不多:

>>> arr = np.arange(10)
>>> arr
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> arr[5]
5
>>> arr[5:8]
array([5, 6, 7])
>>> arr[5:8] = 12
>>> arr
array([ 0,  1,  2,  3,  4, 12, 12, 12,  8,  9])

跟列表最重要的区别在于,数组切片是原始数组的视图,这意味着数组不会被复制,视图上的任何修改都会直接反映到源数组上:

>>> arr_slice = arr[5:8]
>>> arr_slice[1] = 12345
>>> arr
array([0,1,2,3,4,12,12345,12,8,9])
>>> arr_slice[:] = 64 
>>> arr_slice
array([64, 64, 64])
>>> arr
array([ 0,  1,  2,  3,  4, 64, 64, 64,  8,  9])

因为NumPy设计的目的是处理大数据,所以如果要不断复制数据的话会带来巨大的性能和内存问题。因此,NumPy选择所有切片都使用初始视图来提高效率。

二维数组

在一个二维数组中,各索引位置上的元素不再是标量而是一维数组:

>>> arr2d = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> arr2d[2]
array([7, 8, 9])

因此,可以对各个元素进行递归访问,但这样需要做的事情有点多,你可以传入一个逗号隔开的索引列表来选取单个元素.也就是说哦,下面两种方式是等价的:

>>> arr2d[0][2]
3 
>>> arr2d[0,2]
3

下图说明了二维数组的索引方式,其中0为横向,1为纵向
NumPy数组中的元素索引

多维数组

在多维数组中,如果省略了后面的索引,则返回对象会是一个维度低一点的ndarray(它含有高一级维度上的所有数据).因此,在223数组arr3d中:
arr3d[0]是一个2*3数组

>>> arr3d = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
>>> arr3d
array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[ 7,  8,  9],
        [10, 11, 12]]])
>>> arr3d[0]
array([[1, 2, 3],
       [4, 5, 6]])

在这里插入图片描述

常用操作

关闭科学计数法 & 完整输出结果

import numpy as np
np.set_printoptions(suppress=True,precision=4) # 默认是8, threshold=np.inf 完整输出(没有省略号)

提取数组的整数部分

# 使用五种不同的方法去提取一个随机数组的整数部分
Z = np.random.uniform(0,10,10)
print ("方法 1: ", Z - Z%1)
print ("方法 2: ", np.floor(Z))
print ("方法 3: ", np.ceil(Z)-1)
print ("方法 4: ", Z.astype(int))
print ("方法 5: ", np.trunc(Z))

ravel()、flatten()、squeeze()

numpy中的ravel()、flatten()、squeeze()的用法与区别
https://blog.csdn.net/weixin_38632246/article/details/99121202

数组形状操作

为了测试,首先创建一个2*3的数组

>>> a = np.array([[1,2,3],[4,5,6]])
>>> a
array([[1, 2, 3],
       [4, 5, 6]])

查看数组形状

>>> a.shape
(2, 3)

>>> a.size
6

更改数组形状(不改变原始数组)

>>> a.reshape(3,2)
array([[1, 2],
       [3, 4],
       [5, 6]])

更改数组形状(改变原始数组) 没看明白

>>> a = np.array([[1,2,3],[4,5,6]])
>>> a
array([[1, 2, 3],
       [4, 5, 6]])
>>> a.resize(3,2)
>>> a
array([[1, 2],
       [3, 4],
       [5, 6]])

展平数组

>>> a.ravel()
array([1, 2, 3, 4, 5, 6])

沿横轴分割数组

>>> a = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> a
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

>>> np.hsplit(a,3)
[array([[1],
       [4],
       [7]]), 
 array([[2],
       [5],
       [8]]), 
array([[3],
       [6],
       [9]])]

沿纵轴分割数组

>>> np.vsplit(a, 3)
[array([[1, 2, 3]]), array([[4, 5, 6]]), array([[7, 8, 9]])]

数组排序

>>> a = np.array(([1, 4, 3], [6, 2, 9], [4, 7, 2]))
>>> np.sort(a)
array([[1, 3, 4],
       [2, 6, 9],
       [2, 4, 7]])

每列的最大值,每行的最小值

>>> a
array([[1, 4, 3],
       [6, 2, 9],
       [4, 7, 2]])
       
>>> np.max(a,axis=0)
array([6, 7, 9])

>>> np.min(a,axis=1)
array([1, 2, 2])

返回每列最大值索引, 返回每行最小值索引

>>> np.argmax(a,axis=0)
array([1, 2, 1], dtype=int64)

>>> np.argmin(a, axis=1)
array([0, 1, 2], dtype=int64)
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值