您的位置:首页 > 编程语言 > Python开发

Numpy-ndarray对象

2017-10-23 13:58 344 查看
转自请注明出处http://blog.csdn.net/JavaMoo/article/details/78318140

NumPy中使用ndarry对象表示数组,它是整个库的核心,NumPy所有的函数都是围绕ndarray对象进行处理,ndarray可以高效的存储大量的数值元素,提高数组的运算速度,还能与各种扩展库进行数据交换

1.1.1创建

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], [5, 6, 7, 8], [9, 10, 11, 12]])
print(b)
print(c)
# 返回一个表示各个轴的长度的元组
print('返回一个表示各个轴的长度的元组')
print(a.shape)
print(c.shape)
# 改变每个轴的大小,不是对数组转置,且数组中内存的位置没有改变
print('改变轴的大小')
# 某个轴的长度是-1的化则自动计算此轴的长度
c.shape = (4, 3)
print(c)
# 使用数组的reshape方法,创建指定形状的新数组,而原数组形状保持不变
d = a.reshape((2, 2))
print('创建指定形状的新数组')
print(d)
# 数组a和d是共享存储空间的,所以修改a,d任意一个元素都会影响另一个数组的元素
a[1] = 100
print('修改a数组元素后查看b')
print(d)


运算结果

[5 6 7 8]
[[ 1  2  3  4]
[ 5  6  7  8]
[ 9 10 11 12]]
返回一个表示各个轴的长度的元组
(4,)
(3, 4)
改变轴的大小
[[ 1  2  3]
[ 4  5  6]
[ 7  8  9]
[10 11 12]]
创建指定形状的新数组
[[1 2]
[3 4]]
修改a数组元素后查看b
[[  1 100]
[  3   4]]


1.1.2元素类型

def np_type():
c = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(c.dtype)
print('指定ndarray的类型')
# float和complex为python内置的浮点类型和复数类型而np.int32是numpy定义的心得数据类型
ai32 = np.array([1, 2, 3, 4], dtype=np.int32)
af = np.array([1, 2, 3, 4], dtype=np.float)
ac = np.array([1, 2, 3, 4], dtype=np.complex)
print('ai32 类型为:%s,af的类型:%s,ac类型:%s' % (ai32.dtype, af.dtype, ac.dtype))
a = [key for key, value in np.typeDict.items() if value is np.float64]
print(a)
# 通过NumPy的数值类型可以创建数值对象,它与Python的整数对象不同,它的取值范围有限计算
a = np.int16(200)
# 计算200*200溢出
print('溢出计算200*200')
print(a * a)
# 比较Numpy和python内置类型的运算性能:NumPy自带对象比python内置运行慢很多
compare_Python_float64_NumPy_float()
# 可以使用astype方法对数组的元素进行转换
t1 = np.array([1, 2, 3, 4], dtype=np.float)
t2 = np.array([1, 2, 3, 4], dtype=np.complex)
t3 = t1.astype(np.int32)
t4 = t2.astype(np.complex64)

def compare_Python_float64_NumPy_float():
v1 = 3.14
v2 = np.float64(v1)
time1_begin = int(time.time() * 1000)
for i in range(0, 10000):
b = v1 * v1
endtime1 = int(time.time() * 1000)
for i in range(0, 10000):
b = v2 * v2
endtime2 = int(time.time() * 1000)
print('python内置数据类型耗费时间%f,Numpy耗费时间%f' % (endtime1 - time1_begin, endtime2 - endtime1))


运行结果

int32

F:/py_learn/mynumpy/np_create.py:45: RuntimeWarning: overflow encountered in short_scalars

指定ndarray的类型

print(a * a)

ai32 类型为:int32,af的类型:float64,ac类型:complex128

[‘double’, ‘d’, 12, ‘float64’, ‘Float64’, ‘float_’, ‘float’]

溢出计算200*200

-25536

python内置数据类型耗费时间1.000000,Numpy耗费时间3.000000

1.1.3自动生成数组

