python/numpy基础知识,order=C F A K,各个数据索引顺序的区别?

一、哪些函数会用到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])
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值