【Python 零基础入门】第六课 Numpy
-
概述+ 什么是 Numpy?+
-
常用函数+
-
参考答案+
概述
在众多 Python 的数据处理库中, Numpy 是一个非常强大的存在. Numpy 为我们提供了高性能的多维数组, 以及这些数组对象上的各种操作. 但是, 作为一个刚入门 Python 的新手, 你可能会问: "为什么我需要 Numpy, 而不是直接使用Python 的内置列表?"在这篇文章的开篇, 我们就来探讨这个问题.
什么是 Numpy?
Numpy (Numerical Python) 是 Python 非常重要的一个库, 用于处理数值数组. Numpy 为我们提供了大量数据处理的函数以及数学函数. 与 Python 的内列表相比, Numpy 数组在数据分析, 科学计算, 线性代数, 机器学习等方面都表现出了卓越的性能和效率.
Numpy 与 Python 数组的区别
虽然 Python 的内置列表很灵活, 能存储任意类型的数据. 但当我们需要进行大量的数值运算时 (线性代数, 统计), Python 的内置列表效率并不高. Numpy 数组相比之下, 是在连续的内存块上存储的, 这使得访问速度更快, 效率更高. 而且 Numpy 是用 C 语言编写的, 其内部迭代计算比 Python 的内置循环要快很多.
例子:
Numpy 在数据科学中的重要性
在现代数据科学领域, 数据处理, 清晰, 统计分析, 特征工厂, 机器学习等各个领域都离不开数值计算. Numpy 为我们提供了一套完整, 高效的工具, 使得我们的任务变得简单. 几乎所有的 Python 数据处理库, 如 Pandas, Scipy 等, 都是基于 Numpy 构建的. 所以我们非常有必要要熟悉掌握 Numpy 库.
Numpy 底层区别
并发 vs 并行
并发 vs 并行
- 并发 (Concurrency): 是指系统能够处理多个任务在同一时间段内交替执行, 但不一定同时+ 并行 (Parallelism): 并行是指多个任务或多个数据在同一时刻被执行
举个例子:
- 并发: 类似一个单线程的服务器, 可以在短时间内处理多个请求, 但是一次只能处理一个请求. 当等待一个请求数据时, 可以切换到另一个请求+ 并行: 想象成一个多线程的计算任务, 每个线程在多核 CPU 不同核心上同时执行
举个生活中的例子:
小白吃饭吃到一半, 电话来了, 我一直到吃完了以后才去接, 这就说明你不支持并发也不支持并行.
小白吃饭吃到一半, 电话来了, 你停了下来接了电话, 接完后继续吃饭, 这说明你支持并发.
小白吃饭吃到一半, 电话来了, 你一边听电话一边吃饭, 这说明你支持并行.
应用:
- 并发: 进行任务之间的协调 & 同步, 难点在有效地处理资源争用 & 死锁+ 并行: 同时进行多个任务, 难点在于负载均衡和通信开销
单线程 vs 多线程
单线程 vs 多线程:
- 单线程: 在同一时间处理一个任务+ 多线程: 在同一时间处理多个任务
GIL
GIL (Global Interpreter Lock) 全局解释器, 来源是 Python设计之初的考虑, 为了数据安全所做的决定.
每个 CPU 在同一时间只能执行一个线程 (在单核 CPU 下的多线程其实都只是并发, 不是并行, 并发和并行从宏观上来讲都是同时处理多路请求的概念. 但并发和并行又有区别, 并行是指两个或者多个事件在同一时刻发生, 而并发是指两个或多个事件在同一时间间隔内发生.
内存存储
Python 内置列表:
- Python 内置列表是一个东岱数组, 容纳不同类型的元素. 每个远古三都是一个 Python 对象, 包括指针, 类型, 信息, 引用计数等等. 所以 Python 内置的列表内存开销较大, 而且元素在内存中可能是分散的
Numpy ndarray:
- ndarray 是一个多维数组, 通常包含同类型的元素. ndarray 在内存中是连续的, 所以可以被 CPU 更高效的访问. 而且, 由于蒜素都是相同的数据类型, 所以 ndarray 不需要为每个元素存储额外的类型信息
例子:
我们可以看到存储相同数据的情况下, python 内置列表使用了超过 ndarray 2 倍的内存.
ndarray 如何存储数据
进一步说明, 我们来看一下 ndarray 源代码:
/*
* The main array object structure.
*/
/* This struct will be moved to a private header in a future release */
typedef struct tagPyArrayObject_fields {
PyObject_HEAD
/* Pointer to the raw data buffer */
char *data;
/* The number of dimensions, also called 'ndim' */
int nd;
/* The size in each dimension, also called 'shape' */
npy_intp *dimensions;
/*
* Number of bytes to jump to get to the
* next element in each dimension
*/
npy_intp *strides;
PyObject *base;
/* Pointer to type structure */
PyArray_Descr *descr;
/* Flags describing array -- see below */
int flags;
/* For weak references */
PyObject *weakreflist;
} PyArrayObject_fields;
在上述实验中, 我们发现 10,000,000 个元素的列表 Numpy 占用的内存是 40,000,096 字节, 这是因为我们存储的元素为 int32 类型, 也就是 4 个字节, 加上Numpy 数组存储的一些指针, 维度, PyObject_HEAD, 为 96 字节.
对比 int32 数组和 int64 数组:
- int32 占用 32 bit (4 byte) 4 字节, 4100 + 96 = 496+ int64 占用 64 bit (8 byte) 8 字节, 8100 + 96 = 896
图解区别
Numpy 安装
安装命令:
pip install numpy
pip3 install numpy
Anaconda
Anaconda 是一个计算科学库, 可以为我们提供便利的 Python 环境.
安装: Anaconda 官网
导包
导入 Numpy 包:
# 导包
import numpy as np
print(np.__version__)
ndarray
ndarray 是 Numpy 最重要的一个特点. ndarray 是一个 N 维数组对象.
np.array 创建
np.array
可以帮助我们创建一 ndarray.
格式:
numpy.array(object, dtype=None, *, copy=True, order='K', subok=False, ndmin=0, like=None)
参数:
- object: 类数组+ dtype: 数据类型, 可选
例子:
# 导包
import numpy as np
# 创建ndarray
array1 = np.array([1, 2, 3]) # 通过lsit创建
array2 = np.array(<