# 开始值,终值,步长
print('利用arange创建数组')
a = np.arange(0, 1, 0.1)
print(a)
print('通过linspace创建素组 endpoint 为是否包含默认值,默认值为True即包含终值')
b = np.linspace(0, 1, 10)
print(b)
print('linspace 不包含终值')
b = np.linspace(0, 1, 10, endpoint=False)
print(b)
print('利用logspace创建等比数列 base默认为10 通过base修改基')
b = np.logspace(1, 5, 5, base=2)
print(b)
print('利用zeros(),ones(),empty()创建指定形状和类型的数组')
b = np.empty((2, 3), np.int)
print(b)
print('zeros()将数组初始化为0,ones将数组初始化为1,full()将数组初始化为指定的值')
print('zeros_like(),ones_like(),full_like()等函数创建与参数数组形状和类型相同的数组')
print('字符串每个字符占一个字节,如果从字符串s创建一个8位整数数组,则数组元素是ASCII编码')
s = "abcdefgh"
c = np.fromstring(s, dtype=np.int8)
print(c)
print('如果从字符串s床架16位的整数数组,那么相邻两个字节就表示一个整数')
c = np.fromstring(s, dtype=np.int16)
print(c)
# fromstring会对字符串的字节序列进行复制,而frombuffer创建的数组与原始字符串共享内存,但是字符串可读所以无法修改创建的数组内容
# buf = np.frombuffer(s, dtype=np.int16)
# buf[1] = 10
print('# 利用fromfunction创建数组 第一个参数是计算每个数组元素的函数,第二个是构造的数组的形状')
d = np.fromfunction(func, (10,))
print(d)
print('# 利用函数创建乘法表数组')
e = np.fromfunction(func2, (9, 9))
print(e)


运行结果

利用arange创建数组
[ 0.   0.1  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9]
通过linspace创建素组 endpoint 为是否包含默认值,默认值为True即包含终值
[ 0.          0.11111111  0.22222222  0.33333333  0.44444444  0.55555556
0.66666667  0.77777778  0.88888889  1.        ]
linspace 不包含终值
[ 0.   0.1  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9]
利用logspace创建等比数列 base默认为10 通过base修改基
[  2.   4.   8.  16.  32.]
利用zeros(),ones(),empty()创建指定形状和类型的数组
[[       186          0 1869815922]
[1914725741 1869832549 1870209134]]
zeros()将数组初始化为0,ones将数组初始化为1,full()将数组初始化为指定的值
zeros_like(),ones_like(),full_like()等函数创建与参数数组形状和类型相同的数组
字符串每个字符占一个字节,如果从字符串s创建一个8位整数数组,则数组元素是ASCII编码
[ 97  98  99 100 101 102 103 104]
如果从字符串s床架16位的整数数组,那么相邻两个字节就表示一个整数
[25185 25699 26213 26727]
# 利用fromfunction创建数组 第一个参数是计算每个数组元素的函数,第二个是构造的数组的形状
[ 1.  2.  3.  4.  1.  2.  3.  4.  1.  2.]
# 利用函数创建乘法表数组
[[  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.]]


1.1.4存取数组

a = np.arange(10)
print(a)
print('包括a[3]不包括a[5]')
print(a[3:5])
print('从数组最后往前数')
print(a[:-1])
print('隔一个元素取一个元素')
print(a[1:-1:2])
print('步长为负数的时候,开始下标必须大于结束下标')
print('下标用来修改元素的值,通过切片访问的数组是原始数组的一个视图')
a[2:4] = 100, 101
print(a)
x = np.arange(10, 1, -1)
print(x)
a = x[[3, 3, 1, 8]]
b = x[[3, 3, -3, 8]]
print(a, b)
print('使用整数列表获取的数组元素不和原始数组共享数据')
b[2] = 100
print(x, b)
x[[3, 5, 1]] = -1, -2, -3
print(x)
x = np.arange(10, 1, -1)
print('下标是多维数组时得到也是多维数组')
print(x)
print(x[np.array([[3, 3, 1, 8], [3, 3, -3, 8]])])
print('使用布尔数组b作为下标存取数组x中的元素时,获得数组x中与数组b中True对应的元素')
print('布尔数组作为下标获得的数组不和原始数组共享内存')
x = np.arange(5, 0, -1)
print(x)
print(x[np.array([True, False, True, False, False])])
print('使用布尔列表取数据')
print(x[[True, False, True, False, False]])
print('布尔下标也可以用来修改元素')
x[np.array([True, False, True, True, False])] = -1, -2, -3
print(x)
print('产生一个长度为6,元素值为0-9的随机整数数组')
x = np.random.randint(0, 10, 6)
print(x)
print(x > 5)


运行结果

