3. 数值计算(Numpy)¶
3.1. 数组创建¶
数组的创建方式有很多,较便捷的方式有以下三种
直接创建
In [1]:
import numpy as np
In [2]:
a = np.array([1, 2, 3, 4, 5])
a
Out[2]:
array([1, 2, 3, 4, 5])
类 range
In [3]:
a = np.arange(10)
a
Out[3]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [4]:
a = np.arange(1, 10, 2)
a
Out[4]:
array([1, 3, 5, 7, 9])
创建带尾巴的
In [5]:
a = np.linspace(0, 10, 2)
a
Out[5]:
array([ 0., 10.])
更多便捷创建函数
函数 | 功能 |
---|---|
asarray | 将输入转换为 ndarray,若输入本身是 ndarray 就不复制 |
ones、ones_like | 根据指定形状和 dtype 创建一个全 1 数组 |
zeros、zeros_like | 根据指定形状和 dtype 创建一个全 0 数组 |
empty、empty_like | 创建新数组,但只分配内存空间不赋值 |
eye、identity | 创建一个正方的N×N单位矩阵(对角线为1,其余为0 |
在 pandas 中尽量不要使用 np.empty(),这个函数创建的数组里面是有值的,除非你确定创建的这个数组能被完全赋值,否则后面运算起来很麻烦,这些“空值”的布尔类型是 True,而且 dropna() 方法删不掉。想创建空的 Series ,可以使用 Series(np.nan,index=???) 这样。
3.2. ndarray 对象属性¶
.reshape(shape) 改变数组维度
In [6]:
b = np.linspace(0, 7, 8)
b
Out[6]:
array([ 0., 1., 2., 3., 4., 5., 6., 7.])
In [7]:
b = np.linspace(0, 7, 8).reshape(2, 4)
b
Out[7]:
array([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.]])
In [8]:
b = np.arange(0, 8).reshape(2, 2, 2)
b
Out[8]:
array([[[0, 1],
[2, 3]],
[[4, 5],
[6, 7]]])
.astype(dtype) 改变数组格式
In [9]:
print b.dtype
b
int64
Out[9]:
array([[[0, 1],
[2, 3]],
[[4, 5],
[6, 7]]])
In [10]:
b.astype(float)
Out[10]:
array([[[ 0., 1.],
[ 2., 3.]],
[[ 4., 5.],
[ 6., 7.]]])
.transpose(*axes) 转置, transpose 的属性一直没搞懂
In [11]:
b = np.arange(8).reshape(2, 4)
b
Out[11]:
array([[0, 1, 2, 3],
[4, 5, 6, 7]])
In [12]:
b.T
Out[12]:
array([[0, 4],
[1, 5],
[2, 6],
[3, 7]])
In [13]:
b.transpose()
Out[13]:
array([[0, 4],
[1, 5],
[2, 6],
[3, 7]])
.sort 排序
In [14]:
a = np.array([[1,4],[3,1]])
In [15]:
np.sort(a) # sort along the last axis
Out[15]:
array([[1, 4],
[1, 3]])
In [16]:
np.sort(a, axis=None) # sort the flattened array
Out[16]:
array([1, 1, 3, 4])
In [17]:
np.sort(a, axis=0) # sort along the first axis
Out[17]:
array([[1, 1],
[3, 4]])
stats 基本统计
In [18]:
arr = np.arange(12).reshape(3,4)
In [19]:
arr
Out[19]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
In [20]:
arr.sum()
Out[20]:
66
In [21]:
np.sum(arr)
Out[21]:
66
In [22]:
arr.mean(0) # 列均值
Out[22]:
array([ 4., 5., 6., 7.])
In [23]:
arr.mean(1) # 行均值
Out[23]:
array([ 1.5, 5.5, 9.5])
更多统计方法
sum | 求和 |
mean | 均值 |
std,var | 标准差和方差 |
min,max | 最小值和最大值 |
argmin,argmax | 最小值和最大值的索引 |
cumsum | 累积和 |
cumprod | 累积积 |
3.3. 数组间运算¶
In [24]:
a = np.arange(8).reshape(2, 4)
b = np.ones_like(a)
In [25]:
a + b
Out[25]:
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
In [26]:
a * 2
Out[26]:
array([[ 0, 2, 4, 6],
[ 8, 10, 12, 14]])
3.4. 索引和切片¶
基本索引
In [27]:
foo = np.arange(10)
foo
Out[27]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [28]:
bar = foo[:5].copy() # 若没有 copy,则 bar 的改变会影响 foo
In [29]:
bar
Out[29]:
array([0, 1, 2, 3, 4])
In [30]:
bar[:] = 1
In [31]:
bar
Out[31]:
array([1, 1, 1, 1, 1])
In [32]:
foo
Out[32]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
二维和三维数组如何索引?
In [33]:
arr2d = np.array([[1, 2, 3],[4, 5, 6],[7, 8, 9]])
arr2d
Out[33]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
In [34]:
arr2d[2, 0]
Out[34]:
7
In [35]:
arr3d = np.array([[[1, 2, 3],[4, 5, 6]],
[[7, 8, 9],[10, 11, 12]]])
In [36]:
arr3d[0]
Out[36]:
array([[1, 2, 3],
[4, 5, 6]])
In [37]:
arr3d[0, 1, 2]
Out[37]:
6
切片 从第 0 轴开始的
In [38]:
arr2d
Out[38]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
In [39]:
arr2d.shape
Out[39]:
(3, 3)
In [40]:
arr2d[:1]
Out[40]:
array([[1, 2, 3]])
In [41]:
arr2d[1:4] # 理论上第0轴没有4这个基数
Out[41]:
array([[4, 5, 6],
[7, 8, 9]])
In [42]:
arr2d[:2, :1]
Out[42]:
array([[1],
[4]])
布尔型索引
In [43]:
from numpy.random import randn
data = randn(7, 4) # 生成 7*4 个均值为 0,标准差为 1 的数组
data
Out[43]:
array([[ 0.51659011, -0.14527543, 0.73750985, -0.07181445],
[-0.26857463, 0.34883972, 0.07129706, 0.95455506],
[ 0.43307006, -0.04072156, -1.32443926, 0.1124177 ],
[ 1.39517115, -0.54127346, -0.70176892, -0.21847743],
[ 2.69939163, 0.9403898 , -0.0578206 , 0.50806596],
[-0.41641312, -0.45169815, 0.31717456, -0.34085142],
[ 0.44102963, 0.96447336, -2.92258682, -1.22429012]])
In [44]:
names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'] )
names == 'Bob'
Out[44]:
array([ True, False, False, True, False, False, False], dtype=bool)
当两个轴长度一致时,可以用布尔型的数组切片,比如此例切的是 axis 0
In [45]:
data[names == 'Bob']
Out[45]:
array([[ 0.51659011, -0.14527543, 0.73750985, -0.07181445],
[ 1.39517115, -0.54127346, -0.70176892, -0.21847743]])
In [46]:
data[names == 'Bob', 2:]
Out[46]:
array([[ 0.73750985, -0.07181445],
[-0.70176892, -0.21847743]])
In [47]:
data[~(names == 'Bob')]
Out[47]:
array([[-0.26857463, 0.34883972, 0.07129706, 0.95455506],
[ 0.43307006, -0.04072156, -1.32443926, 0.1124177 ],
[ 2.69939163, 0.9403898 , -0.0578206 , 0.50806596],
[-0.41641312, -0.45169815, 0.31717456, -0.34085142],
[ 0.44102963, 0.96447336, -2.92258682, -1.22429012]])
布尔型数组求并集
In [48]:
mask = (names == "Bob") | (names == "Will")
mask
Out[48]:
array([ True, False, True, True, True, False, False], dtype=bool)
In [49]:
data[mask]
Out[49]:
array([[ 0.51659011, -0.14527543, 0.73750985, -0.07181445],
[ 0.43307006, -0.04072156, -1.32443926, 0.1124177 ],
[ 1.39517115, -0.54127346, -0.70176892, -0.21847743],
[ 2.69939163, 0.9403898 , -0.0578206 , 0.50806596]])
3.5. 利用数组做数据处理¶
将条件逻辑表述为数组运算, np.where 是一个极其有用的三元函数,它其实是一个条件运算函数,即 foo if cond else bar
In [50]:
xarr = np.arange(1.1, 1.6, 0.1)
In [51]:
xarr
Out[51]:
array([ 1.1, 1.2, 1.3, 1.4, 1.5])
In [52]:
yarr = np.arange(2.1, 2.6, 0.1)
In [53]:
yarr
Out[53]:
array([ 2.1, 2.2, 2.3, 2.4, 2.5])
In [54]:
cond = np.array([True, False, True, True, False])
根据 cond 的值选取 xarr 和 yarr 的值
In [55]:
result = [(x if c else y)
for x, y, c in zip(xarr, yarr, cond)]
In [56]:
result
Out[56]:
[1.1000000000000001,
2.2000000000000002,
1.3000000000000003,
1.4000000000000004,
2.5000000000000004]
不够简洁,可用 where 改写
In [57]:
result = np.where(cond, xarr, yarr)
result
Out[57]:
array([ 1.1, 2.2, 1.3, 1.4, 2.5])
np.where 的第二个和第三个参数不必是数组,他们都是标量值
In [58]:
arr = randn(4,4)
arr
Out[58]:
array([[ 2.0086379 , -0.33799069, 0.48232499, 0.00343801],
[-0.54010599, 1.63779772, 1.22284334, -1.34602676],
[ 0.80309605, -0.82099082, -0.8703366 , 0.20060704],
[ 1.10812415, -0.01419402, -0.30237458, 1.30298964]])
In [59]:
np.where(arr > 0, 2, -2) # 正值设置为 2,负值设置为 -2
Out[59]:
array([[ 2, -2, 2, 2],
[-2, 2, 2, -2],
[ 2, -2, -2, 2],
[ 2, -2, -2, 2]])
└ 这个代码的意思其实就是 >0 则 2,else -2
3.6. 其他通用函数¶
一元函数
函数名 | 功用 |
---|---|
abs,fabs | 整数、浮点、复数的绝对值,对于非复数,可用更快的 fabs |
sqrt | 平方根,等于 arr**0.5 |
square | 平方,等于 arr**2 |
exp | 以 e 为底的指数函数 |
log,log10,log2,log1p | 以 e 为底的对数函数 |
sign | 计算各元素的正负号,1(正),0(零),-1(负) |
ceil | 计算大于等于该值的最小整数 |
floor | 计算小于等于该值的最大整数 |
rint | round int,四舍五入到整数 |
modf | 将数组的整数和小数部分以两个独立数组的形式返回 |
isnan | 返回一个 “哪些值是 NaN” 的布尔型数组 |
isfinite,isinf | 返回是否是有穷(无穷)的布尔型数组 |
cos,cosh,sin,sinh,tan,tanh | 普通和双曲型三角函数 |
arccos,arccosh…等同上 | 反三角函数 |
logical_not | 计算个元素 not x 的真值,等于 -arr |
unique | 计算元素唯一值并返回排序后的结果 |
二元函数
函数名 | 功用 |
---|---|
add | 加法,+ |
subtract | 减法,- |
multiply | 乘法,* |
divide,floor_divide | 除法和地板除,/ 和 // |
power | 乘方,** |
maximum,fmax | 元素级最大值,fmax 将忽略 NaN |
minimum,fmin | 同上 |
mod | 取模,% |
copysign | 将第二数组元素的符号复制给第一数组 |
greater(_equal),less(*equal),(not*) equal | 字面意义,返回布尔数组 |
logical_and,logical_or,logical_xor | 字面意义,返回布尔数组 |