numpy基本使用01

"""
author by xiaoyao
"""

NumPy-快速处理数据

import numpy
numpy.__version__
'1.16.5'

ndarray对象

import numpy as np

创建

a = np.array([1, 2, 3, 4])
b = np.array((5, 6, 7, 8))
c = np.array([[1, 2, 3, 4], [4, 5, 6, 7], [7, 8, 9, 10]])
print(a)
print('*'*50)
print(b)
print("*"*50)
print(c)
[1 2 3 4]
**************************************************
[5 6 7 8]
**************************************************
[[ 1  2  3  4]
 [ 4  5  6  7]
 [ 7  8  9 10]]
print("a,b,c的形状依次为:{}{}{}".format(a.shape,b.shape,c.shape))
a,b,c的形状依次为:(4,)(4,)(3, 4)
# 原始c
c
array([[ 1,  2,  3,  4],
       [ 4,  5,  6,  7],
       [ 7,  8,  9, 10]])
# 通过赋值的形式更改c的shape,注意和转置操作的区别!!!
print("c的原始形状为:{}".format(c.shape))
c.shape = 4, 3
c
c的原始形状为:(3, 4)





array([[ 1,  2,  3],
       [ 4,  4,  5],
       [ 6,  7,  7],
       [ 8,  9, 10]])
print("c的当前形状为:{}".format(c.shape))
c的当前形状为:(4, 3)

通过对比,可以发现,这里并不是进行转置操作

print("原始c的样子:{}".format(c.shape))
原始c的样子:(4, 3)
# 通过赋值操作对c的形状更改,这里保证是两行,多少列我不管,设为-1,系统会自动进行计算
c.shape = (2, -1)
c
array([[ 1,  2,  3,  4,  4,  5],
       [ 6,  7,  7,  8,  9, 10]])
print("原始a的样子:{}".format(a.shape))
原始a的样子:(4,)
a
array([1, 2, 3, 4])
d = a.reshape((2,2)) # 也可以用a.reshape(2,2)
print(d)
print("******")
print(a)
[[1 2]
 [3 4]]
******
[1 2 3 4]
# d的shape为2X2,,二维数组,二维数组的元素为"一维数组",
d[0]
array([1, 2])
print("a的长度为%d" % len(a))
print("d的长度为%d" % len(d))
print("d[0]的长度为%d" % len(d[0]))
a的长度为4
d的长度为2
d[0]的长度为2
a[1] = 100 # 将数组a的第1个元素改为100
print("更改元素之后的a:",(a))
print("观察与此同时的d:",(d))
更改元素之后的a: [  1 100   3   4]
观察与此同时的d: [[  1 100]
 [  3   4]]
d = a.reshape(2,2)
d
array([[  1, 100],
       [  3,   4]])
a[0] = 99
d
array([[ 99, 100],
       [  3,   4]])

从而可见,a和d 是共享存储空间的,修改其中任意一个数组的值,都会同时修改另一个数组的内容。

元素类型

c
array([[ 1,  2,  3,  4,  4,  5],
       [ 6,  7,  7,  8,  9, 10]])
print(type(c)) # c这个对象的类型
print(c.dtype) # c中元素的类型
<class 'numpy.ndarray'>
int32
# 通过dtype指定元素的类型
ai32 = np.array([1, 2, 3, 4], dtype=np.int32)
af = np.array([1, 2, 3, 4], dtype=float)
ac = np.array([1, 2, 3, 4], dtype=complex) # 复数,这里为complex128类型
print(ai32.dtype,af.dtype,ac.dtype)
int32 float64 complex128

Numpy有自己的浮点数类型:float16,float32,float64,float128.当使用float64作为dtype参数的时候,效果和内置的float类型相同。

当需要指定dtype类型的时候,也可以传递一个字符串来表示每个元素的数值类型。Numpy中的每个数值类型都有几种字符串表示形式,字符串和类型之间的

对应关系存储在了typeDict字典中。

