【利用python进行数据分析】学习笔记-第4章 NumPy基础

第4章 NumPy基础:数组和矢量运算

  • 引用惯例:import numpy as np
  • 基于NumPy的算法要比纯python快10到100倍(甚至更快),并且使用更少的内存。

4.1NumPy的ndarray:一种多维数组对象

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

4.1.1 创建ndarray

  • 使⽤array函数:接受⼀切序列型的对象(包括其他数组),然后产⽣⼀个新的含有传⼊数据的
    NumPy数组。

    In [19]: data1 = [6, 7.5, 8, 0, 1]
    
    In [20]: arr1 = np.array(data1)
    
    In [21]: arr1
    Out[21]: array([ 6. , 7.5, 8. , 0. , 1. ])
    
  • 嵌套序列

    In [22]: data2 = [[1, 2, 3, 4], [5, 6, 7, 8]]
    
    In [23]: arr2 = np.array(data2)
    
    In [24]: arr2
    Out[24]:
    array([[1, 2, 3, 4],
           [5, 6, 7, 8]])
    
    # 数据维度
    In [25]: arr2.ndim
    Out[25]: 2
    
    # 数据大小
    In [26]: arr2.shape
    Out[26]: (2, 4)
    
  • np.array会尝试为新建的这个数组推断出⼀个较为合适的数据类型。数据类型保存在⼀个特殊的dtype对象中。

    In [27]: arr1.dtype
    Out[27]: dtype('float64')
    
    In [28]: arr2.dtype
    Out[28]: dtype('int64')
    
  • 其它可新建数组的函数

    In [29]: np.zeros(10)
    Out[29]: array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. ])
    
    In [30]: np.zeros((3, 6))
    Out[30]:
    array([[ 0., 0., 0., 0., 0., 0.],
           [ 0., 0., 0., 0., 0., 0.],
           [ 0., 0., 0., 0., 0., 0.]])
    
    In [31]: np.empty((2, 3, 2)) # np.empty不一定返回全0数组,很多情况下它返回的都是⼀些未初始化的垃圾值。
    Out[31]:
    array([[[ 0., 0.],
            [ 0., 0.],
            [ 0., 0.]],
           [[ 0., 0.],
            [ 0., 0.],
            [ 0., 0.]]])
    
    In [32]: np.arange(15)
    Out[32]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 121314]
    

4.1.2 ndarray的数据类型

  • dtype含有ndarray将⼀块内存解释为特定数据类型所需的信息

    In [33]: arr1 = np.array([1, 2, 3], dtype=np.float64)
    
    In [34]: arr2 = np.array([1, 2, 3], dtype=np.int32)
    
    In [35]: arr1.dtype
    Out[35]: dtype('float64')
    
    In [36]: arr2.dtype
    Out[36]: dtype('int32')
    
  • NumPy所有数据类型:

    类型 说明
    int8, uint8 有符号和无符号的8位整数
    int16, uint16 有符号和无符号的16位整数
    int32, uint32 有符号和无符号的32位整数
    int64, uint64 有符号和无符号的64位整数
    float16 半精度浮点数
    float32 标准的单精度浮点数
    float64 标准的双精度浮点数
    float128 扩展精度浮点数
    complex64, complex128, complex256 分别用两个32位, 64位或128位浮点数表示的复数
    bool 布尔类型
  • 数据类型转换:astype

    如果将浮点数转换成整数,则⼩数部分将会被截取删除

    In [37]: arr = np.array([1, 2, 3, 4, 5])
    
    In [38]: arr.dtype
    Out[38]: dtype('int64')
    
    In [39]: float_arr = arr.astype(np.float64)
    
    In [40]: float_arr.dtype
    Out[40]: dtype('float64')
    

4.1.3 NumPy数组的运算

不⽤编写循环即可对数据执⾏批量运算

# ⼤⼩相等的数组之间的任何算术运算都会将运算应⽤到元素级
In [51]: arr = np.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 [55]: 1 / arr
Out[55]:
array([[ 1. , 0.5 , 0.3333],
       [ 0.25 , 0.2 , 0.1667]])