[0 1 2 3 4 5 6 7 8 9]
包括a[3]不包括a[5]
[3 4]
从数组最后往前数
[0 1 2 3 4 5 6 7 8]
隔一个元素取一个元素
[1 3 5 7]
步长为负数的时候,开始下标必须大于结束下标
下标用来修改元素的值,通过切片访问的数组是原始数组的一个视图
[  0   1 100 101   4   5   6   7   8   9]
[10  9  8  7  6  5  4  3  2]
[7 7 9 2] [7 7 4 2]
使用整数列表获取的数组元素不和原始数组共享数据
[10  9  8  7  6  5  4  3  2] [  7   7 100   2]
[10 -3  8 -1  6 -2  4  3  2]
下标是多维数组时得到也是多维数组
[10  9  8  7  6  5  4  3  2]
[[7 7 9 2]
[7 7 4 2]]
使用布尔数组b作为下标存取数组x中的元素时,获得数组x中与数组b中True对应的元素
布尔数组作为下标获得的数组不和原始数组共享内存
[5 4 3 2 1]
[5 3]
使用布尔列表取数据
[5 3]
布尔下标也可以用来修改元素
[-1  4 -2 -3  1]
产生一个长度为6,元素值为0-9的随机整数数组
[2 7 0 4 1 8]
[False  True False False False  True]


1.1.5多维数组

print('产生一个多维数组')
a = np.arange(0, 60, 10).reshape(-1, 1) + np.arange(0, 6)
print(a)
print('多维数组各种分片')
print(a[0, 3:5])
print(a[4:, 4:])
print(a[:, 2])
print(a[2::2, ::2])
print('b是a的视图他们共享数据')
b = a[0, 3:5]
print(b)
print('生成切片对象时需要使用slice创建')
# print(a[::2,2:][::2,2:])
# a[idx]#相当于a[::2,2:],a[idx][idx]相当于a[::2,2:][::2,2:]
idx = slice(None, None, 2), slice(2, None)
print(a[idx])
print('利用np.s_创建切片对象')
s = np.s_[::2, :]
print(s)
print(a[(0, 1, 2, 3), (1, 2, 3, 4)])
print('选取第三行开始0,2,5列元素')
print(a[3:, [0, 2, 5]])
print('生成一个bool数组')
mask = np.array([1, 0, 1, 0, 0, 1], dtype=np.bool)
print(mask)
mask1 = np.array([1, 0, 1, 0, 0, 1])
mask2 = [True, False, True, False, False, True]
print('取出(1,2)(0,2)(1,2)(0,2)(0,2)(1,2)')
print(a[mask1, 2])
print('取出(0,2)(2,2)(4,2)')
print(a[mask2, 2])
print('所有的轴使用证书数组作为下标的时候,得到的数组与下标数组的形状相同')
x = np.array([[0, 1], [2, 3]])
y = np.array([[-1, -2], [-3, -4]])
print(a[x, y])
print('下面这个例子与上面这个例子效果相同')
print(a[(0, 1, 2, 3), (-1, -2, -3, -4)].reshape(2, 2))
print('没有指定第一轴的下标时使用:作为下标得到一个三维数组')
print(a[x])
print('利用整数数组快速替换元素')
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[image])


运行结果