# 如下程序获取与float64类型对应的所有键值
# 使用列表推导式
[key for key, value in np.typeDict.items() if value is np.float64]
['double', 'd', 12, 'float64', 'Float64', 'f8', 'float_', 'float']
# 通过集合显示typeDict中所有的值
set(np.typeDict.values())
{numpy.bool_,
 numpy.bytes_,
 numpy.complex128,
 numpy.complex128,
 numpy.complex64,
 numpy.datetime64,
 numpy.float16,
 numpy.float32,
 numpy.float64,
 numpy.float64,
 numpy.int16,
 numpy.int32,
 numpy.int32,
 numpy.int64,
 numpy.int8,
 numpy.object_,
 numpy.str_,
 numpy.timedelta64,
 numpy.uint16,
 numpy.uint32,
 numpy.uint32,
 numpy.uint64,
 numpy.uint8,
 numpy.void}
# 如上显示的数值类型,与数组的dtype属性是不同的对象。通过dtype对象的type属性可以获得与其对应的属性。
c.dtype.type
numpy.int32
c.dtype
dtype('int32')
# 通过numpy的数值类型可以创建数组对象,如下计算结果会产生溢出。返回一个负数
a = np.int16(200)
a*a
D:\installation\anaconda3\lib\site-packages\ipykernel_launcher.py:2: RuntimeWarning: overflow encountered in short_scalars
  





-25536

numpy 的数值对象运算速度比python的内置类型运算速度要慢。所有在遇到需要大量计算的时候,尽量避免使用

v1 = 3.14
v2 = np.float64(v1)
print("内置类型:")
%timeit v1*v1
print("numpy的数值运算对象:")
%timeit v2*v2
内置类型:
73.5 ns ± 4.57 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
numpy的数值运算对象:
129 ns ± 9.56 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
# 使用astype()方法可以实现将数组的元素类型进行更改
t1 = np.array([1, 2, 3, 4], dtype=np.float)
t2 = np.array([1, 2, 3, 4], dtype=np.complex)
print("*"*50)
print("t1原始类型:",t1.dtype)
print("t2原始类型:",t2.dtype)
print("类型转换之后:")
t3 = t1.astype(np.int32)
t4 = t2.astype(np.complex64)
print("t1现在类型:",t3.dtype)
print("t2现在类型:",t4.dtype)
**************************************************
t1原始类型: float64
t2原始类型: complex128
类型转换之后:
t1现在类型: int32
t2现在类型: complex64

自动生成数组

# arange()类似于内置函数range(),通过指定开始值,终止值,步长,来创建表示等差数列的一维数组。结果不包含终止值

np.arange(0, 1, 0.1)
array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
# linspace()通过指定开始值,终止值,元素个数来创建等差数列。可以通过endpoint来指定是否包含终止值。默认为True
np.linspace(0, 1, 10) # 步长为1/9
array([0.        , 0.11111111, 0.22222222, 0.33333333, 0.44444444,
       0.55555556, 0.66666667, 0.77777778, 0.88888889, 1.        ])
np.linspace(0, 1, 10, endpoint=False) # 步长为1/10
array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
np.linspace(0, 1, 10,retstep=True, endpoint=False) # 设置返回步长
(array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]), 0.1)
# logspace()产生的是等比数列。默认底数为10,默认包含尾数
np.logspace(0, 2, 5)
array([  1.        ,   3.16227766,  10.        ,  31.6227766 ,
       100.        ])
np.logspace(0, 1, 12, base=2, endpoint=False) # 设置底数为2,不含尾数
array([1.        , 1.05946309, 1.12246205, 1.18920712, 1.25992105,
       1.33483985, 1.41421356, 1.49830708, 1.58740105, 1.68179283,
       1.78179744, 1.88774863])
np.logspace(0, 1, 12, base=2, endpoint=False).dtype # 元素类型默认为float64
dtype('float64')

zeros(),ones(),empty()可以创建指定形状和类型的数组。全零/全壹/不分配内存

# empty()仅仅分配数组所使用的内存,不对数组元素进行初始化
np.empty((2,3), np.int)
array([[         0, 1072168960,          0],
       [1072168960,          0,          0]])
# 将数组元素初始化为零
np.zeros(4, np.int)
array([0, 0, 0, 0])
# 将数组元素初始化为1
np.ones(4, np.int)
array([1, 1, 1, 1])
np.ones(4, np.int).dtype
dtype('int32')
# full()将数组元素初始化为指定的值
np.full(4, np.pi)
array([3.14159265, 3.14159265, 3.14159265, 3.14159265])
np.full(4, np.pi).dtype
dtype('float64')
np.pi
3.141592653589793

此外,zeros_like(),ones_like(),empty_like(),full_like()等函数创建与参数数组的形状,类型相同的数组。

zeros_like(a) 和zeros(a.shape,a.dtype)是等价的。

frombuffer(),fromstring(),fromfilw()等函数可以从字节序列或者文件创建数组。

s = b"abcdefgh"
# 推荐使用frombuffer()
np.fromstring(s, dtype=np.int8)
D:\installation\anaconda3\lib\site-packages\ipykernel_launcher.py:2: DeprecationWarning: The binary mode of fromstring is deprecated, as it behaves surprisingly on unicode inputs. Use frombuffer instead
  





array([ 97,  98,  99, 100, 101, 102, 103, 104], dtype=int8)
# frombuffer将s以流的形式读入,并转化成ndarray对象

# data是字符串的时候,Python3默认str是Unicode类型,所以要转成bytestring在原str前加上b
np.frombuffer(s, dtype=np.int8)
array([ 97,  98,  99, 100, 101, 102, 103, 104], dtype=int8)
print(98*256+97)
np.fromstring(s, dtype=np.int16) # 推荐使用frombuffer()
25185


D:\installation\anaconda3\lib\site-packages\ipykernel_launcher.py:2: DeprecationWarning: The binary mode of fromstring is deprecated, as it behaves surprisingly on unicode inputs. Use frombuffer instead
  





array([25185, 25699, 26213, 26727], dtype=int16)
# 使用frombuffer()创建的额数组与原来的字符串是共享内存空间的,由于str是只读的,故而这里无法修改数组内容。
buf = np.frombuffer(s, dtype=np.int16)
buf[1] = 10
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-67-31ad7f34d8a4> in <module>
      1 buf = np.frombuffer(s, dtype=np.int16)
----> 2 buf[1] = 10


ValueError: assignment destination is read-only
# 从函数创建数组
def func(i):
    return i % 4 + 1
# 第一个参数是:计算每个元素的函数,第二个参数指定数组的形状。
np.fromfunction(func, (10,))
array([1., 2., 3., 4., 1., 2., 3., 4., 1., 2.])
# 说明:fromfunction(),这里的计算方式:按照方向向下的y轴,向右的x轴,从原点出发。

# 这里的func()仅仅进行了x的操作,具体就是:0%4+1,1%4+1,2%4+1.。。。共产生10个元素就行
def func2(i, j):
    return (i + 1) * (j + 1)
np.fromfunction(func2, (9,9))
array([[ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.],
       [ 2.,  4.,  6.,  8., 10., 12., 14., 16., 18.],
       [ 3.,  6.,  9., 12., 15., 18., 21., 24., 27.],
       [ 4.,  8., 12., 16., 20., 24., 28., 32., 36.],
       [ 5., 10., 15., 20., 25., 30., 35., 40., 45.],
       [ 6., 12., 18., 24., 30., 36., 42., 48., 54.],
       [ 7., 14., 21., 28., 35., 42., 49., 56., 63.],
       [ 8., 16., 24., 32., 40., 48., 56., 64., 72.],
       [ 9., 18., 27., 36., 45., 54., 63., 72., 81.]])

存取元素

可以使用和列表相同的方式进行元素存取

# 先产生一个0~9的一维数组
a = np.arange(10)
a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# 按照下标
print(a[5])
# 切片存取
print(a[3:5])
# 切片缺省
print(a[:5])
# 负数切片
print(a[:-1]) # 输出前9个元素
5
[3 4]
[0 1 2 3 4]
[0 1 2 3 4 5 6 7 8]
a[1:-1:2] # 在中间8个元素中,按照步长为2进行访问
array([1, 3, 5, 7])
a[::-1] # 这里实现逆序输出,意思是:访问全部元素,步长为-1,,也就是从9到0
array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
a[5:1:-2] # 从下标5到下标1(注意不含尾数下标对应的值),步长为-2
array([5, 3])

和列表不同,通过切片获取的新数组是原始数组的一个试图。与原始数组共享存储空间

# 新建列表
list01 = [1,2,3,4,5]
list_01 = list01[2:4]
print("list_01的值:{}".format(list_01))
# 修改list_01的值
list_01 = [99,97]
print("修改过后的list_01:{}".format(list_01))
print("注意,这时候的list01:{}".format(list01))
list_01的值:[3, 4]
修改过后的list_01:[99, 97]
注意,这时候的list01:[1, 2, 3, 4, 5]
a[2:4] = 100, 101 # 通过赋值修改下标为2,3的元素值
a
array([  0,   1, 100, 101,   4,   5,   6,   7,   8,   9])
b = a[3:7] # 通过切片产生一个新的数组b,b和a共享同一块数据存储空间
b[2] = -10 # 将b的第2个元素修改为-10
print(b)
print(a)
a
[101   4 -10   6]
[  0   1 100 101   4 -10   6   7   8   9]





array([  0,   1, 100, 101,   4, -10,   6,   7,   8,   9])
x = np.arange(10, 1, -1)
x
array([10,  9,  8,  7,  6,  5,  4,  3,  2])

除开使用切片,还可以使用:整数列表,整数数组,布尔数组这些高级下标存取方法

a = x[[3, 3, 1, 8]]
b = x[[3, 3, -3, 8]]
print(a)
print(b)
[7 7 9 2]
[7 7 4 2]
# 这里的b和x不共享内存
b[2] = 100
print(b)
print(x)
[  7   7 100   2]
[10  9  8  7  6  5  4  3  2]
x[[3,5,1]] = -1, -2, -3
x
array([10, -3,  8, -1,  6, -2,  4,  3,  2])
# 当下标为一维数组的时候,作用和使用列表作为下标的结果相同
x = np.arange(10,1,-1)
x[np.array([3,3,1,8])] 
array([7, 7, 9, 2])
# 当下表是多维数组,得到的结果也是多维数组
x[np.array([[3,3,1,8],[3,3,-3,8]])] 
array([[7, 7, 9, 2],
       [7, 7, 4, 2]])
x[np.array([[3,3,1,8],[3,3,-3,8]])].shape
(2, 4)
x[[3,3,1,8,3,3,-3,8]].reshape(4,2) # 改变数组形状
array([[7, 7],
       [9, 2],
       [7, 7],
       [4, 2]])
x = np.arange(5,0,-1)
x
array([5, 4, 3, 2, 1])
# 使用布尔数组
x[np.array([True, False, True, False, False])] 
array([5, 3])
np.__version__
'1.16.5'

在numpy1.1版本之后,布尔列表会被处理为布尔数组。

x[[True, False, True, False, False]] 
array([5, 3])

WARNING

在NumPy 1.10之后的版本中布尔列表会被当作布尔数组,因此上面的运行结果会变成array([5, 3])

# 布尔数组的维度要与x的维度要一致,不然,,嘿嘿嘿
x[np.array([True, False, True, True])] 
---------------------------------------------------------------------------

IndexError                                Traceback (most recent call last)

<ipython-input-105-f6750cd4560d> in <module>
      1 # 布尔数组的维度要与x的维度要一致,不然,,嘿嘿嘿
----> 2 x[np.array([True, False, True, True])]


IndexError: boolean index did not match indexed array along dimension 0; dimension is 5 but corresponding boolean dimension is 4
x[np.array([True,False,True,True,False])]
array([5, 3, 2])
x[np.array([True, False, True, True,False])] = -1, -2, -3   # 将True对应的元素值更改
x
array([-1,  4, -2, -3,  1])
x = np.random.randint(0, 10, 6) # 产生一个长度为6,元素值为0到9的随机整数数组
x
array([1, 8, 8, 1, 6, 3])
x > 5 # 返回布尔数组
array([False,  True,  True, False,  True, False])
[x for x in x if x>5] # 使用列表推导式,输出x中大于5的元素值
[8, 8, 6]
x[x > 5] # 本质上使用布尔数组作为下边进行访问
array([8, 8, 6])

多维数组

# 这里实际上是一个加发表,由纵向0~10和横向量0~5元素相加而成。
a = np.arange(0, 60, 10).reshape(-1, 1) + np.arange(0, 6) # arange(start,stop,step),产生步长为10,在范围【0,60)之间的一维数组.
a
array([[ 0,  1,  2,  3,  4,  5],
       [10, 11, 12, 13, 14, 15],
       [20, 21, 22, 23, 24, 25],
       [30, 31, 32, 33, 34, 35],
       [40, 41, 42, 43, 44, 45],
       [50, 51, 52, 53, 54, 55]])
xy = np.arange(0,6)
xy
array([0, 1, 2, 3, 4, 5])
# 又例如:
xy = np.arange(1,20,5).reshape(-1,1)
xy
array([[ 1],
       [ 6],
       [11],
       [16]])
xy = np.arange(1,20,5).reshape(-1,1)+np.arange(2,6)
xy
array([[ 3,  4,  5,  6],
       [ 8,  9, 10, 11],
       [13, 14, 15, 16],
       [18, 19, 20, 21]])
np.arange(2,6)
array([2, 3, 4, 5])
a
array([[ 0,  1,  2,  3,  4,  5],
       [10, 11, 12, 13, 14, 15],
       [20, 21, 22, 23, 24, 25],
       [30, 31, 32, 33, 34, 35],
       [40, 41, 42, 43, 44, 45],
       [50, 51, 52, 53, 54, 55]])
a[0, 3:5] # 从第0行,3~5列,不含第五列,输出对应元素
array([3, 4])
a[4:, 4:] # 输出从第四行,第四列开始的所有元素
array([[44, 45],
       [54, 55]])
a[:, 2] # 输出第二列的所有元素
array([ 2, 12, 22, 32, 42, 52])
a[2::2, ::2] # 从第二行,步长为2,所有列,步长为2,,输出对应的元素
array([[20, 22, 24],
       [40, 42, 44]])
# 如果下标中仅包含整数和切片,那么得到的数组和原始数组共享数据,是原数组的一个视图。

# 切片访问列表,不共享
# 切片访问一维数组,共享
# 使用布尔数组访问一维数组,不共享

x = np.arange(0,6)
print(x) 
x[np.array([True,False,False,True,False,False])] = 99, 97
print("修改过后的x:{}".format(x))
x_1 = x[np.array([True,False,False,True,False,False])] 
print(x_1)
x_1[np.array([True,False])] = 60
print(x_1)
print(x)
[0 1 2 3 4 5]
修改过后的x:[99  1  2 97  4  5]
[99 97]
[60 97]
[99  1  2 97  4  5]
b = a[0, 3:5]
b[0] = -b[0]
a[0, 3:5]
array([-3,  4])
b
array([-3,  4])
a
array([[ 0,  1,  2, -3,  4,  5],
       [10, 11, 12, 13, 14, 15],
       [20, 21, 22, 23, 24, 25],
       [30, 31, 32, 33, 34, 35],
       [40, 41, 42, 43, 44, 45],
       [50, 51, 52, 53, 54, 55]])

在【】中可以使用冒号隔开的两个或者三个整数表示切片。单独生成切片对象的时候,需要使用slice(开始值,结束值,间隔步长)。当有参数缺省,则写为:None

idx = slice(None, None, 2), slice(2,None) # 行的访问:所有行,步长为2,列的访问:从第2列开始,所有的列
a[idx]
array([[ 2, -3,  4,  5],
       [22, 23, 24, 25],
       [42, 43, 44, 45]])
a[idx][idx] # 相当于两次上述操作
array([[ 4,  5],
       [44, 45]])

使用上述的内置函数slice()创建下标,比较麻烦。可以使用s_对象来辅助生成下标。s_是IndexExpression类的一个对象。

type(np.s_)  # 显示类型
numpy.lib.index_tricks.IndexExpression
np.s_[::2, 2:]
(slice(None, None, 2), slice(2, None, None))
a
array([[ 0,  1,  2, -3,  4,  5],
       [10, 11, 12, 13, 14, 15],
       [20, 21, 22, 23, 24, 25],
       [30, 31, 32, 33, 34, 35],
       [40, 41, 42, 43, 44, 45],
       [50, 51, 52, 53, 54, 55]])
# 从两个序列的对应位置取出两个整数组成下标。分别为a[0,1],a[1,2]
a[(0,1,2,3),(1,2,3,4)]
array([ 1, 12, 23, 34])
a[0:2] # 前两行
array([[ 0,  1,  2, -3,  4,  5],
       [10, 11, 12, 13, 14, 15]])
a[0,2] # 第0行,第二列对应的元素
2
a[:,0:2] # 前两列元素
array([[ 0,  1],
       [10, 11],
       [20, 21],
       [30, 31],
       [40, 41],
       [50, 51]])
a[3:, [0,2,5]]
array([[30, 32, 35],
       [40, 42, 45],
       [50, 52, 55]])

注意这里mask如果不是布尔数组,他就按照对应的下标进行访问

mask = np.array([1,0,1,0,0,1], dtype=np.bool)   # 访问第二列(准确的讲:下标为2的列),对应第0,2,5 行的元素
a[mask, 2]
array([ 2, 22, 52])
mask1 = np.array([1,0,1,0,0,1])
mask2 = [True,False,True,False,False,True]
print(a[mask1, 2]) # 分别对应,一行2列,0行2列.....
print(a[mask2, 2])
[12  2 12  2  2 12]
[ 2 22 52]
a
array([[ 0,  1,  2, -3,  4,  5],
       [10, 11, 12, 13, 14, 15],
       [20, 21, 22, 23, 24, 25],
       [30, 31, 32, 33, 34, 35],
       [40, 41, 42, 43, 44, 45],
       [50, 51, 52, 53, 54, 55]])
a[[1,2],:] # 对应下标为1,2的行,所有的列
array([[10, 11, 12, 13, 14, 15],
       [20, 21, 22, 23, 24, 25]])
a[[1,2]] # 作用同上
array([[10, 11, 12, 13, 14, 15],
       [20, 21, 22, 23, 24, 25]])
a[:,[1,2]] # 这里的作用对象就是列了,,
array([[ 1,  2],
       [11, 12],
       [21, 22],
       [31, 32],
       [41, 42],
       [51, 52]])
a
array([[ 0,  1,  2, -3,  4,  5],
       [10, 11, 12, 13, 14, 15],
       [20, 21, 22, 23, 24, 25],
       [30, 31, 32, 33, 34, 35],
       [40, 41, 42, 43, 44, 45],
       [50, 51, 52, 53, 54, 55]])
x = np.array([[0,1],[2,3]])   # 元素对应。0行-1列,1行-2列,2行-3列,3行-4列。。。这里对应的是下标(从0开始计数)
print("x是:{}".format(x))
y = np.array([[-1,-2],[-3,-4]])
print("y是:{}".format(y))
a[x,y]
x是:[[0 1]
 [2 3]]
y是:[[-1 -2]
 [-3 -4]]





array([[ 5, 14],
       [23, 32]])
a[(0,1,2,3),(-1,-2,-3,-4)].reshape(2,2) # 同上
array([[ 5, 14],
       [23, 32]])
a[x]  # 0,1,2,3行
array([[[ 0,  1,  2, -3,  4,  5],
        [10, 11, 12, 13, 14, 15]],

       [[20, 21, 22, 23, 24, 25],
        [30, 31, 32, 33, 34, 35]]])
palette = np.array( [ [0,0,0],                
                      [255,0,0],              
                      [0,255,0],              
                      [0,0,255],              
                      [255,255,255] ] )       
image = np.array( [ [ 0, 1, 2, 0 ],           
                    [ 0, 3, 4, 0 ]  ] )
print(palette.shape)
print(palette[image])   # 都是行,
(5, 3)
[[[  0   0   0]
  [255   0   0]
  [  0 255   0]
  [  0   0   0]]

 [[  0   0   0]
  [  0   0 255]
  [255 255 255]
  [  0   0   0]]]

结构数组

persontype = np.dtype({ #❶
    'names':['name', 'age', 'weight'],  # 定义每个字段的名字
    'formats':['S30','i', 'f']}, align=True) # 定义每个字段的类型 ,S30表示长度为30个字节的字符串
a = np.array([("Zhang", 32, 75.5), ("Wang", 24, 65.2)], #❷
    dtype=persontype)
a[0] # a 的第一个元素
(b'Zhang', 32, 75.5)
a[0][0] # a 的第一个元素的第一个元素
b'Zhang'
a.dtype
dtype({'names':['name','age','weight'], 'formats':['S30','<i4','<f4'], 'offsets':[0,32,36], 'itemsize':40}, align=True)
print( a[0])
a[0].dtype
(b'Zhang', 32, 75.5)





dtype({'names':['name','age','weight'], 'formats':['S30','<i4','<f4'], 'offsets':[0,32,36], 'itemsize':40}, align=True)

i:忽视字节顺序,<:低位字节在前,>:高位字节在前

a[0]["name"]
b'Zhang'
a[1]
(b'Wang', 24, 65.2)
c = a[1]
c["name"] = "Li"
a[1]["name"]
b'Li'
a[1]
(b'Li', 24, 65.2)
b=a["age"]
b[0] = 40
print( a[0]["age"])
40

通过a.tostring()或者a.tofile()方法,可以将数组a以二进制的方式转换成为字符串或者直接写入到文件中

a.tofile("./test.bin")  # 文件名为:test.txt ,放在当前工作目录

利用下面大的C语言,可以讲上述文件中的数据读取出来。%%file是Ipython的魔法命令,他将该单元格中的文本保存成为:read_struct_array.c

%%file read_struct_array.c

#include <stdio.h>
struct person 
{
    char name[30];
    int age;
    float weight;
};

struct person p[3];

void main ()
{
    FILE *fp;
    int i;
    fp=fopen("./test.bin","rb");
    fread(p, sizeof(struct person), 2, fp);
    fclose(fp);
    for(i=0;i<2;i++)
    {
        printf("%s %d %f\n", p[i].name, p[i].age, p[i].weight);
    }
}
Overwriting read_struct_array.c
np.dtype([('f1', [('f2', np.int16)])]) # 结构类型中包含其他的结构类型
dtype([('f1', [('f2', '<i2')])])
np.dtype([('f0', 'i4'), ('f1', 'f8', (2, 3))]) # 当某个字段类型为数组的时候,用元组的第三个元素表示其形状  这里就是shape为(2,3)的浮点数组
dtype([('f0', '<i4'), ('f1', '<f8', (2, 3))])
np.dtype({'surname':('S25',0),'age':(np.uint8,25)}) # 类型描述是一个元组,他的第二个值给出字段以字节为单位的偏移量。
dtype([('surname', 'S25'), ('age', 'u1')])

内存结构

a = np.array([[0,1,2],[3,4,5],[6,7,8]], dtype=np.float32)
a
array([[0., 1., 2.],
       [3., 4., 5.],
       [6., 7., 8.]], dtype=float32)
b = a[::2, ::2]
print(b)
print(b.strides) # 数组对象使用strides属性保存每个轴上相邻两个元素的地址差,当某个轴的下标增加1的时候,数据存储区的指针增加的字节数
[[0. 2.]
 [6. 8.]]
(24, 8)
c = np.array([[0,1,2],[3,4,5],[6,7,8]], dtype=np.float32, order="F")
c.strides
(4, 12)
print(a.flags) # 数组的flags属性描述了数据存储区域的一些属性,
print("c_contiguous:", a.flags.c_contiguous)
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False
c_contiguous: True
  • C_CONTIGUOUS:数据存储区域是否是c语言格式的连续区域
  • F_CONTIGUOUS:数据存储区域是否是Fortran语言格式的连续区域。
  • OWNDATA:数组是否拥有此数据存储区域,当一个数组是其他数组的视图的时候,他不拥有数据存储区域。
a.T.flags # 查看a的转置标志
  C_CONTIGUOUS : False
  F_CONTIGUOUS : True
  OWNDATA : False
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False
b.flags
  C_CONTIGUOUS : False
  F_CONTIGUOUS : False
  OWNDATA : False
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False
id(b.base) # 通过视图的base属性,可以获得保存数据的原始数组。
2330882035184
id(a)
2330882035184
  • 通过使用view()方法从同一块数据区创建不同的dtype的数组对象,也就是使用不同的数组类型查看同一段内存中的二进制数据。
a = np.array([[0, 1], [2, 3], [4, 5]], dtype=np.float32)
b = a.view(np.uint32) # 把每四个字节当作无符号32位整数处理
c = a.view(np.uint8)  # 把每个字节当作一个单字节的无符号整数
print("a",a)
print(b)
print("*"*50)
print(c)
a [[0. 1.]
 [2. 3.]
 [4. 5.]]
[[         0 1065353216]
 [1073741824 1077936128]
 [1082130432 1084227584]]
**************************************************
[[  0   0   0   0   0   0 128  63]
 [  0   0   0  64   0   0  64  64]
 [  0   0 128  64   0   0 160  64]]
a[0, 0] = 3.14
a
array([[3.14, 1.  ],
       [2.  , 3.  ],
       [4.  , 5.  ]], dtype=float32)

通过view()方法获取的新数组与原数组共享内存,当修改a[0,0]的时候,b[0,0]也会被修改

b[0, 0]
1078523331
c[0, :4]
array([195, 245,  72,  64], dtype=uint8)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章