python numpy基础

实例1

%time 列表推导式 range

In [7]: import numpy as np
In [8]: my_arr = np.arange(1000000)
In [9]: my_list = list(range(1000000))
In [10]: %time for _ in range(10): my_arr2 = my_arr * 2
CPU times: user 20 ms, sys: 50 ms, total: 70 ms
Wall time: 72.4 ms
In [11]: %time for _ in range(10): my_list2 = [x * 2 for x in my_list]
CPU times: user 760 ms, sys: 290 ms, total: 1.05 s
Wall time: 1.05 s
  • CPU times: user 20 ms, sys: 50 ms, total: 70 ms
  • user:CPU 执行 Python 代码(如将 my_arr 乘以 2)所花费的时间。这里是 20 毫秒。
  • sys:CPU 花费在系统级操作(如内存管理、输入输出等)上的时间。这里是 50 毫秒。
  • total:CPU 花费的总时间(用户时间 + 系统时间)。总计 70 毫秒。
  • Wall time: 72.4 ms
  • Wall time 表示实际经过的时间,也就是你用秒表测量到的时间,它包括所有其他开销(如等待资源、CPU 空闲时间等)。这里是 72.4 毫秒,表示整个操作从开始到完成的总时间。

my_arr和内置my_list主要区别:

  1. NumPy 数组 (my_arr) vs Python 列表 (my_list) 的效率
    • NumPy 数组 对于数值计算进行了高度优化,my_arr * 2 操作是 向量化 的,这意味着它通过底层的 C 代码实现操作,因此可以非常快速地完成。
    • Python 列表 在进行类似的元素级操作时效率较低,因为列表操作需要在 Python 中逐个元素地进行循环,这种方式的性能较差。

my_list2 = [x * 2 for x in my_list] 这种写法是 列表推导式(List Comprehension)的一种形式,它是 Python 中用来创建新列表的一种简洁且高效的方法。

列表推导式

my_list2 = [x * 2 for x in my_list]

这段代码的含义是:

  • my_list 中的每个元素 x 执行操作 x * 2,然后将结果放入一个新的列表 my_list2 中。
  • 列表推导式 是一种迭代遍历列表、过滤元素并在一个表达式中生成新列表的方式。其基本结构是:
new_list = [expression for item in iterable]

其中:

    • iterable 是你要遍历的可迭代对象(如列表、元组、字典等)。
    • expression 是你对每个元素执行的操作。

传统for循环

my_list2 = []
for x in my_list:
    my_list2.append(x * 2)

扩展条件过滤

my_list2 = [x * 2 for x in my_list if x > 2]
  • 列表推导式 是 Python 中用于创建新列表的简洁方式,特别适合进行简单的转换和过滤操作。

%time 在正常python代码里面能用吗

%timeIPythonJupyter Notebook 中的魔法命令(magic command),它是专门为这些交互式环境设计的,不能直接在标准的 Python 脚本或命令行中使用。

主要特点:
  • IPython(包括 Jupyter Notebook)提供了许多魔法命令,这些命令通常以 %%% 开头,用来简化或扩展某些功能。例如,%time 用于测量代码的执行时间。
  • 这些命令是在 IPython 环境中有效的,而在常规 Python 脚本中(例如 .py 文件或普通 Python 解释器)无法直接使用。
例子:

Jupyter NotebookIPython 中,你可以直接使用:

%time my_arr2 = my_arr * 2

这会返回代码执行的时间。

但如果你在普通的 Python 脚本或命令行中运行这行代码,Python 会报错:

SyntaxError: invalid syntax
在普通 Python 环境中如何做性能测试:

如果你在标准的 Python 环境中想要测量代码执行时间,可以使用 time 模块或 timeit 模块。

使用 time 模块:
import time

start_time = time.time()  # 记录开始时间
my_arr2 = my_arr * 2
end_time = time.time()  # 记录结束时间

print(f"Execution time: {end_time - start_time} seconds")
使用 timeit 模块:

timeit 是一个专门用于性能测试的模块,它可以帮助你多次运行代码并返回平均时间,这对于精确测试非常有用。