In [56]: arr ** 0.5
Out[56]:
array([[ 1. , 1.4142, 1.7321],
       [ 2. , 2.2361, 2.4495]])

# ⼤⼩相同的数组之间的⽐较会⽣成布尔值数组
In [57]: arr2 = np.array([[0., 4., 1.], [7., 2., 12.]])

In [59]: arr2 > arr
Out[59]:
array([[False,  True, False],
       [ True, False,  True]], dtype=bool)

4.1.4 基本的索引和切片

In [60]: arr = np.arange(10)

In [62]: arr[5]
Out[62]: 5

In [63]: arr[5:8]
Out[63]: array([5, 6, 7])

# 视图上的任何修改都会直接反映到源数组上
In [64]: arr[5:8] = 12

In [65]: arr
Out[65]: array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9])
# 切片
In [66]: arr_slice = arr[5:8]
    
In [67]: arr_slice
Out[67]: array([12, 12, 12])

# 切⽚[:]会给数组中的所有值赋值
In [70]: arr_slice[:] = 64
In [71]: arr
Out[71]: array([ 0, 1, 2, 3, 4, 64, 64, 64, 8, 9])
    
# 高维数组的索引位置上的元素变为数组
In [72]: arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    
In [73]: arr2d[2]
Out[73]: array([7, 8, 9])

# 下面两种方式等价
In [74]: arr2d[0][2]
Out[74]: 3

In [75]: arr2d[0, 2]
Out[75]: 3

4.1.5 切片索引:与python列表相似

In [88]: arr
Out[88]: array([ 0, 1, 2, 3, 4, 64, 64, 64, 8, 9])

In [89]: arr[1:6]
Out[89]: array([ 1, 2, 3, 4, 64])
    
# 二维数组切片
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]])

4.1.6 布尔型索引

In [98]: names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])

In [99]: data = np.random.randn(7, 4)

In [100]: names
Out[100]:
array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'], dtype=')

In [101]: data
Out[101]:
array([[ 0.0929,  0.2817,  0.769 ,  1.2464],
       [ 1.0072, -1.2962,  0.275 ,  0.2289],
       [ 1.3529,  0.8864, -2.0016, -0.3718],
       [ 1.669 , -0.4386, -0.5397,  0.477 ],
       [ 3.2489, -1.0212, -0.5771,  0.1241],
       [ 0.3026,  0.5238,  0.0009,  1.3438],
       [-0.7135, -0.8312, -2.3702, -1.8608]])
       
In [102]: names == 'Bob'
Out[102]: array([ True, False, False, True, False, False, False])

# 这个布尔型数组可⽤于数组索引
In [103]: data[names == 'Bob']
Out[103]:
array([[ 0.0929,  0.2817,  0.769 , 1.2464],
       [ 1.669 , -0.4386, -0.5397, 0.477 ]])

In [104]: data[names == 'Bob', 2:]
Out[104]:
array([[ 0.769 , 1.2464],
       [-0.5397, 0.477 ]])

In [105]: data[names == 'Bob', 3]
Out[105]: array([ 1.2464, 0.477 ])
    
# ~和!=都可以表示否定
In [106]: names != 'Bob'  
Out[106]: array([False, True, True, False, True, True, True])

In [107]: data[~(names == 'Bob')]
Out[107]:
array([[ 1.0072, -1.2962,  0.275 ,  0.2289],
       [ 1.3529,  0.8864, -2.0016, -0.3718],
       [ 3.2489, -1.0212, -0.5771,  0.1241],
       [ 0.3026,  0.5238,  0.0009,  1.3438],
       [-0.7135, -0.8312, -2.3702, -1.8608]])

# 组合引用多个布尔条件
In [110]: mask = (names == 'Bob') | (names == 'Will')
    
In [111]: mask
Out[111]: array([ True, False, True, True, True, False, False])

In [112]: data[mask]
Out[112]:
array([[ 0.0929, 0.2817, 0.769 , 1.2464],
       [ 1.3529, 0.8864, -2.0016, -0.3718],
       [ 1.669 , -0.4386, -0.5397, 0.477 ],
       [ 3.2489, -1.0212, -0.5771, 0.1241]])

4.1.7 花式索引(利⽤整数数组进⾏索引)

In [117]: arr = np.empty((8, 4))

In [118]: for i in range(8):
   .....: arr[i] = i
   
In [119]: arr
Out[119]:
array([[ 0., 0., 0., 0.],
       [ 1., 1., 1., 1.],
       [ 2., 2., 2., 2.],
       [ 3., 3., 3., 3.],
       [ 4., 4., 4., 4.],
       [ 5., 5., 5., 5.],
       [ 6., 6., 6., 6.],
       [ 7., 7., 7., 7.]])

# 为了以特定顺序选取⾏⼦集,只需传⼊⼀个⽤于指定顺序的整数列表或ndarray即可
In [120]: arr[[4, 3, 0, 6]]
Out[120]:
array([[ 4., 4., 4., 4.],
       [ 3., 3., 3., 3.],
       [ 0., 0., 0., 0.],
       [ 6., 6., 6., 6.]])

# 使⽤负数索引将会从末尾开始选取⾏
In [121]: arr[[-3, -5, -7]]
Out[121]:
array([[ 5., 5., 5., 5.],
       [ 3., 3., 3., 3.],
       [ 1., 1., 1., 1.]])

# ⼀次传⼊多个索引数组,返回⼀个⼀维数组,其中的元素对应各个索引元组
In [122]: arr = np.arange(32).reshape((8, 4))
    
In [123]: arr
Out[123]:
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23],
       [24, 25, 26, 27],
       [28, 29, 30, 31]])

In [124]: arr[[1, 5, 7, 2], [0, 3, 1, 2]]
Out[124]: array([ 4, 23, 29, 10])

# 使选取矩阵的行列子集为矩形区域的形式
In [125]: arr[[1, 5, 7, 2]][:, [0, 3, 1, 2]]
Out[125]:
array([[ 4,  7,  5,  6],
       [20, 23, 21, 22],
       [28, 31, 29, 30],
       [ 8, 11,  9, 10]])

4.1.8 数组转置和轴对换

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]])

# 利用T属性转置
In [128]: arr.T 
Out[128]:
array([[ 0, 5, 10],
       [ 1, 6, 11],
       [ 2, 7, 12],
       [ 3, 8, 13],
       [ 4, 9, 14]])

# 利用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需要得到⼀个由轴编号组成的元组才能对这些轴进⾏转置
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]]])

4.2 通用函数:快速的元素级数组函数

通⽤函数(即ufunc)是⼀种对ndarray中的数据执⾏元素级运算的函数

# 一元ufunc,如sqrt和exp
In [137]: arr = np.arange(10)
In [138]: arr
Out[138]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [139]: np.sqrt(arr)
Out[139]:
array([0.        , 1.        , 1.41421356, 1.73205081, 2.        ,
       2.23606798, 2.44948974, 2.64575131, 2.82842712, 3.        ])

In [140]: np.exp(arr)
Out[140]:
array([1.00000000e+00, 2.71828183e+00, 7.38905610e+00, 2.00855369e+01,
       5.45981500e+01, 1.48413159e+02, 4.03428793e+02, 1.09663316e+03,
       2.98095799e+03, 8.10308393e+03])

# 二元func,如add和maximum
In [141]: x = np.random.randn(8)
    
In [142]: y = np.random.randn(8)
    
In [143]: x
Out[143]:
array([-0.0119, 1.0048, 1.3272, -0.9193, -1.5491, 0.0222, -0.6605])

In [144]: y
Out[144]:
array([ 0.8626, -0.01 , 0.05 , 0.6702, 0.853 , -0.9559, -2.3042])

In [145]: np.maximum(x, y)
Out[145]:
array([ 0.8626, 1.0048, 1.3272, 0.6702, 0.853 , 0.0222, -0.6605])

# 返回多个数组的ufunc,如modf
In [146]: arr = np.random.randn(7) * 5
    
In [147]: arr
Out[147]: array([ 0.14637842, 16.6325636 , -3.00944909,  4.40540062,  1.76045076, 0.4892904 , -5.15885562])

In [148]: remainder, whole_part = np.modf(arr) # 返回浮点数的小数部分
                 
In [149]: remainder
Out[149]: array([ 0.14637842,  0.6325636 , -0.00944909,  0.40540062,  0.76045076,
0.4892904 , -0.15885562])
                 
In [150]: whole_part
Out[150]: array([ 0., 16., -3.,  4.,  1.,  0., -5.])

4.3 利用数组进行数据处理

矢量化:⽤数组表达式代替循环的做法

In [155]: points = np.arange(-5, 5, 0.01) 

In [156]: xs, ys = np.meshgrid(points, points)

In [157]: ys
Out[157]:
array([[-5.  , -5.  , -5.  , ..., -5.  , -5.  , -5.  ],
       [-4.99, -4.99, -4.99, ..., -4.99, -4.99, -4.99],
       [-4.98, -4.98, -4.98, ..., -4.98, -4.98, -4.98],
       ...,
       [ 4.97,  4.97,  4.97, ...,  4.97,  4.97,  4.97],
       [ 4.98,  4.98,  4.98, ...,  4.98,  4.98,  4.98],
       [ 4.99,  4.99,  4.99, ...,  4.99,  4.99,  4.99]])

In [158]: z = np.sqrt(xs ** 2 + ys ** 2)
In [159]: z
Out[159]:
array([[ 7.0711, 7.064 , 7.0569, ..., 7.0499, 7.0569, 7.064 ],
       [ 7.064 , 7.0569, 7.0499, ..., 7.0428, 7.0499, 7.0569],
       [ 7.0569, 7.0499, 7.0428, ..., 7.0357, 7.0428, 7.0499],
       ...,
       [ 7.0499, 7.0428, 7.0357, ..., 7.0286, 7.0357, 7.0428],
       [ 7.0569, 7.0499, 7.0428, ..., 7.0357, 7.0428, 7.0499],
       [ 7.064 , 7.0569, 7.0499, ..., 7.0428, 7.0499, 7.0569]])

# 用matplotlib创建这个二维数组的可视化
In [160]: import matplotlib.pyplot as plt

In [161]: plt.imshow(z, cmap=plt.cm.gray); 
          plt.colorbar()
Out[161]: <matplotlib.colorbar.Colorbar at 0x7f715e3fa630>
    
In [162]: plt.title("Image plot of $\sqrt{x^2 + y^2}$ for a grid")
Out[162]: <matplotlib.text.Text at 0x7f715d2de748>

4.3.1将条件逻辑表述为数组运算

注:三元表达式x if condition else y对大数组的处理速度不是很快, 且无法用于多维数组

# numpy.where函数是三元表达式x if condition else y的⽮量化版本
In [165]: xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])

In [166]: yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])

In [167]: cond = np.array([True, False, True, True, False])
    
In [168]: result = [(x if c else y)
   .....: for x, y, c in zip(xarr, yarr, cond)] # 当cond中的值为True时,选取xarr的值,否则从yarr中选取
    
In [169]: result
Out[169]: [1.1, 2.2, 1.3, 1.4, 2.5]

# np.where实现,比起之前更加简洁
In [170]: result = np.where(cond, xarr, yarr)
    
In [171]: result
Out[171]: array([ 1.1, 2.2, 1.3, 1.4, 2.5])
    
# np.where的第⼆个和第三个参数不必是数组,它们都可以是标量值
In [172]: arr = np.random.randn(4, 4)
    
In [173]: arr
Out[173]:
array([[-0.5031, -0.6223, -0.9212, -0.7262],
       [ 0.2229,  0.0513, -1.1577,  0.8167],
       [ 0.4336,  1.0107,  1.8249, -0.9975],
       [ 0.8506, -0.1316,  0.9124,  0.1882]])

In [174]: arr > 0
Out[174]:
array([[False, False, False, False],
       [ True,  True, False,  True],
       [ True,  True,  True, False],
       [ True, False,  True, True]], dtype=bool)

In [175]: np.where(arr > 0, 2, -2)
Out[175]:
array([[-2, -2, -2, -2],
       [ 2,  2, -2,  2],
       [ 2,  2,  2, -2],
       [ 2, -2,  2,  2]])

# 使⽤np.where,可以将标量和数组结合起来。例如,我可⽤常数2替换arr中所有正的值
In [176]: np.where(arr > 0, 2, arr) # set only positive values 
Out[176]:
array([[-0.5031, -0.6223, -0.9212, -0.7262],
       [ 2.    ,  2.    , -1.1577,  2.    ],
       [ 2.    ,  2.    ,  2.    , -0.9975],
       [ 2.    , -0.1316,  2.    ,  2.    ]])

4.3.2 数学和统计方法

可以通过数组上的⼀组数学函数对整个数组或某个轴向的数据进行统计计算。sum、mean以及标准差std等聚合计算

# 对正态分布随机数据做聚类统计
In [177]: arr = np.random.randn(5, 4)

In [178]: arr
Out[178]:
array([[ 2.1695, -0.1149,  2.0037,  0.0296],
       [ 0.7953,  0.1181, -0.7485,  0.585 ],
       [ 0.1527, -1.5657, -0.5625, -0.0327],
       [-0.929 , -0.4826, -0.0363,  1.0954],
       [ 0.9809, -0.5895,  1.5817, -0.5287]])
       
In [179]: arr.mean()
Out[179]: 0.19607051119998253

In [180]: np.mean(arr)
Out[180]: 0.19607051119998253

In [181]: arr.sum()
Out[181]: 3.9214102239996507
    
# mean和sum这类的函数可以接受⼀个axis选项参数,⽤于计算该轴向上的统计值,最终结果是⼀个少⼀维的数组
In [182]: arr.mean(axis=1) # 每行的平均值
Out[182]: array([ 1.022 , 0.1875, -0.502 , -0.0881, 0.3611])
    
In [183]: arr.sum(axis=0) # 每列的和
Out[183]: array([ 3.1693, -2.6345, 2.2381, 1.1486])
    
### 累加
In [184]: arr = np.array([0, 1, 2, 3, 4, 5, 6, 7])
    
In [185]: arr.cumsum()
Out[185]: array([ 0, 1, 3, 6, 10, 15, 21, 28], dtype=int32)
    
# 在多维数组中,累加函数(如cumsum)返回的是同样⼤⼩的数组,但是会根据每个低维的切⽚沿着标记轴计算部分聚类
In [186]: arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])

In [187]: arr
Out[187]:
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

In [188]: arr.cumsum(axis=0)
Out[188]:
array([[ 0,  1,  2],
       [ 3,  5,  7],
       [ 9, 12, 15]])

In [189]: arr.cumprod(axis=1) # 累乘
Out[189]:
array([[ 0,  0,   0],
       [ 3, 12,  60],
       [ 6, 42, 336]])
  • 统计函数
函数 说明
sum 对数组中全部或某轴向的元素求和
mean 算数平方数
std, var 标准差, 方差
min, max 最大值和最小值
argmin, argmax 最大和最小元素的索引
cumsum 累加
cumprod 累乘

4.3.3 用于布尔值数组的方法

# sum可⽤来对布尔型数组中的True值计数
In [190]: arr = np.random.randn(100)

In [191]: (arr > 0).sum()
Out[191]: 42

# any⽤于测试数组中是否存在⼀个或多个True
In [192]: bools = np.array([False, False, True, False])
    
In [193]: bools.any()
Out[193]: True
 
# all可检查数组中所有值是否都是True
In [194]: bools.all()
Out[194]: False

4.3.4 排序

In [195]: arr = np.random.randn(6)

In [196]: arr
Out[196]: array([-0.45591363,  1.14798833,  2.69410768, -0.88924344, 1.04095721, 0.8110316])
    
In [197]: arr.sort()
    
In [198]: arr
Out[198]: array([-0.88924344, -0.45591363,  0.8110316 ,  1.04095721, 1.14798833, 2.69410768])
    
# 多维数组可以在任何⼀个轴向上进⾏排序,只需将轴编号传给sort即可
In [199]: arr = np.random.randn(5, 3)
    
In [200]: arr
Out[200]:
array([[ 0.6033,  1.2636, -0.2555],
       [-0.4457,  0.4684, -0.9616],
       [-1.8245,  0.6254,  1.0229],
       [ 1.1074,  0.0909, -0.3501],
       [ 0.218 , -0.8948, -1.7415]])

In [201]: arr.sort(1) # 按行排序
    
In [202]: arr
Out[202]:
array([[-0.2555,  0.6033, 1.2636],
       [-0.9616, -0.4457, 0.4684],
       [-1.8245,  0.6254, 1.0229],
       [-0.3501,  0.0909, 1.1074],
       [-1.7415, -0.8948, 0.218 ]])

4.3.5 唯⼀化以及其它的集合逻辑

# np.unique⽤于找出数组中的唯⼀值并返回已排序的结果,等同于sort(set(names))
In [206]: names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will'])

In [207]: np.unique(names)
Out[207]:
array(['Bob', 'Joe', 'Will'], dtype=')

In [208]: ints = np.array([3, 3, 3, 2, 2, 1, 1, 4, 4])

In [209]: np.unique(ints)
Out[209]: array([1, 2, 3, 4])
    
# np.in1d⽤于测试⼀个数组中的值在另⼀个数组中的成员资格,返回⼀个布尔型数组
In [211]: values = np.array([6, 0, 0, 3, 2, 5, 6])
    
In [212]: np.inld(values, [2, 3, 6])
Out[212]: array([ True, False, False, True, True, False, True])
  • NumPy中的集合函数

    函数 说明
    unique(x) 计算x中的唯一元素,并返回有序结果
    intersect1d(x, y) 计算x和y中的公共元素,并返回有序结果
    union1d(x, y) 计算x和y的并集,并返回有序结果
    in1d(x, y) 得到一个表示“x的元素是否包含y”的布尔型数组
    setdiff1d(x, y) 集合的差,即元素在x中且不在y中
    setxor1d(x, y) 集合的对称差,即存在于一个数组中但不同时存在于两个数组中的元素

4.4 用于数组的文件输入输出

# np.save和np.load是读写磁盘数组数据的两个主要函数。默认情况下,数组是以未压缩的原始⼆进制格式保存在扩展名为.npy的⽂件中的
In [213]: arr = np.arange(10)

In [214]: np.save('some_array', arr)

In [215]: np.load('some_array.npy')
Out[215]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    
# 通过np.savez可以将多个数组保存到⼀个未压缩⽂件中,将数组以关键字参数的形式传⼊即可
In [216]: np.savez('array_archive.npz', a=arr, b=arr)
    
# 加载.npz⽂件时,你会得到⼀个类似字典的对象,该对象会对各个数组进⾏延迟加载
In [217]: arch = np.load('array_archive.npz')
    
In [218]: arch['b']
Out[218]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

# 如果数据压缩的很好,就可以使⽤numpy.savez_compressed
In [219]: np.savez_compressed('arrays_compressed.npz', a=arr, b=arr)

4.5 线性代数

# NumPy提供了⼀个⽤于矩阵乘法的dot函数
In [223]: x = np.array([[1., 2., 3.], [4., 5., 6.]])

In [224]: y = np.array([[6., 23.], [-1, 7], [8, 9]])

In [225]: x
Out[225]:
array([[ 1., 2., 3.],
       [ 4., 5., 6.]])

In [226]: y
Out[226]:
array([[  6., 23.],
       [ -1.,  7.],
       [  8.,  9.]])
       
In [227]: x.dot(y)
Out[227]:
array([[ 28.,  64.],
       [ 67., 181.]])
       
# x.dot(y)等价于np.dot(x, y)
In [228]: np.dot(x, y)
Out[228]:
array([[ 28.,  64.],
       [ 67., 181.]])
       
# @符也可以⽤作中缀运算符,进⾏矩阵乘法
In [230]: x @ np.ones(3)
Out[230]: array([ 6., 15.])

# numpy.linalg中有⼀组标准的矩阵分解运算以及诸如求逆和⾏列式之类的函数
In [231]: from numpy.linalg import inv, qr

In [232]: X = np.random.randn(5, 5)

In [233]: mat = X.T.dot(X)

In [234]: inv(mat)
Out[234]:
array([[  933.1189,   871.8258, -1417.6902, -1460.4005,  1782.1391],
       [  871.8258,   815.3929, -1325.9965, -1365.9242,  1666.9347],
       [-1417.6902, -1325.9965,  2158.4424,  2222.0191, -2711.6822],
       [-1460.4005, -1365.9242,  2222.0191,  2289.0575, -2793.4224],        
       [ 1782.1391,  1666.9347, -2711.6822, -2793.422 ,  3409.5128]])

In [235]: mat.dot(inv(mat))
Out[235]:
array([[ 1., 0., -0., -0., -0.],
       [-0., 1.,  0.,  0.,  0.],
       [ 0., 0.,  1.,  0.,  0.],
       [-0., 0.,  0.,  1., -0.],
       [-0., 0.,  0.,  0.,  1.]])
       
In [236]: q, r = qr(mat)

In [237]: r
Out[237]:
array([[-1.6914,  4.38  ,  0.1757,  0.4075, -0.7838],
       [ 0.    , -2.6436,  0.1939, -3.072 , -1.0702],
       [ 0.    ,  0.    , -0.8138,  1.5414,  0.6155],
       [ 0.    ,  0.    ,  0.    , -2.6445, -2.1669],
       [ 0.    ,  0.    ,  0.    ,  0.    ,  0.0002]])

4.6 伪随机数生成

  • Python内置的random模块则只能⼀次⽣成⼀个样本值。从下⾯的测试结果中可以看出,如果需要产⽣⼤量样本值,numpy.random快了不⽌⼀个数量级
# ⽤normal来得到⼀个标准正态分布的4×4样本数组
In [238]: samples = np.random.normal(size=(4, 4))

In [239]: samples
Out[239]:
array([[ 0.5732, 0.1933,  0.4429,  1.2796],
       [ 0.575 , 0.4339, -0.7658, -1.237 ],
       [-0.5367, 1.8545, -0.92  , -0.1082],
       [ 0.1525, 0.9435, -1.0953, -0.144 ]])
       
# 可以⽤NumPy的np.random.seed更改随机数⽣成种⼦
In [244]: np.random.seed(1234)

# numpy.random的数据⽣成函数使⽤了全局的随机种⼦。要避免全局状态,你可以使⽤numpy.random.RandomState,创建⼀个与其它隔离的随机数⽣成器
In [245]: rng = np.random.RandomState(1234)

In [246]: rng.randn(10)
Out[246]:
array([ 0.4714, -1.191 , 1.4327, -0.3127, -0.7206, 0.8872, -0.6365, 0.0157, -2.2427])
  • numpy.random函数

    函数 说明
    seed 确定随机数生成器的种子
    permutation 返回一个序列的随机排列
    shuffle 对一个序列就地随机排列
    rand 产生均匀分布的样本值
    randint 从给定上下范围内随机选取整数
    randn 产生正态分布(平均值为0,标准值为1)的样本值
    binomial 产生二项分布的样本值
    normal 产生正态(高斯)分布的样本值
    beta 产生Beta分布的样本值
    chisquare 产生卡方分布的样本值
    gamma 产生Gamma分布的样本值
    uniform 产生在(0,1)中均匀分布的样本值

你可能感兴趣的:(python数据分析,python,numpy,数据分析)