Numpy 基础

本文详细介绍了Python数据分析库NumPy的基本概念和核心功能,包括ndarray数据结构、创建数组的方法、数组的索引和切片、数组函数以及矩阵运算。讲解了如何进行数组乘法、创建不同类型的数组、布尔型索引、一元和二元函数的使用,并展示了随机数生成。此外,还涵盖了数组的保存和读取、统计方法以及随机数的生成。
摘要由CSDN通过智能技术生成

一、简介

Numpy,全称Numerical Python,是Python的一个强大的数据分析包。相比于list数据结构,Numpy的ndarray数据结构,支持矢量计算、无需遍历即可完成对整组数据的运算。此外,还提供了诸如转置、点积等线代操作。提供了随机数生成、傅里叶变换等功能。最后,Numpy还可以作为Python和C(C++,Fortran等)进行数据交流的基础。

dt = [[1, 2], [3, 4]]
arr = np.array(dt)
# 数组乘数组——对应位置元素相乘
print(arr*arr)
# 数组乘标量——数组每个元素都乘该标量
print(arr*2)


# 输出:[[ 1  4]
#        [ 9 16]]
#      [[2 4]
#       [6 8]]

二、创建ndarray

创建数组ndarray的常用方法
方法说明
array将序列数据转换为ndarray,指定类型或自动分析类型
asarray同上,区别在于输入为ndarray时,不进行复制
arange使用同range
ones,ones_like生成指定形状值为1的数组
zeros,zeros_like生成指定形状值为0的数组
empty,empty_like生成指定形状值不赋初值的数组
eye,identity根据参数N生成单位矩阵

1.np.array创建数组

import numpy as np
dt = [[2, 1], (1, 2)]
arr = np.array(dt)
print(arr)
# 没有指定类型,自动识别
print(arr.dtype)


# 输出:[[2 1]
#        [1 2]]
#       int32

2.np.array和np.asarray的区别

dt = [[2, 1], (1, 2)]
arr = np.array(dt)
# 不管什么类型序列,都会新建一个数组
arr2 = np.array(arr)
# 传入是数组,则不会再新建
as_arr = np.asarray(arr)
print('原始数组id:{},使用np.array创建数组的id:{},使用np.asarray创建数组的id:{}'.format(id(arr), id(arr2), id(as_arr)))


# 输出:原始数组id:1913281185152,使用np.array创建数组的id:1913281155680,
#       使用np.asarray创建数组的id:1913281185152

3.np.empty创建的并不是空数组

这个方法只是分配了2*3的一个数组空间,未赋值。但并不代表值为空。这些地址空间的值为上一个程序使用之后的结果,存在未知随机风险。

arr = np.empty((2, 3))
print(arr)


# 输出:[[6.23042070e-307 1.89146896e-307 1.42417221e-306]
#        [1.37961641e-306 6.23039354e-307 1.69115935e-306]]

 4.np.ones_like生成一个和指定数组一样形状的数组,可指定类型

print(arr.shape)
arr = np.ones_like(arr, dtype='f4')
print(arr)


# 输出:(2, 2)
#      [[1. 1.]
#       [1. 1.]]
Numpy常用数据类型
类型简写说明
int32,uint32i4,u4有符号和无符号32位整数(4字节)
float64f8或d对应python的float和C的double
complex128c16128位浮点数表示的复数
bool?真假
objectOPython的对象
string_S每个字符占一个字节
unicode_U字节数由平台决定

5.类型转换

注意:无论转换前后,数据类型是否一致,都会创建新的对象。

dt = [[2, 1], (1, 2)]
arr = np.array(dt)
print(arr.dtype)
# 自动对应float64
new_arr = arr.astype(float)
print(new_arr.dtype)


# 输出:int32
#      float64

三、索引和切片

1.基本索引和切片

(1) 两种方式访问某个元素

dt = [[1, 2], [3, 4]]
arr = np.array(dt)
# 这种访问方式和二维列表一样
print('第一个元素是:', arr[0][0])
# 还可以这样访问
print('还可以这样访问第一个元素:', arr[0, 0])

 (2)简单切片

dt = [[1, 2, 3], [4, 5, 6]]
# 列表切片
print(dt[0:1])
arr = np.array(dt)
# 数组切片
print(arr[0:1])


# 输出:[[1, 2, 3]]
#      [[1 2 3]]

 (3)切片赋值

list的切片会拷贝数据,即修改切片不会改变原列表。同时,赋值号前后应是同样结构的数据。数组的切片则不同。

dt = [1, 2, 3, 4, 5, 6]
arr = np.array(dt)
# 切片所得是两个元素,可以通过广播,赋值为同一个值
arr_slice = arr[1:3]
# 修改切片,原数组也会改变
arr_slice[:] = 0
print(arr)


# 数组:[1 0 0 4 5 6]

2.花式索引

(1)混合索引

dt = [[1, 2, 3], [4, 5, 6]]
arr = np.array(dt)
print('取每一行的第一个元素:', arr[:, 0])


# 输出:取每一行的第一列: [1 4]

 (2)布尔型索引

dt = [1, 2, 3, 4, 5, 6]
arr = np.array(dt)
bl = [True, True, False, True, True, True]
print(arr[bl])


# 输出:[1 2 4 5 6]

 实际不会这样手动构造包含布尔值的列表,而是采用条件表达式。

dt = [1, 2, 3, 4, 5, 6]
arr = np.array(dt)
print(arr[arr != 3])

 (3)花式索引

dt = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
arr = np.array(dt)
print('原数组:\n', arr)
# 取第一行和最后一行
print('取第一行和最后一行:\n', arr[[0, -1]])
# 取对角线元素,相当于取(0,0)(1,1)(2,2)
print('取对角线元素:', arr[[0, 1, 2], [0, 1, 2]])


# 输出:原数组:
#       [[1 2 3]
#        [4 5 6]
#        [7 8 9]]
#       取第一行和最后一行:
#       [[1 2 3]
#        [7 8 9]]
#       取对角线元素: [1 5 9]

 如果想取原数组一个矩形区域,可以使用np.ix_

dt = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
arr = np.array(dt)
print('原数组:\n', arr)
print('取中间2*2的数组:\n', arr[np.ix_([1, 2], [1, 2])])


# 输出:原数组:
#      [[ 1  2  3  4]
#       [ 5  6  7  8]
#       [ 9 10 11 12]
#       [13 14 15 16]]
#      取中间2*2的数组:
#      [[ 6  7]
#       [10 11]]

四、数组函数

数组函数和一般的函数没有什么区别,只是它作用在数组上,是简单函数的矢量化包装。

1.一元函数

常用一元函数
函数说明
abs,fabs绝对值,对于非复数,可使用更高效的fabs
square各元素求平方
sigh各元素正负号,1:正数,0:零,-1:负数
ceil,floor向上,向下取整
rint四舍五入到整数,同时保留dtype
modf将整数和小数部分分开返回
isnan数组元素要么是数字要么是np.nan
cos,sin,tan,arcsin三角函数

(1)向上取整

不小于原数的最小整数,输出数据类型为float

dt = [1.4, 2.6, 3.7, 4.8]
arr = np.array(dt)
# 向上取整,并非四舍五入
print(np.ceil(arr))


# 输出:[2. 3. 4. 5.]

(2)分割整数和小数部分 

dt = [1.5, 2.6, 3.7, 4.8]
arr = np.array(dt)
arr_dcm, arr_int = np.modf(arr)
print(arr_dcm, arr_int)


# 输出:[0.5 0.6 0.7 0.8] [1. 2. 3. 4.]

 (3)判断是否是数字

元素只能是数字和np.nan,如传入字符串会报错。

dt = [1.5, 2.6, np.nan, 4.8]
arr = np.array(dt)
print(np.isnan(arr))


# 输出:[False False  True False]

 np.nan并不是“是否为空”的判断,而是一个特殊的float对象。

dt = [1.5, 2.6, None, 4.8]
arr = np.array(dt)
print(np.isnan(arr))


# 输出:TypeError: ufunc 'isnan' not supported for the input types


print(np.nan is None)
print(type(np.nan))


# 输出:False
#      <class 'float'>

2.二元函数

常用二元函数
函数说明
add,subtract,multiply元素间加,减,乘
divide,floor_divide除,向下整除
powera^b
maximum,fmax逐个比较取大值,fmax会忽略nan
mod元素间求模
copysign将第二组元素符号复制给第一组
greater,less_equal>,<=,返回布尔型数组
logical_and,logical_xor逻辑与,逻辑异或

 (1)向下整除

arr = np.array([1, 2, 3, 4])
arr2 = np.array([5, 6, 7, 8])
print(np.floor_divide(arr2, arr))


# 输出:[5 3 2 2]

(2)相同位置元素取大值

arr = np.array([1, 2, 3, np.nan])
arr2 = np.array([5, 6, 7, 8])
print(np.maximum(arr2, arr))


# 输出:[ 5.  6.  7. nan]

 (3)复制正负号

arr = np.array([1, 2, 3, 4])
arr2 = np.array([1, -1, 1, -1])
print(np.copysign(arr, arr2))


# 输出:[ 1. -2.  3. -4.]

五、综合使用

 1.条件表达np.where

arr = np.array([1, -2, 3, -4])
# 根据条件筛选取数
print(np.where(arr < 0))


# 输出:(array([1, 3], dtype=int64),)
arr = np.array([1, -2, 3, -4])
# 数组中小于0的赋值为0,否则赋值为1
print(np.where(arr < 0, 0, 1))


# 输出:[1 0 1 0]
arr = np.array([1, -2, 3, -4])
# 小于0的元素赋值为0,否则保留原数
print(np.where(arr < 0, 0, arr))


# 输出:[1 0 3 0]

2.数组统计方法

数组统计方法
方法说明
sum,mean求和,求均值
std,var标准差,方差
min,max最值
argmin,argmax最值索引
cumsum所有元素累计求和
cumprod所有元素累计求积

(1)求和

arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
print(np.sum(arr, axis=0))
# 不指定轴,则求全部元素和
print(arr.sum())


