ndarray的数据类型

dtype(数据类型)是一个特殊的对象,它含有ndarray将一块内存解释为特定数据类型所需的信息

a = np.array([1,2,3],dtype=np.float64)
a
array([1., 2., 3.])
a.dtype
dtype('float64')
b = np.array([1,2,3],dtype=np.int32)
b
array([1, 2, 3])
b.dtype
dtype('int32')

numpy的数据类型

类型

类型代码

说明

int8、uint8

i1、u1

有符号和无符号的8位(1个字节)整形

int16、uint16

i2、u2

有符号和无符号的16位(2个字节)整形

int32、uint32

i3、u3

有符号和无符号的32位(4个字节)整形

int64、uint64

i4、u4

有符号和无符号的64位(8个字节)整形

float16

f2

半精度浮点数

float32

f4或f

标准的双精度浮点数。与C的float兼容

float64

f8或d

标准的双精度浮点数。与C的double和python的float对象兼容

float128

f16或g

扩展精度浮点数

complex64 、complex128

c8、c16

分别用两个32位、64位或128位位浮点数表示的复数

complex256

c32

复数

bool


存储True和False值得布尔类型

object

O

Python对象类型

string_

S

固定长度的字符串类型(每个字符一个字节)。例如,要创建一个长度为10的字符串,应使用510

unicode_

U

固定长度的unicode类型(字节数由平台决定)。跟字符串的定义方式一样(如U10)

可以通过ndarray的astype方法显式的转换其dtype:

#整形转浮点型
a = np.array([1,2,3])
a.dtype
dtype('int32')
a_float = a.astype(np.float64)
a_float.dtype
dtype('float64')
#浮点型转整形,小数点后的数字直接舍去
b = np.array([1.2,2.3,3.4])
b.dtype
dtype('float64')
b_int = b.astype(np.int64)
b_int.dtype
dtype('int64')
b_int
array([1, 2, 3], dtype=int64)
#字符串数组全是数字,也可以转为对应的数值形式
c = np.array(['1.2','2.3','3.4'],dtype=np.string_)
c.dtype
dtype('S3')
c.astype(float)
array([1.2, 2.3, 3.4])
#dtype的另一种用法
a = np.array([1,2,3],dtype=np.int64)
b = np.array([1.1,2.2,3.3],dtype=np.float64)
a.astype(b.dtype)
array([1., 2., 3.])
#dtype的简介表示
empty_uint32 = np.empty(8,dtype='u4')
empty_uint32
array([         0,    5177428,        424,          0, 3538688192,
              482,      65793,          0], dtype=uint32)

数组和标量之间的运算

数组可以使你不用编写循环即可对数据执行批量运算。这通常就叫做矢量化。大小相等的数组之间的任何算术运算都会将运算应用用到元素级。

a = np.array([[1,2,3],[4,5,6]])
a
array([[1, 2, 3],
       [4, 5, 6]])
a * a
array([[ 1,  4,  9],
       [16, 25, 36]])
a - a
array([[0, 0, 0],
       [0, 0, 0]])
1 / a
array([[1.        , 0.5       , 0.33333333],
       [0.25      , 0.2       , 0.16666667]])
a ** 0.5
array([[1.        , 1.41421356, 1.73205081],
       [2.        , 2.23606798, 2.44948974]])

基本的索引和切片

一维数组和python列表的功能差不多

a = np.arange(5)
a
array([0,1,2,3,4])
a[3]
3
a[1:3]
array([1, 2])
a[1:3]=15
a
array([ 0, 15, 15,  3,  4])

当把一个标量赋值给一个切片时,该值会自动覆盖原先数组。数组切片是原始数组的视图,视图上的任何修改都会直接反应到原数组上。

a_slice = a[1:3]
In[5]: a_slice[1] = 123456
In[6]: a
Out[6]: array([     0,      1, 123456,      3,      4])
In[7]: a_slice[:] = 64
In[8]: a
Out[8]: array([ 0, 64, 64,  3,  4])

二维数组

In[9]: a2 = np.array([[1,2,3],[4,5,6],[7,8,9]])
In[10]: a2[2]
Out[10]: array([7, 8, 9])
`In[11]: a2[0][2]
Out[11]: 3
In[12]: a2[0,2]
Out[12]: 3

二维数组的索引如下表示

python nparray转换为整数 python numpy.ndarray转string_数组

#三维数组
In[3]: a3 = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
In[4]: a3
Out[4]: 
array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[ 7,  8,  9],
        [10, 11, 12]]])
In[5]: a3[0]
Out[5]: 
array([[1, 2, 3],
       [4, 5, 6]])
In[6]: old_values = a3[0].copy()
In[8]: a3[0] = 42
In[9]: a3
Out[9]: 
array([[[42, 42, 42],
        [42, 42, 42]],

       [[ 7,  8,  9],
        [10, 11, 12]]])
In[10]: a3[0] = old_values
In[11]: a3
Out[11]: 
array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[ 7,  8,  9],
        [10, 11, 12]]])
 In[12]: a3[1,0]
Out[12]: array([7, 8, 9])

切片索引

#一维数组
In[13]: a1 = np.arange(10)
In[14]: a1
Out[14]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In[15]: a1[1:6]
Out[15]: array([1, 2, 3, 4, 5])
#二维数组
In[16]: a2 = np.array([[1,2,3],[4,5,6],[7,8,9]])
In[17]: a2
Out[17]: 
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
In[18]: a2[:2]
Out[18]: 
array([[1, 2, 3],
       [4, 5, 6]])

通过以上例子可以看出,它是沿着第0轴(即第一个中括号)切片的,即切片是沿着一个轴向选取元素的。

In[19]: a2[:2,1:]
Out[19]: 
array([[2, 3],
       [5, 6]])
 In[20]: a2[1,:2]
Out[20]: array([4, 5])
In[21]: a2[2,:1]
Out[21]: array([7])
In[22]: a2[:,:1]
Out[22]: 
array([[1],
       [4],
       [7]])
 In[24]: a2[:2,1:] = 0
In[25]: a2
Out[25]: 
array([[1, 0, 0],
       [4, 0, 0],
       [7, 8, 9]])

布尔值索引
假设一个用于存储数据的数组以及一个存储姓名的数组(含有重复项)。使用numpy.random中的randn函数生成一些正态分布的随机数据

In[29]: names = np.array(['Bob','Joe','Will','Bob','Will','Joe','Joe'])
In[30]: names
Out[30]: array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'], dtype='<U4')
In[31]: data = np.random.randn(7,4)
In[32]: data
Out[32]: 
array([[ 1.06804939,  0.53763406, -0.34468005, -0.26877366],
       [-0.77521385, -1.22275166, -0.40538837, -0.55845101],
       [-1.38442773, -1.45071359,  0.5586666 ,  0.07969325],
       [-0.16880411, -0.3988792 , -1.28797105,  0.62871321],
       [ 1.15519442, -0.40048694,  1.53369361,  0.70366078],
       [ 0.51046507, -1.04062609, -1.3817315 ,  0.87470915],
       [-0.58902799, -0.69330514,  0.49844266, -0.05298475]])

假设每个名字都对应data数组的一行

In[33]: names == "Bob"
Out[33]: array([ True, False, False,  True, False, False, False])
In[34]: data[names == 'Bob']
Out[34]: 
array([[ 1.06804939,  0.53763406, -0.34468005, -0.26877366],
       [-0.16880411, -0.3988792 , -1.28797105,  0.62871321]])
In[35]: data[names == 'Bob',2:]
Out[35]: 
array([[-0.34468005, -0.26877366],
       [-1.28797105,  0.62871321]])
In[36]: data[names == 'Bob',3]
Out[36]: array([-0.26877366,  0.62871321])

选择‘Bob’以外的值可以用不等符号(!=),也可以直接通过非(~)。

In[37]: names != 'Bob'
Out[37]: array([False,  True,  True, False,  True,  True,  True])
In[40]: data[~(names == 'Bob')]
Out[40]: 
array([[-0.77521385, -1.22275166, -0.40538837, -0.55845101],
       [-1.38442773, -1.45071359,  0.5586666 ,  0.07969325],
       [ 1.15519442, -0.40048694,  1.53369361,  0.70366078],
       [ 0.51046507, -1.04062609, -1.3817315 ,  0.87470915],
       [-0.58902799, -0.69330514,  0.49844266, -0.05298475]])

同时选取多个名字的组合需要使用|(或)

In[45]: mask = (names == 'Bob') | (names == 'Will')
In[46]: mask
Out[46]: array([ True, False,  True,  True,  True, False, False])
In[47]: data[mask]
Out[47]: 
array([[ 1.06804939,  0.53763406, -0.34468005, -0.26877366],
       [-1.38442773, -1.45071359,  0.5586666 ,  0.07969325],
       [-0.16880411, -0.3988792 , -1.28797105,  0.62871321],
       [ 1.15519442, -0.40048694,  1.53369361,  0.70366078]])

通过布尔型数组设置值

In[54]: data[data < 0] = 0
In[55]: data
Out[55]: 
array([[1.06804939, 0.53763406, 0.        , 0.        ],
       [0.        , 0.        , 0.        , 0.        ],
       [0.        , 0.        , 0.5586666 , 0.07969325],
       [0.        , 0.        , 0.        , 0.62871321],
       [1.15519442, 0.        , 1.53369361, 0.70366078],
       [0.51046507, 0.        , 0.        , 0.87470915],
       [0.        , 0.        , 0.49844266, 0.        ]])

In[57]: data[names != 'Joe'] = 7
In[58]: data
Out[58]: 
array([[7.        , 7.        , 7.        , 7.        ],
       [0.        , 0.        , 0.        , 0.        ],
       [7.        , 7.        , 7.        , 7.        ],
       [7.        , 7.        , 7.        , 7.        ],
       [7.        , 7.        , 7.        , 7.        ],
       [0.51046507, 0.        , 0.        , 0.87470915],
       [0.        , 0.        , 0.49844266, 0.        ]])

花式索引
花式索引即利用整数数组进行索引。

In[59]: arr = np.empty((8,4))
In[60]: arr
Out[60]: 
array([[6.91409243e-310, 2.20472012e-316, 6.91409302e-310,
        6.91409301e-310],
       [6.91408939e-310, 6.91409300e-310, 6.91409297e-310,
        6.91409301e-310],
       [6.91409175e-310, 6.91408937e-310, 6.91409302e-310,
        6.91409302e-310],
       [6.91409302e-310, 6.91409301e-310, 6.91409300e-310,
        6.91409302e-310],
       [6.91409300e-310, 6.91409302e-310, 6.91409300e-310,
        6.91409193e-310],
       [6.91409195e-310, 6.91409302e-310, 6.91409174e-310,
        6.91409299e-310],
       [6.91409298e-310, 6.91409295e-310, 6.91409301e-310,
        6.91409011e-310],
       [6.91408640e-310, 6.91409302e-310, 6.91409190e-310,
        6.91409300e-310]])
In[61]: for i in range(8):
   ...:     arr[i] = i
   ...:     
In[62]: arr
Out[62]: 
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[63]: arr[[1,2,3,4]]
Out[63]: 
array([[1., 1., 1., 1.],
       [2., 2., 2., 2.],
       [3., 3., 3., 3.],
       [4., 4., 4., 4.]])

使用负数将从末尾开始选取行

In[64]: arr[[-1,-2,-3]]
Out[64]: 
array([[7., 7., 7., 7.],
       [6., 6., 6., 6.],
       [5., 5., 5., 5.]])

一次传入多个索引数组会有一点特别。他返回的是一个一维数组,其中的元素对应各个索引元组

In[67]: arr = np.arange(32).reshape((8,4))#reshape用于重构多维数组形状
In[68]: arr
Out[68]: 
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[70]: arr[[0,1,2,3],[0,1,2,3]]
Out[70]: array([ 0,  5, 10, 15])

为了得到矩阵区域形式的矩阵的行列子集

In[71]: arr[[0,1,2,3]][:,[0,1,2,3]]
Out[71]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])
In[72]: arr[np.ix_([0,1,2,3],[0,1,2,3])]
Out[72]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])

花式索引和切片不一样,它总是将数据复制到新数组中。

数组转置和轴对换
转置是重塑的一种特殊形式,它返回的是源数据的视图(不会进行任何复制操作)。数组不仅有transpose方法,还有一个特殊的T属性。

In[76]: arr = np.arange(15).reshape((3,5))
In[77]: arr
Out[77]: 
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])
In[78]: arr.T
Out[78]: 
array([[ 0,  5, 10],
       [ 1,  6, 11],
       [ 2,  7, 12],
       [ 3,  8, 13],
       [ 4,  9, 14]])

在进行矩阵计算时,经常需要,比如利用numpy.dot计算矩阵内积X**T * X

n[79]: arr = np.random.randn(6,3)
In[80]: arr
Out[80]: 
array([[-1.07635721, -2.07780713, -0.04095446],
       [ 0.08187961, -1.02451744, -0.31626861],
       [ 1.2343947 , -0.04506441, -0.75610648],
       [-1.69744337,  0.12104636, -0.60267598],
       [-0.38439969, -0.5898125 , -0.82001761],
       [ 1.09967225,  2.18918989, -0.48352121]])
In[81]: np.dot(arr.T,arr)
Out[81]: 
array([[ 6.92733555,  4.52559412, -0.10864014],
       [ 4.52559412, 10.52403267, -0.20462317],
       [-0.10864014, -0.20462317,  1.9428401 ]])

对于高维数组,转置需要得到一个由轴编号组成的元组才能对这些轴进行转置。

In[96]: arr = np.arange(16).reshape((2,2,4))
In[97]: arr
Out[97]: 
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]]])
In[98]: arr.transpose((1,0,2))
Out[98]: 
array([[[ 0,  1,  2,  3],
        [ 8,  9, 10, 11]],

       [[ 4,  5,  6,  7],
        [12, 13, 14, 15]]])

shape

index

2

0

2

1

4

2

transpose的参数即是index的元组,同时也是arr中每一个元素的索引,arr中的元素位置随着参数的改变而改变。
多维数组的swapaxes方法。

In[99]: arr.swapaxes(1,2)
Out[99]: 
array([[[ 0,  4],
        [ 1,  5],
        [ 2,  6],
        [ 3,  7]],

       [[ 8, 12],
        [ 9, 13],
        [10, 14],
        [11, 15]]])