import timeit

# 测试单行代码的执行时间
execution_time = timeit.timeit("my_arr * 2", setup="my_arr = [1, 2, 3, 4]", number=1000)
print(f"Execution time: {execution_time} seconds")
总结:
  • %time 只能在 IPythonJupyter Notebook 中使用。
  • 标准 Python 环境 中,使用 timetimeit 模块来进行性能测试。

实例2 ndarray

ndarray是一个通用的同构数据多维容器,也就是说,其中的所有元素必须是相同类型的。每个数 组都有一个shape(一个表示各维度大小的元组)和一个dtype(一个用于说明数组数据类型的对 象)

In [15]:data = np.random.randn(2, 3)
In [16]:type(data) # 类型是numpy.ndarray
out [16]:numpy.ndarray
In [17]: data.shape
Out[17]: (2, 3)
In [18]: data.dtype
Out[18]: dtype('float64')

上面的例子np.arange(1000000)返回的也是numpy.ndarray

  • numpy.random:这是 NumPy 中用于生成随机数的子模块。它包含了多种生成随机数的函数,比如:
  • rand():生成均匀分布的随机数。
  • randn():生成标准正态分布(均值为 0,标准差为 1)的随机数。
  • randint():生成整数的随机数。
  • choice():生成从给定序列中随机选取的元素。
  • randn:表示 "random normal",即从标准正态分布中生成随机数。n 代表的是 normal distribution(正态分布)。
import numpy as np

# 一维数组
arr1 = np.array([1, 2, 3, 4])
print(arr1.ndim)  # 输出 1,因为是一个一维数组

# 二维数组
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print(arr2.ndim)  # 输出 2,因为是一个二维数组

# 三维数组
arr3 = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print(arr3.ndim)  # 输出 3,因为是一个三维数组

ndim"number of dimensions" 的缩写,表示 维度的数量

多维数组的创建

传入普通数组

zeros,ones,empty方法传入一个表示形状的元组

  • np.array():总是返回一个新的 NumPy 数组,数据会被复制(除非 copy=False)。
  • np.asarray():如果输入已经是 NumPy 数组,则返回原始数组的视图,不进行数据复制;如果输入是其他类型,则像 np.array() 一样创建一个新的数组。
In [31]: np.empty((2, 3, 2))
Out[31]:
array([[[ 0.,  0.],
[ 0., 0.],
        [ 0.,  0.]],
       [[ 0.,  0.],
        [ 0.,  0.],
[ 0., 0.]]])

(2, 3, 2) 这个元组有 3 个数字,它表示数组的 三维形状,具体解释如下

  • 2:数组的 第 1 维(也叫 "轴 0")的大小,即数组有 2 个“层”(2 个二维矩阵)。
  • 3:数组的 第 2 维(也叫 "轴 1")的大小,即每个二维矩阵有 3 行。
  • 2:数组的 第 3 维(也叫 "轴 2")的大小,即每一行有 2 列。

数组类型

# 查看数据类型
arr.dtype
# 转成指定数据类型
arr.astype(np.float64)
# 创建的时候制订数据类型
np.array(['1.25', '-9.6', '42'], dtype=np.string_)
# 用代码表示数据类型
empty_uint32 = np.empty(8, dtype='u4')

数组运算

不用编写循环即可对数据执行批量运算。NumPy用户称其为矢量化(vectorization)

In [51]: arr = np.array([[1., 2., 3.], [4., 5., 6.]])
In [52]: arr
Out[52]:
array([[ 1.,  2.,  3.],
       [ 4.,  5.,  6.]])
In [53]: arr * arr
Out[53]:
array([[  1.,   4.,   9.],
       [ 16.,  25.,  36.]])
In [54]: arr - arr
Out[54]:
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])

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


In [56]: arr ** 0.5 ## ** 0.5 是开平方的意思 2 ** 0.5 ≈ 1.414
Out[56]:
array([[ 1.    ,  1.4142,  1.7321],
       [ 2.    ,  2.2361,  2.4495]])

大小相同的数组之间的比较会生成布尔值数组:

不同大小的数组之间的运算叫做广播(broadcasting)暂不讨论

切片和索引

切片的是视图,而不是复制操作,如果你想要得到的是ndarray切片的一份副本而非视图,就需要明确地进行复制操作, 例如 arr[5:8].copy() 。

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

In [76]: arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
In [77]: arr3d
Out[77]:
array([[[ 1,  2,  3],
        [ 4,  5,  6]],
       [[ 7,  8,  9],
        [10, 11, 12]]])

arr3d[0]是一个2×3数组:

In [78]: arr3d[0]
Out[78]:
array([[1, 2, 3],
[4, 5, 6]])

实例3基本索引和切片

arr3d = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
old_values = arr3d[0].copy
arr3d[0] = 44
arr3d[0] = old_values
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[75], line 1
----> 1 arr3d[0] = old_values

TypeError: int() argument must be a string, a bytes-like object or a real number, not 'builtin_function_or_method'
  • 错误的原因是 arr3d[0].copy 没有加上括号来调用 copy() 方法。
  • 修正代码后,通过 arr3d[0].copy() 来正确获取数组的副本。

实例4切片索引

In [90]: arr2d
Out[90]:
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
In [91]: arr2d[:2]
Out[91]:
array([[1, 2, 3],
[4, 5, 6]])
In [92]: arr2d[:2, 1:]
Out[92]:
array([[2, 3],
[5, 6]])
In [93]: arr2d[1, :2]
Out[93]: array([4, 5])
In [94]: arr2d[:2, 2]
Out[94]: array([3, 6])
In [95]: arr2d[:, :1]
Out[95]:
array([[1],
[4], [7]])
In [96]: arr2d[:2, 1:] = 0
In [97]: arr2d
Out[97]:
array([[1, 0, 0],
       [4, 0, 0],
       [7, 8, 9]])

实例5

import numpy as np

# 创建一个包含字符串的数组,每个字符串最大长度为 4
arr = np.array(['apple', 'banana', 'cherry'], dtype='<U4')

print(arr)
print(arr.dtype)

# 输出
['appl' 'bana' 'cher']
<U4

dtype='<U4' 是 NumPy 数组的 数据类型(dtype),表示该数组的数据类型是 Unicode 字符串,并且每个字符串的最大长度为 4 个字符

解释:

  • <:表示字节顺序(endianess)。< 表示 小端字节顺序(little-endian),即低位字节存储在内存的低地址。对于 Unicode 字符串来说,通常情况下是默认使用小端字节顺序。
  • U:表示该数据类型是 Unicode 字符串U 是 "Unicode" 的缩写)。
  • 4:表示每个字符串的最大长度为 4 个字符,即每个元素可以存储最多 4 个 Unicode 字符。
  • dtype='<U4' 中,< 表示小端字节顺序,U 表示字符串类型,4 表示每个字符串的最大长度为 4 个字符。
  • 所以,即使字符串 'apple' 的实际长度为 5 个字符,NumPy 会将其截断为前 4 个字符 'appl',同理 'banana' 被截断为 'bana''cherry' 被截断为 'cher'

总结:

  • dtype='<U4' 表示一个 Unicode 字符串数组,其中每个字符串的最大长度为 4 个字符。
  • 如果尝试存储一个长度大于 4 的字符串,NumPy 会自动进行截断。

实例6 数组转置和轴对换

T属性

In [126]: arr = np.arange(15).reshape((3, 5))
In [127]: arr
Out[127]:
array([[ 0,  1,  2,  3,  4],
[5, 6, 7, 8, 9], [10, 11, 12, 13, 14]])
In [128]: arr.T
Out[128]:
array([[ 0,  5, 10],
[1, 6,11], [2, 7,12], [3, 8,13], [ 4, 9, 14]])
  • reshape() 方法用于改变数组的形状,不会改变数据的内容。
  • 可以使用 -1 来让 NumPy 自动推导某一维度的大小。
  • reshape() 返回的是一个新数组,原始数组的元素不发生变化。

np.dot计算矩阵内积:

