一、哪些函数会用到order参数?
numpy.copy
numpy.reshape
numpy.ravel
numpy.flatten
二、C F A K之间的区别是什么?
C是最后一个索引变化最快。
F是第一个索引变化最快。
A是C或F中的一种,也就说也与索引相关。
K是唯一不与索引相关,只与数据缓存顺序相关的ordering,具体来说对于数组[3,1,2],因为内部对按大小顺序进行缓存,所以先取小的数再取大的数。
# 1、生成形状为(2,2,3)的ndarray数据
a = np.arange(12).reshape(2,3,2).swapaxes(1,2)
print(a)
# 输出为▼▼▼▼
# [[[ 0 2 4]
# [ 1 3 5]]
# [[ 6 8 10]
# [ 7 9 11]]]
# 2、order='C',按照a[0,0,0]-->a[0,0,1]-->a[0,0,2]-->a[0,1,0]...的顺序索引
print(a.ravel(order='C'))
# 输出为[ 0, 2, 4, 1, 3, 5, 6, 8, 10, 7, 9, 11]
# 3、order='F',按照a[0,0,0]-->a[1,0,0]-->a[0,1,0]-->a[1,1,0]...的顺序索引
print(a.ravel(order='F'))
# 输出为[ 0, 6, 1, 7, 2, 8, 3, 9, 4, 10, 5, 11]
# 4、order='A',按照C或F中的一种顺序进行,python中以C顺序进行
print(a.ravel(order='A'))
# 输出为[ 0, 2, 4, 1, 3, 5, 6, 8, 10, 7, 9, 11]
# 5、order='K',按照数据在内存中的缓存顺序进行,一般来说按数值大小顺序进行缓存
print(a.ravel(order='K'))
# 输出为[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
三、对order=’K’的探究
刚刚有一个可爱的小伙伴在评论区质疑我对K的描述,然后我想ta质疑的是啊!我复现了他的代码,发现确实不一定按1,2,3,4,5的顺序去铺排。
x = np.array([[[ 1 , 0],
[ 3 , 2],
[ 5 , 4]],
[[ 7 , 6],
[ 9 , 8],
[11, 10]],
[[12 ,13],
[14 ,15],
[16 ,17]]]).reshape(3,3,2).swapaxes(1,2)
z=np.ravel(x, order='K')
output:[ 1 0 3 2 5 4 7 6 9 8 11 10 12 13 14 15 16 17]
下面开始我的实验吧!朋友有难我帮忙。
3.1 如果数据是4维的,那么是按照[0,0,0,0]–>[0,0,0,1]–>[0,1,0,0]–>[0,1,0,1]–>[0,0,1,0]–>[0,0,1,1]–>[0,1,1,0]–>[0,1,1,1]…的顺序索引,也即先遍历倒数第1维、再遍历倒数第3维、再遍历倒数第2维、最后遍历倒数第4维。
print(np.arange(24).reshape(2,3,2,2).swapaxes(1,2))
print(np.arange(24).reshape(2,3,2,2).swapaxes(1,2).ravel(order='k'))
# [[[[[ 0 1]
# [ 2 3]]
# [[ 8 9]
# [10 11]]
# [[16 17]
# [18 19]]]
# [[[ 4 5]
# [ 6 7]]
# [[12 13]
# [14 15]]
# [[20 21]
# [22 23]]]]
# [[[[24 25]
# [26 27]]
# [[32 33]
# [34 35]]
# [[40 41]
# [42 43]]]
# [[[28 29]
# [30 31]]
# [[36 37]
# [38 39]]
# [[44 45]
# [46 47]]]]]
# [ 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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47]
3.2 如果数据是5维的,那么是按照[0,0,0,0,0]–>[0,0,0,0,1]–>[0,0,0,0,0]–>[0,1,0,1]–>[0,0,1,0]–>[0,0,1,1]–>[0,1,1,0]–>[0,1,1,1]…的顺序索引,也即先遍历倒数第1维、再遍历倒数第2维、再遍历倒数第4维、再遍历倒数第3维、最后遍历倒数第5维。
对照3.1得出来的结论,瞬间不好了!程序本身绝对是有一套稳定的算法,至少在这两个实验中我觉得简直就是薛定谔的猫——真是乱七八糟!
print(np.arange(48).reshape(2,3,2,2,2).swapaxes(1,2))
print(np.arange(48).reshape(2,3,2,2,2).swapaxes(1,2).ravel(order='k'))
# [[[[[ 0 1]
# [ 2 3]]
# [[ 8 9]
# [10 11]]
# [[16 17]
# [18 19]]]
# [[[ 4 5]
# [ 6 7]]
# [[12 13]
# [14 15]]
# [[20 21]
# [22 23]]]]
# [[[[24 25]
# [26 27]]
# [[32 33]
# [34 35]]
# [[40 41]
# [42 43]]]
# [[[28 29]
# [30 31]]
# [[36 37]
# [38 39]]
# [[44 45]
# [46 47]]]]]
# [ 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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47]
转换一下思路,官网已经说了,K就是按内存顺序来索引的;那么这个内存顺序是在创建array的时候发生,还是根据已经缓存在python的buffer中的常用数字的顺序来确定呢?
下面看实验3.3,得出来的结论是:内存顺序是在创建array的时候发生,因为两个数组的元素0的地址不一样;说明在分别创建这两个数组的时候,其中的元素是开拓了新的内存区,而非直接引用buffer中的常用数字的地址。
a = np.arange(24).reshape(2,3,2,2).swapaxes(1,2)
b = np.arange(48).reshape(2,3,2,2,2).swapaxes(1,2)
a[0,0,0,0] is b[0,0,0,0,0] # False
接着看实验3.4,得出来的结论是:一个数组如果是通过arange得出来的,那么内存顺序和数字大小相关,从前到后数值逐渐递增;而如果一个数组是逐元素均用表达式给出,那么内存顺序和order=’c’的一样;因为存入内存的顺序是’c’(计算机不可能说一下子吃一个大块头吧?肯定是逐元素存入内存的,顺序就默认是’c’),所以用a.ravel(order=’k’)平铺出来的顺序也跟内存顺序一样是’c’。
实验3.4的子实验(1)如下:
a = np.arange(96).reshape(2,3,2,2,2,2).swapaxes(1,2)
print(a)
# array([[[[[[ 0, 1],
# [ 2, 3]],
# [[ 4, 5],
# [ 6, 7]]],
# [[[16, 17],
# [18, 19]],
# [[20, 21],
# [22, 23]]],
# [[[32, 33],
# [34, 35]],
# [[36, 37],
# [38, 39]]]],
# [[[[ 8, 9],
# [10, 11]],
# [[12, 13],
# [14, 15]]],
# [[[24, 25],
# [26, 27]],
# [[28, 29],
# [30, 31]]],
# [[[40, 41],
# [42, 43]],
# [[44, 45],
# [46, 47]]]]],
# [[[[[48, 49],
# [50, 51]],
# [[52, 53],
# [54, 55]]],
# [[[64, 65],
# [66, 67]],
# [[68, 69],
# [70, 71]]],
# [[[80, 81],
# [82, 83]],
# [[84, 85],
# [86, 87]]]],
# [[[[56, 57],
# [58, 59]],
# [[60, 61],
# [62, 63]]],
# [[[72, 73],
# [74, 75]],
# [[76, 77],
# [78, 79]]],
# [[[88, 89],
# [90, 91]],
# [[92, 93],
# [94, 95]]]]]])
再平铺开:
a.ravel(order='k')
# 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, 32, 33,
# 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
# 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
# 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
# 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95])
然后再利用子实验(1)得到的array进行子实验(2):最终平铺出来的结果顺序从前到后并不完全是按数值大小递增,换句话说这个顺序和order=’c’的一样。
a = np.array([[[[[[ 0, 1],
[ 2, 3]],
[[ 4, 5],
[ 6, 7]]],
[[[16, 17],
[18, 19]],
[[20, 21],
[22, 23]]],
[[[32, 33],
[34, 35]],
[[36, 37],
[38, 39]]]],
[[[[ 8, 9],
[10, 11]],
[[12, 13],
[14, 15]]],
[[[24, 25],
[26, 27]],
[[28, 29],
[30, 31]]],
[[[40, 41],
[42, 43]],
[[44, 45],
[46, 47]]]]],
[[[[[48, 49],
[50, 51]],
[[52, 53],
[54, 55]]],
[[[64, 65],
[66, 67]],
[[68, 69],
[70, 71]]],
[[[80, 81],
[82, 83]],
[[84, 85],
[86, 87]]]],
[[[[56, 57],
[58, 59]],
[[60, 61],
[62, 63]]],
[[[72, 73],
[74, 75]],
[[76, 77],
[78, 79]]],
[[[88, 89],
[90, 91]],
[[92, 93],
[94, 95]]]]]])
print(a.ravel(order='k'))
# array([ 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23, 32,
# 33, 34, 35, 36, 37, 38, 39, 8, 9, 10, 11, 12, 13, 14, 15, 24, 25,
# 26, 27, 28, 29, 30, 31, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
# 51, 52, 53, 54, 55, 64, 65, 66, 67, 68, 69, 70, 71, 80, 81, 82, 83,
# 84, 85, 86, 87, 56, 57, 58, 59, 60, 61, 62, 63, 72, 73, 74, 75, 76,
# 77, 78, 79, 88, 89, 90, 91, 92, 93, 94, 95])