产生一个多维数组
[[ 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]]
多维数组各种分片
[3 4]
[[44 45]
[54 55]]
[ 2 12 22 32 42 52]
[[20 22 24]
[40 42 44]]
b是a的视图他们共享数据
[3 4]
生成切片对象时需要使用slice创建
[[ 2  3  4  5]
[22 23 24 25]
[42 43 44 45]]
利用np.s_创建切片对象
(slice(None, None, 2), slice(None, None, None))
[ 1 12 23 34]
选取第三行开始0,2,5列元素
[[30 32 35]
[40 42 45]
[50 52 55]]
生成一个bool数组
[ True False  True False False  True]
取出(1,2)(0,2)(1,2)(0,2)(0,2)(1,2)
[12  2 12  2  2 12]
取出(0,2)(2,2)(4,2)
[ 2 22 52]
所有的轴使用证书数组作为下标的时候,得到的数组与下标数组的形状相同
[[ 5 14]
[23 32]]
下面这个例子与上面这个例子效果相同
[[ 5 14]
[23 32]]
没有指定第一轴的下标时使用:作为下标得到一个三维数组
[[[ 0  1  2  3  4  5]
[10 11 12 13 14 15]]

[[20 21 22 23 24 25]
[30 31 32 33 34 35]]]
利用整数数组快速替换元素
[[[  0   0   0]
[255   0   0]
[  0 255   0]
[  0   0   0]]

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


1.1.6结构数组

# 结构数组
print('S30长度为30个字节的字符串类型,i:np.int32 32位整形,f np.float32,align用来实现结构数组的内存对齐')
persontype = np.dtype({
'names': ['name', 'age', 'weight'],
'formats': ['S30', 'i4', 'f4']
}, align=True)
a = np.array([('zhang', 32, 75.5), ('wang', 24, 65.2)], dtype=persontype)
print(a)
print(a[0]['name'])
print('得到age视图,通过修改b会影响a')
b = a['age']
b[0] = 40
print(a)
# 将数组a以二进制形式转换成字符串或写入文件
a.tofile('test.bin')


运行结果

S30长度为30个字节的字符串类型,i:np.int32 32位整形,f np.float32,align用来实现结构数组的内存对齐
[(b'zhang', 32,  75.5       ) (b'wang', 24,  65.19999695)]
b'zhang'
得到age视图,通过修改b会影响a
[(b'zhang', 40,  75.5       ) (b'wang', 24,  65.19999695)]


1.1.7 ndarray数据结构

a=np.array([[0,1,2],[3,4,5],[6,7,8]])


如下这张图显示了ndarray的数据结构,



这个结构引用了两个对象,用于保存数据的存储区域和用于描述元素类型的dtype对象,数据存储区域保存着数组中所有元素的二进制数据,dtype知道如何将元素的二进制数据转换为可用的值

strides:保存着每个轴相邻两个元素的地址差 比如a[1,0]比a[0,0]的地址大12,正好是三个单精度浮点数的总字节数

如果strides属性中的数值正好和对应轴所占据的字节数相同,那么数据在内存中连续的,通过下标得到的新数组是原始数组的视图

a = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
print(a.strides)
b = a[::2, ::2]
print(b)
print(b.strides)
print('修改为Fortran格式存储数据')
c = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.float32, order='F')
print(c.strides)
# 当使用整数和切片的时候,所得的数据在数据存储区域中是等间隔分布的,因为只需要修改dim count
# dimensions和stride等属性以及指向数据存储的指针data就能实现整数和切片下标,所以新数组和原始数组能够共享数据存储区域
# 使用整数序列,整数数组和布尔数组时不能保证所得的数据在数据存储区域中是等间隔的,所以无法和原始数组共享数据只能对数据进行复制
print('flags属性描述了数据存储区域的一些属性\n', a.flags)
b = a.T
print('数组转置\n', b.flags)
print('通过视图base属性获得保存数据的原始数组')
print(id(b.base))
print(id(a))
print('使用不同的数值类型查看同一段内存的二进制数据')
b = a.view(np.uint32)
c = a.view(np.uint8)
print(b)
print(c)
print('a,b,c共享内存当a[0,0]修改时,b[0,0]和c[0,:4]都会发生改变')
a[0, 0] = 3.14
print(b)
print(c)
from numpy.lib.stride_tricks import as_strided
print('设置shape和strides属性,实现切片实现不了的功能,shape和strides在错误设置的情况下会造成内存越界')
a = np.arange(6)
b = as_strided(a, shape=(4, 3), strides=(4, 4))
print(a)
print(b)


运行结果

(12, 4)
[[0 2]
[6 8]]
(24, 8)
修改为Fortran格式存储数据
(4, 12)
flags属性描述了数据存储区域的一些属性
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
数组转置
C_CONTIGUOUS : False
F_CONTIGUOUS : True
OWNDATA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
通过视图base属性获得保存数据的原始数组
5407968
5407968
使用不同的数值类型查看同一段内存的二进制数据
[[0 1 2]
[3 4 5]
[6 7 8]]
[[0 0 0 0 1 0 0 0 2 0 0 0]
[3 0 0 0 4 0 0 0 5 0 0 0]
[6 0 0 0 7 0 0 0 8 0 0 0]]
a,b,c共享内存当a[0,0]修改时,b[0,0]和c[0,:4]都会发生改变
[[3 1 2]
[3 4 5]
[6 7 8]]
[[3 0 0 0 1 0 0 0 2 0 0 0]
[3 0 0 0 4 0 0 0 5 0 0 0]
[6 0 0 0 7 0 0 0 8 0 0 0]]
设置shape和strides属性,实现切片实现不了的功能
int32
[0 1 2 3 4 5]
[[0 1 2]
[1 2 3]
[2 3 4]
[3 4 5]]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: