numpy快速入门
安装
pip3 install numpy
numpy快速入门
数组是 NumPy 库的核心数据结构。创建数组的最简单方法之一是使用array
函数。
1 创建数组
import numpy as np
x = np.array([[1,2,3],[2,3,4]])
print(x)
"""
输出:
[[1 2 3]
[2 3 4]]
"""
array
函数可以在列表甚至嵌套列表上调用。 由于此处输入的嵌套级别是2,因此生成的数组是二维的。 这意味着可以使用两个整数集对数组进行索引。 计算数组维数的最简单方法是检查数组的ndim
属性,也可以通过检查数组的shape
属性,数组中的元素总数使用size
查看:
print(array.ndim)
print(array.shape)
print(array.size)
"""
输出:
2
(2, 3)
6
"""
创建初始值为0、为1、空值(随机值)的数组:
array=np.zeros(2)
print(array)
array=np.ones(2)
print(array)
array=np.empty(2)
print(array)
"""
输出:
[0. 0.]
[1. 1.]
[1. 1.]
"""
使用arange创建数组,它类似于内置range函数:
array=np.arange(4) # 同range,默认步长为1,区间左闭右开[0,3)
print(array)
array=np.arange(2, 9, 2) # 区间[2,9),步长为2
print(array)
"""
输出:
[0 1 2 3]
[2 4 6 8]
"""
创建等间距的数组:
array=np.linspace(0, 10, num=5)
print(array)
"""
输出:
[ 0. 2.5 5. 7.5 10. ]
"""
以上方法创建的数组默认数据类型为np.float64
,可以在创建时显式地制定它的类型:
array=np.ones(2, dtype=np.int64)
print(array)
"""
输出:
[1 1]
"""
2 添加、删除和排序元素
初始数组如下:
arr = np.array([2, 1, 5, 3, 7, 4, 6, 8])
使用sort
对其进行排序:
arr = np.array([2, 1, 5, 3, 7, 4, 6, 8])
print(arr)
arr=np.sort(arr)
print(arr)
"""
输出:
[2 1 5 3 7 4 6 8]
[1 2 3 4 5 6 7 8]
"""
对数组进行拼接,使用concatenate
:
a = np.array([1, 2, 3, 4])
b = np.array([5, 6, 7, 8])
c=np.concatenate((a,b))
print(c)
"""
输出:
[1 2 3 4 5 6 7 8]
"""
拼接两个二维数组:
x = np.array([[1, 2], [3, 4]])
y = np.array([[5, 6]])
c=np.concatenate((x, y), axis=0)
print(c)
"""
输出:
[[1 2]
[3 4]
[5 6]]
"""
对于删除元素,使用索引切片来选择需要保留的元素更加简单。
3 重塑数组
reshape
可以在不更改数据的情况下为数组提供新形状,但是时要注意生成的数组必须和原始数组具有相同数量的元素,如果你从一个有 12 个元素的数组reshape
,你需要确保你的新数组也有总共 12 个元素:
arr=np.arange(6)
print(arr)
arr=arr.reshape(3,2)
print(arr)
"""
输出:
[0 1 2 3 4 5]
[[0 1]
[2 3]
[4 5]]
"""
在这里补充一下numpy以及pandas中axis(轴)的概念,对于二维数组:
arr=np.array([[0, 4, 2], [-2, 5, 3]])
"""
[[ 0 4 2]
[-2 5 3]]
"""
横向(axis=0)对应行,纵向(axis=1)对应列。
在进行操作时,比如前面提到的拼接两个二维数组:
x = np.array([[1, 2], [3, 4]])
y = np.array([[5, 6], [7, 8]])
c=np.concatenate((x, y), axis=0)
print(c)
axis=0表示顺着axis=0(顺着每一行)操作,结果如下:
[[1 2]
[3 4]
[5 6]
[7 8]]
axis=1表示顺着axis=1(顺着每一列)操作,结果如下:
[[1 2 5 6]
[3 4 7 8]]
有点古怪对吧,也可以尝试这样理解:axis=0表示竖向操作,横向不变;axis=1表示横向操作,竖向不变。
4 索引和切片
numpy为数组提供了强大的索引功能。你可以像切片python列表一样索引和切片numpy数组。
data = np.array([1, 2, 3])
# 语法和python原生索引切片类似 [起始索引:结束索引:步长]
# 区间前闭后开 [start,end)
print(data[1])
print(data[0:2])
print(data[0::2])
"""
输出:
2
[1 2]
[1 3]
"""
对于多维数组,不需要用多个中括号[]
,只需使用逗号,
分隔:
data=np.array([[1,2],[3,4],[5,6]])
# print(data[0][1]) python方式
print(data[0,1]) # numpy只需要用`,`分隔每一维度
一些操作示例:
data=np.array([[1,2],[3,4],[5,6]])
print(data[1,:]) # 访问第2行
print(data[:,1]) # 访问第2列
print(data[::-1,1]) # 反转第2列
# 传入两个维度的元组,分别代表行索引和列索引
print(data[(0,1,2),(0,0,1)])
"""
输出:
[3 4]
[2 4 6]
[6 4 2]
[1 3 6]
"""
如果想从数组中选择满足特定条件的值,使用numpy很简单:
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
# 小于5的所有值
print(a[a < 5])
"""
输出:
[1 2 3 4]
"""
# 大于等于5的所有值
print(a[a>=5])
"""
输出:
[ 5 6 7 8 9 10 11 12]
"""
# 能被 2 整除的元素
print(a[a%2==0])
"""
输出:
[ 2 4 6 8 10 12]
"""
# 还可以使用逻辑运算符&以及|
print(a[(a > 4) & (a % 2 == 0)]) # 大于4且能被2整除的元素
print(a[(a < 4) | (a % 2 == 0)]) # 小于4或能被2整除的元素
"""
输出:
[ 6 8 10 12]
[ 1 2 3 4 6 8 10 12]
"""
# 可以直接打印对应的布尔值
print((a > 4) & (a % 2 == 0))
"""
输出:
[[False False False False]
[False True False True]
[False True False True]]
"""
使用nonzero
可以返回非零元素的索引:
x = np.array([[3, 0, 0], [0, 4, 0], [5, 6, 0]])
print(np.nonzero(x))
print(x[np.nonzero(x)])
"""
输出:
(array([0, 1, 2, 2]), array([0, 1, 0, 1]))
[3 4 5 6]
"""
在此示例中,返回了一个数组元组:每个维度一个。第一个数组表示找到这些值的行索引,第二个数组表示找到这些值的列索引。
除了切片,还可以使用vstack
垂直堆叠、hstack
水平堆叠数组:
a1 = np.array([[1, 1],
[2, 2]])
a2 = np.array([[3, 3],
[4, 4]])
print(np.vstack((a1,a2)))
print(np.hstack((a1,a2)))
"""
输出:
[[1 1]
[2 2]
[3 3]
[4 4]]
[[1 1 3 3]
[2 2 4 4]]
"""
使用hsplit
或vsplit
,可以将数组水平或垂直拆分为几个形状相同的数组:
x = np.arange(1, 25).reshape(2, 12)
print(x)
print(np.hsplit(x,3))
print(np.vsplit(x,2))
"""
输出:
[[ 1 2 3 4 5 6 7 8 9 10 11 12]
[13 14 15 16 17 18 19 20 21 22 23 24]]
[array([[ 1, 2, 3, 4],
[13, 14, 15, 16]]),
array([[ 5, 6, 7, 8],
[17, 18, 19, 20]]),
array([[ 9, 10, 11, 12],
[21, 22, 23, 24]])]
[array([[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]]),
array([[13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]])]
"""
4 视图和副本
视图是一个重要的numpy概念,它是对原始数组的引用,而副本则不是。numpy函数以及索引和切片等操作会尽可能返回视图。这可以节省内存并且速度更快(无需复制数据)。然而,重要的是要意识到:修改视图中的数据也会修改原始数组。
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(a)
# 切片获取a数组的第一行
b1 = a[0, :]
# 判断b1是否是a的视图
print(np.may_share_memory(a,b1))
print(b1)
# 修改b1
b1[0]=99
# 查看原始数组
print(a)
"""
输出:
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
True
[1 2 3 4]
[[99 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
"""
使用may_share_memory
可用于确定两个数组是彼此的副本还是彼此的视图,这里返回True
,因此修改数组b1会影响原数组a。
使用copy
可以创建副本:
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(a)
# 切片获取a数组的第一行
b1 = a[0:1, :].copy()
# 判断b1是否是a的视图
print(np.may_share_memory(a,b1))
"""
输出:
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
False
"""
5 基本数组操作
基本操作包括加减乘除:
# 直接用运算符号将两个数组进行运算
data = np.array([1, 2])
ones = np.ones(2, dtype=int)
print(data+ones)
print(data-ones)
print(data*data)
print(data/data)
"""
输出:
[2 3]
[0 1]
[1 4]
[1. 1.]
"""
这里要注意的重要一点是,两个numpy多维数组之间的算术运算不是矩阵乘法。结果仍然返回相同形状的numpy 数组。矩阵乘法需要使用dot
:
data = np.array([1, 2])
ones = np.ones(2, dtype=int)
print(np.dot(data,data))
"""
输出:
5
"""
如果要查找数组中元素的总和,可以使用sum
. 这适用于一维数组、二维数组和更高维度的数组:
a = np.array([[1, 2, 3, 4],[1, 2, 3, 4]])
print(np.sum(a))
"""
输出:
20
"""
对于二维和更高维数组,可以指定轴axis进行求和:
a = np.array([[1, 2, 3, 4],[1, 2, 3, 4]])
print(np.sum(a,axis=0))
print(np.sum(a,axis=1))
"""
输出:
[2 4 6 8]
[10 10]
"""
6 广播
numpy操作大部分是按元素进行的,这需要一个操作中的两个数组具有相同的形状。但是,这并不意味着numpy不能操作两个形状不同的数组。numpy提供了在较大的数组上广播较小尺寸的数组的灵活性。比如:
data = np.array([1.0, 2.0])
data *= 1.6
print(data)
"""
输出:
[1.6 3.2]
"""
numpy理解乘法应该发生在每个单元格上。这个概念叫做广播。广播是一种允许numpy对不同形状的数组执行操作的机制。您的数组的维度必须兼容,例如,当两个数组的维度相等或其中一个为 1 时。如果维度不兼容,将得到一个ValueError
。
具体的规则如下:
- 两个数组的大小应相等
- 其中之一是 1
如果不满足上述条件,将引发ValueError
异常,以指示数组具有不兼容的形状。举例:
x = np.array([[ 0, 0, 0],
[10,10,10],
[20,20,20]])
y = np.array([1, 2, 3])
print(x+y)
"""
输出:
[[ 1 2 3]
[11 12 13]
[21 22 23]]
"""
让我们将前面的代码制作成图表,以帮助我们理解广播。x变量的形状为(3, 3),而y的形状仅为3。但是在 numpy广播中,y的形状转换为1x3;因此,该规则的第二个条件已得到满足。 通过重复将y广播到x的相同形状。+
操作可以按元素应用。
再来看一个广播两个数组的结果:
x = np.array([[0], [10], [20]])
y = np.array([1,2,3])
print(x+y)
"""
输出:
[[ 1 2 3]
[11 12 13]
[21 22 23]]
"""
7 更多有用的数组操作
numpy还有聚合功能。除了min
、max
和sum
之外,还可以用mean
以获得平均值、prod
将元素相乘的结果、std
获得标准偏差、unique
获取唯一元素、.T
转置矩阵等。
arr = np.array([[1, 2, 3],
[1, 2, 3],
[1, 2, 3]])
print(np.min(arr))
print(np.max(arr))
print(np.sum(arr))
print(np.mean(arr))
print(np.unique(arr))
print(arr.T)
"""
输出:
1
3
18
2.0
[1 2 3]
[[1 1 1]
[2 2 2]
[3 3 3]]
"""
8 反转数组
对数组的反转,除了使用-1
步长完成,也可以用flip
:
# 一维数组的反转
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
print(np.flip(arr))
# 二维数组的反转
arr = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
print(np.flip(arr,axis=0)) # 反转行
print(np.flip(arr,axis=1)) # 反转列
print(np.flip(arr)) # 全反转
"""
输出:
[8 7 6 5 4 3 2 1]
[[7 8 9]
[4 5 6]
[1 2 3]]
[[3 2 1]
[6 5 4]
[9 8 7]]
[[9 8 7]
[6 5 4]
[3 2 1]]
"""
9 重塑和展平多维数组
flatten
和ravel
可以展平多维数组,后者不创建副本,效率更快。
x = np.array([[1 , 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(x.flatten())
print(x.ravel())
"""
输出:
[ 1 2 3 4 5 6 7 8 9 10 11 12]
[ 1 2 3 4 5 6 7 8 9 10 11 12]
"""
10 保存和加载numpy对象
有几种方法可以使用numpy保存和加载对象。.npy
和.npz
后缀的文件以允许正确检索数组的方式存储重建ndarray所需的数据、形状、dtype和其他信息,即使文件位于具有不同架构的另一台机器上也是如此。
如果要存储单个ndarray对象,使用np.save
将其存储为.npy
文件,如果要在单个文件中存储多个ndarray对象,使用np.savez
将其保存为.npz
文件。
a = np.array([1, 2, 3, 4, 5, 6])
np.save('filename', a) # 保存为.npy文件
# 使用np.load()来从文件加载numpy对象
b = np.load('filename.npy')
print(b)
"""
输出:
[1 2 3 4 5 6]
"""
也可以将numpy数组保存为纯文本文件,例如.csv
或.txt
文件:
csv_arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
np.savetxt("myfile.csv",csv_arr) # 将其保存为名为`new_file.csv`的`.csv`文件
# 可以使用loadtxt方法轻松地加载保存的文本文件:
b=np.loadtxt("myfile.csv")
print(b)
"""
输出:
[1. 2. 3. 4. 5. 6. 7. 8.]
"""
本文来自博客园,作者:yyyz,转载请注明原文链接:https://www.cnblogs.com/yyyzyyyz/p/16515207.html