# 输出:[ 6  8 10 12]
#       36

(2)最值索引

arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
# 注意,即使是多维数组,返回的也是数字,而不是位置元组
print(np.argmax(arr))


# 输出:7

3.用于布尔型数组的方法

arr.any():是否存在真元素,arr.all()是否全部为真。注意,0和False为假,非0数字和True为真。

空字符串、空列表、None等不能判断。

arr = np.array([1, False, 3, 4])
# 是否全为真
print(arr.all())


# 输出:False

4.排序

arr = np.array([[1, 5, 3, 9], [6, 4, 7, 8]])
print(np.sort(arr, axis=0))

# 输出:[[1 4 3 8]
#       [6 5 7 9]]

5.数组的集合操作

数组的集合操作
方法说明
unique(x)返回x中只出现一次的元素数组
intersect1d(x,y)交集
union1d(x,y)并集
in1d(x,y)x的元素是否在y中的布尔数组
setdiff1d(x,y)在x中不在y中的元素
setxor1d(x,y)在x或y中,但不同时存在于两个数组

以上方法的说明已经很明确,就仅以最后一个做示例

arr = np.array([1, 5, 3, 9])
arr2 = np.array([2, 5, 3, 10])
print(np.setxor1d(arr, arr2))

# 输出:[ 1  2  9 10]

6.保存和读取文件

(1)保存文件

arr = np.array([1, 5, 3, 9])
np.save('保存数组.npy', arr)

 记事本打开如下图,数据是以原始二进制格式保存的。

 (2)保存成压缩文件

arr = np.array([1, 2, 3, 4])
arr2 = np.array([5, 6, 7, 8])
# 关键字key1,key2是自定义的,用于读取数据
np.savez('保存数组.npz', key1=arr, key2=arr2)

(3)保存到文本文件

arr = np.array([[1, 2, 3, 4], [1, 2, 3, 4]], dtype=int)
# 参数分别表示保存文件名,数组,十进制数格式,逗号分割
np.savetxt('保存数组.txt', arr, fmt="%d", delimiter=',')

 

(3)读取数据

data = np.load('保存数组.npz')
print('数组一的数据为:', data['key1'])

# 输出:数组一的数据为: [1 2 3 4]

# 打开文本文件就是np.loadtxt
data = np.loadtxt('保存数组.txt', delimiter=',')

7.矩阵运算

矩阵运算方法
方法说明
dot矩阵乘法
diagonal返回方阵对角线或将一维数组转成方阵
trace对角线元素之和
det矩阵行列式
inv方阵的逆
qrQR分解
svd奇异值分解
solve解线性方程组Ax=b,A为方阵

(1)矩阵乘法

arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]], dtype=int)
print('矩阵乘矩阵的转置:\n', arr.dot(arr.T))

# 输出:矩阵乘矩阵的转置:
#      [[ 30  70]
#       [ 70 174]]

(2)矩阵对角线 

arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [1, 2, 3, 4], [5, 6, 7, 8]], dtype=int)
print(arr)
print('矩阵的对角线:\n', arr.diagonal())


# 输出:[[1 2 3 4]
#        [5 6 7 8]
#        [1 2 3 4]
#        [5 6 7 8]]
#      矩阵乘矩阵的转置:
#      [1 6 3 8]

8.产生随机数

np.random的随机函数
方法说明
permutation传入序列则打乱,传入整数则返回打乱的range
shuffle打乱序列
rand[0,1)随机产生一个数,满足均匀分布
randint给定的范围内随机选取整数
randn均值0,方差1的正态分布
binomail二项分布
normal高斯分布
betaBeta分布
chisquare卡方分布
gammaGamma分布
uniform[0, 1)中均匀分布
seed随机种子

(1)打乱序列permutation

data = [1, 2, 3, 4, 5, 6]
arr = np.random.permutation(data)
arr2 = np.random.permutation(6)
print(arr, arr2)

# 输出:[4 3 6 1 2 5] [1 3 2 0 5 4]

(2)给定范围产生一定量随机数

# 1-10之间随机产生2个数
arr = np.random.randint(1, 10, 2)
print(arr)

# 输出:[5 3]

(3)产生一组符合正态分布的数

可以看到,随机产生的这一组数基本满足均值为0,方差为1的正态分布。(数量越大,越接近标准分布)

arr = np.random.randn(1000)
plt.figure(figsize=(10, 8))
plt.hist(arr, bins=20, density=True)
print('均值:{},方差:{}'.format(arr.mean(), arr.std()))
plt.show()


# 输出:均值:-0.0033979715972624175,方差:0.9870680514692056

 (4)关于随机数的一个补充

for i in range(3):
    np.random.seed(666)
    arr = np.random.random()
    print('第{}产生的随机数:{}'.format(i+1, arr))


# 输出:第1产生的随机数:0.7004371218578347
#      第2产生的随机数:0.7004371218578347
#      第3产生的随机数:0.7004371218578347

通过上例可以看出,确定了随机种子,那么每次生成的随机数其实是确定的。也就是说,这里的随机不是真的随机。这个特性在某些过程复现中有用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值