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 字面意义,返回布尔数组