IPython 超越Python
IPython: interactive Python ,交互式Python编程
Jupyter Notebook 是 IPython shell 基于浏览器的图形界面,虽然其是在网页上进行代码的查看和编辑,但还是要和一个正在运行的Python进程进行连接,这个进程被称为核(kernel)
IPython的一些使用技巧:
1、使用符号?获取文档
In [1]: len?
Signature: len(obj, /)
Docstring: Return the number of items in a container.
Type: builtin_function_or_method
# 2、使用符号??获取源代码
In [2]: def add_two_num(a,b):
...: '''计算两个数的和 '''
...: return a+b
In [3]: add_two_num??
Signature: add_two_num(a, b)
Source:
def add_two_num(a,b):
'''计算两个数的和 '''
return a+b
File: ~/<ipython-input-7-250102af8d49>
Type: function
#??有时不能显示源代码,这是因为查询的对象并不是用Python实现的,而是C语言或其他编译扩展语言实现的。
3、使用Tab补全代码
4、'*'通配符的补全
魔法方法
5、%paste:粘贴代码 %paste 命令同时输入并执行复制的代码 (%cpaste 可持续粘贴 )
6、%run 执行外部代码 %run py路径
7、%timeit 计算单行代码执行的精确时间
%time 对单个语句的执行时间进行计时
In [4]: %timeit a = 1
16.1 ns ± 0.289 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
# 若是计算代码块的时间 使用 %%timeit
8、IPython 中创建了叫作 In 和 Out 的 Python 变量,这些变量自动更新以反映命令历史
print(In) # 打印列表,按照顺序记录所有的命令
#(列表中的第一项是一个占位符,以便 In[1] 可以表示第一条命令
Print(Out) #打印字典,它将输入数字映射到相应的输出(如果有的话)
9、在句子的结尾输入 ; 可以禁止在Out中输出
10、使用%prun分析函数的执行时间 ,
%lprun逐行分析函数的执行时间(需要先pip install line_profiler)
NumPy入门
有效地存储和操作数值数组是数据科学中绝对的基础过程,Numpy包就是处理这些数值数据的工具之一。
Numpy(Numerical Python):提供了高效存储和操作密集数据缓存的接口
Python的数据类型
Python是一门动态类型的语言
标准的Python实现是用C语言编写的,这意味着每一个Python对象都是一个聪明的伪C语言结构体,该结构体不仅包含其值,还有其他信息,这也就意味着Python的int不是真正的int 🧐
注意:和Python 列表不同,NumPy数组是固定类型的。
这意味着当你试图将一个浮点值插入一个整型数组时,浮点值会被截短成整型。
举个例子:
a = np.array([3, 4]) ; a[1] = 1213.321312321 ; 输出a array([ 3, 1213])
Numpy的基本使用
import numpy as np #标准导入方法
#从Python列表创建数组
>>> np.array([3.14, 4, 2, 3]) #NumPy要求数组必须包含同一类型的数据
array([3.14, 4. , 2. , 3. ])
#用dtype关键字指定元素类型
>>> np.array([3, 4, 2, 3],dtype='float64')
array([3., 4., 2., 3.])
#zeros()、ones()、full()、arange()、linspace()
#random.random()/random.randint()/random.normal()、eye()、empty()
>>> np.zeros(10, dtype=int) #创建一个长度为10的数组,数组的值都是0 注意其shape为(10,)
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
>>> np.ones((3, 5), dtype=float)
array([[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]])
>>> np.full((3,5),31)
array([[31, 31, 31, 31, 31],
[31, 31, 31, 31, 31],
[31, 31, 31, 31, 31]])
>>> np.arange(0,10,2) # 类似于python内置的range函数
array([0, 2, 4, 6, 8])
>>> np.linspace(1,2,5) #创建等差数列 创建一个5个元素的数组,这5个数均匀地分配到1~2
array([1. , 1.25, 1.5 , 1.75, 2. ])
>>> np.random.random((3, 3)) #创建一个3×3的、在0~1均匀分布的随机数组成的数组
array([[0.29754805, 0.10436244, 0.11162626],
[0.20406406, 0.48309063, 0.80017593],
[0.94510514, 0.08344147, 0.13553327]])
>>> np.eye(2) # 创建单位矩阵
array([[1., 0.],
[0., 1.]])
>>> np.empty(3) #创建空数组 注意数组内的值不为空,而是一些垃圾值
array([2.21442477e-314, 2.21454033e-314, 0.00000000e+000])
数组的操作:
1.确定数组的大小、形状、存储大小、数据类型 - ndim、shape、size,dtype
2.获取和设置数组各个元素的值 - 索引 a[-1] a[1,2](a[1][2])
3.在大的数组中获取或设置更小的子数组 - 切片
切片方式: x[start: stop: step]
这里有个逆序小技巧:x[::-1]
>注意:数组切片返回的是数组的视图,而不是副本(便于大数据集的操作)
修改切片会反映到原始数据上,这一点和python内置的list不一样
如果不想改变原始数组的话,可以使用copy()方法
4.改变给定数组的形状 - reshape np.newaxis(反正自己没怎么用过)
5.数组的拼接和分裂
拼接 np.concatenate np.vstack(垂直栈/行) np.hstack (水平栈/列)
第一个参数: 数组元组或数组列表
分裂 np.split、np.hsplit np.vsplit
>>> x = [1, 2, 3, 99, 99, 3, 2, 1]
>>> x1, x2, x3 = np.split(x, [3, 5]) #np.split(数组,[分裂点位置列表])
>>> print(x1, x2, x3)
[1 2 3] [99 99] [3 2 1]
Numpy的强大之处-向量化操作
处理瓶颈并不是运算本身,而是CPython在每次循环时必须做数据类型的检查和函数的调度
numpy中向量化有两种形式,
一元通用函数(unary ufunc),对单个输入操作;
二元通用函数(binary ufunc),对两个输入操作;
np.abs(x) np.sin(x) np.exp(x) np.exp2(x)) np.log(x)
np.power(次方数,x) 等价于 x**次方数
一般在面对大量数据的时候,第一步是计算相关数据的概括统计值,最常用的包括有
求和、乘积、中位数、最小值和最大值、分位数、均值、标准差
#求和 sum(x) np.sum(x)
In [1]:big_array = np.random.rand(1000000)
%timeit sum(big_array)
87 ms ± 2.64 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit np.sum(big_array)
409 µs ± 4.31 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
ps:针对数据的求和、求最大值、最小值,使用np.sum(x)、np.max(x)、np.min(x)更快
#对于多维度的数组来说
In [2]: M = np.random.random((3, 4))
In [3]: M.sum() #对二维数组进行求和 M.sum() 而不是sum(M) sum(M)会得到每一列的和
Out[3]: 4.277430157572991
In [4]: sum(M)
Out[4]: array([1.36862191, 1.39587722, 0.69730366, 0.81562737])
In [5]: M.min(axis=0) # 注意参数 axis 0 沿着行 1 沿着列
Out[5]: array([0.03183734, 0.23139794, 0.10978954, 0.07375324])
Numpy的比较、布尔逻辑(& | ~)、掩码操作
In [6]: x = np.array([1, 2, 3, 4, 5])
In [7]: x < 3
Out[7]: array([ True, True, False, False, False])
In [13]: x = np.random.randint(10,size=(2,3))
In [14]: x
Out[14]:
array([[4, 1, 9],
[7, 7, 6]])
In [15]: np.count_nonzero(x < 6) # np.count_nonzero统计记录的个数
Out[15]: 2
等价于
In [16]: np.sum(x < 6) #由于True = 1 False = 0
Out[16]: 2
# 掩码操作
In [21]: x
Out[21]:
array([[4, 1, 9],
[7, 7, 6]])
In [22]: x<5
Out[22]:
array([[ True, True, False],
[False, False, False]])
In [23]: x[x<5] #返回的是一个一维数组,它包含了所有满足条件的值
Out[23]: array([4, 1])
Numpy的花式索引
利用fancy indexing,结果的形状与索引数组的形状一致,而不是与被索引数组的形状一致
In [30]: x = np.random.randint(100, size=10)
In [31]: x
Out[31]: array([77, 3, 62, 45, 98, 10, 54, 8, 38, 16])
In [32]: ind = np.array([[3,7],[4,5]])
In [33]: x[ind]
Out[33]:
array([[45, 8],
[98, 10]])