In [129]: arr = np.random.randn(6, 3)
In [130]: arr
Out[130]:
array([[-0.8608,  0.5601, -1.2659],
       [ 0.1198, -1.0635,  0.3329],
       [-2.3594, -0.1995, -1.542 ],
       [-0.9707, -1.307 ,  0.2863],
       [ 0.378 , -0.7539,  0.3313],
       [ 1.3497,  0.0699,  0.2467]])
In [131]: np.dot(arr.T, arr)
Out[131]:
array([[ 9.2291,  0.9394,  4.948 ],
       [ 0.9394,  3.7662, -1.3622],
       [ 4.948 , -1.3622,  4.3437]])

transpose

对于高维数组,transpose需要得到一个由轴编号组成的元组才能对这些轴进行转置(比较费脑 子):

这里,第一个轴被换成了第二个,第二个轴被换成了第一个,最后一个轴不变。

In [132]: arr = np.arange(16).reshape((2, 2, 4))
In [133]: arr
Out[133]:
array([[[ 0,  1,  2,  3],
[4, 5, 6, 7]], [[ 8, 9, 10, 11],
        [12, 13, 14, 15]]])
In [134]: arr.transpose((1, 0, 2))
Out[134]:
array([[[ 0,  1,  2,  3],
[ 8, 9, 10, 11]], [[4, 5, 6, 7],
        [12, 13, 14, 15]]])

swapaxes

需要接 受一对轴编号:

In [135]: arr
Out[135]:
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],
       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]]])
In [136]: arr.swapaxes(1, 2)
Out[136]:
array([[[ 0,  4],
        [ 1,  5],
        [ 2,  6],
        [ 3,  7]],
       [[ 8, 12],
        [ 9, 13],
        [10, 14],
        [11, 15]]])
### Python Numpy 基础教程入门指南 #### 导入Numpy库并验证安装 为了开始使用 NumPy,首先需要将其导入到工作环境中。可以利用如下代码片段完成这一过程: ```python import numpy as np print(np.__version__) ``` 这段代码不仅会加载 NumPy 库以便后续调用其功能函数,还会打印当前使用的 NumPy 版本号[^1]。 #### 创建数组 NumPy 的核心对象是多维数组 `ndarray`。创建一个简单的 NumPy 数组可以通过多种方式实现: ```python # 使用列表创建一维数组 a = np.array([1, 2, 3]) print(a) # 创建二维数组 b = np.array([[1, 2], [3, 4]]) print(b) ``` 这些例子展示了如何基于现有的 Python 列表结构快速构建新的 NumPy 数组实例[^4]。 #### 查看数组属性 一旦有了数组之后,就可以查询有关该数组的一些基本信息,比如形状(shape),维度(dimension)等: ```python c = np.array([[1, 2, 3], [4, 5, 6]]) # 输出数组的形状 (rows, columns) print(c.shape) # 获取数组的数据类型 print(c.dtype.name) # 访问特定位置上的元素 c[row][column] print(c[0, 1]) ``` 上述命令可以帮助理解所创建数组的具体特征及其内部存储模式。 #### 执行基本运算 除了作为静态数据容器外,NumPy 还支持高效的数值计算操作,例如加法、乘法以及其他更复杂的线性代数变换: ```python d = np.arange(6).reshape((2, 3)) e = d * 2 + 1 f = e.sum(axis=0) print(f"d:\n{d}") print(f"e after multiply by 2 and add 1:\n{e}") print(f"f sum along axis 0:\n{f}") ``` 这里展示了一些常见的算术运算符的应用场景以及沿指定轴求和的方法。 #### 随机数生成 随机抽样也是科学研究中不可或缺的一部分,在这方面 NumPy 提供了一系列便捷实用的功能接口: ```python g = np.random.rand(3, 3) # 从均匀分布中抽取样本填充矩阵 h = np.random.randn(3, 3) # 从标准正态分布中抽取样本填充矩阵 i = np.random.randint(0, 10, size=(2, 2)) # 整型随机整数 print(g) print(h) print(i) ``` 以上代码段分别演示了三种不同类型的伪随机数发生器的工作原理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值