Numpy

Numpy

  • 功能强大的N维数组对象。
  • 精密广播功能函数。
  • 集成 C/C+和Fortran 代码的工具。
  • 强大的线性代数、傅立叶变换和随机数功能。
  • NumPy提供了一个N维数组类型,即ndarray, 它描述了相同类型的“项目”集合。可以使用例如N个整数来索引项目。
  • 所有ndarray都是同质的:每个项目占用相同大小的内存块, 并且所有块都以完全相同的方式解释。
  • 如何解释数组中的每个项目由单独的数据类型对象指定, 其中一个对象与每个数组相关联。除了基本类型(整数,浮点数 等 )之外, 数据类型对象还可以表示数据结构。

导入Numpy模块

1
2
3
import numpy as np
# 或
from numpy import *

初识数组(Arrays)

  • numpy数组是一个值网格,所有类型都相同,并由非负整数元组索引。
  • 维数是数组的排名; 数组的形状是一个整数元组,给出了每个维度的数组大小。
1
2
3
4
5
6
# 用一个一维列表传入
ar1 = np.array([1, 3, 5, 7])
ar1

# 数组转成列表
ar1.tolist()
1
2
array([1, 3, 5, 7])
[1, 3, 5, 7]
1
2
3
# 查看类型

type(ar1)
1
numpy.ndarray
1
2
3
# 查看维度  返回的格式(n,m),其中n为行数,m为列数

ar1.shape
1
(4,)
1
2
3
# 查看数组的维度数

ar1.ndim
1
1
1
ar1.size
1
4
1
2
3
# 索引

ar1[0],ar1[2]
1
(1, 5)
1
2
3
4
# 修改值

ar1[2]=9
ar1
1
array([1, 3, 9, 7])

创建数组

创建一维数组

  1. 用np.array(list) 传入列表
  2. 用np.arange() 传入数值范围
1
2
3
4
5
# 直接用列表传入
np.array([x for x in range(1,20,4)])

lst1=['a',"b","c"]
np.array(lst1)
1
2
array([ 1,  5,  9, 13, 17])
array(['a', 'b', 'c'], dtype='<U1')
1
2
3
# 用 arange() 传入一个范围,arange的用法和range一样

np.arange(1, 10, 3)
1
array([1, 4, 7])

创建二维数组

  1. 用np.array([list1,list2]) 传入一个二维列表,且长度一致
  2. 用np.arange() .reshape(()) 传入数值范围,用reshpe函数重构,reshape函数内是一个元组格式,元素相乘的结果要等于范围内的个数
  3. reshape()函数重构时,必须保证各维度数值相乘的结果等于数组中元素的个数
1
2
3
4
# 直接传入一个二维列表

c = np.array([[1, 2, 3], [4, 5, 6]])
type(c), c.shape, c
1
2
3
4
(numpy.ndarray,
(2, 3),
array([[1, 2, 3],
[4, 5, 6]]))
1
2
3
4
# 用arange传入数据范围后用reshape()重构,指定成?行?列

d = np.arange(1, 7).reshape((2, 3))
d
1
2
array([[1, 2, 3],
[4, 5, 6]])

创建多维数组

  1. 一般用reshape函数比较简单,因为中括号的嵌套比较复杂。
  2. shape属性可以查看数组的维度。如:e.shape
  3. 多维数组如何看待?
    1. 维度显示是一个元组形式
    2. 末尾的两位可以简单看成是行数和列数
    3. 再往前则可以理解成小区块,大区快
    4. 如果shape的结果是(2,3,4) 表示有2个区块,每个区块中有3行4列的数据
    5. 如果结果是(2,2,2,3) 表示有2个大区块,每个大区块中有2个小区块,每个小区块中有2行3列数据
1
2
3
4
5
6
7
8
# 创建一个3维数组
# 数组维度是用元组的方式表示的。元组内最后两个数分别表示行和列。再往前就是表示块
# 下面的表示就是:2块,3行4列的数组

e = np.arange(24).reshape(2, 3, 4)

e.shape
e
1
2
3
4
5
6
7
8
9
(2, 3, 4)

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]]])
1
2
3
4
5
6
# 多维数组
# 从维度元组中可以得知:最小单位是2行3列的数组,有2个大块,每个大块中包含2个小块,每个小块中有1个2行3列的数组。

f = np.arange(24).reshape(2, 2, 2, 3)

f.shape, f
1
2
3
4
5
6
7
8
9
10
11
12
((2, 2, 2, 3),
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]]]]))

数组的转换

  • reshape()函数和flatten()函数
  1. 有重构函数reshpe()可以改变数组的维度,只要保证元组元素乘积等于数组数据的个数
  2. 多维数组就可以转换成1维数组
    1. reshape((num1,)) num1=数据个数
    2. flatten()展开数组变成一维数组
1
2
a = np.arange(12).reshape(3, 4)
a
1
2
3
array([[ 0,  1,  2,  3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
1
2
3
4
5
6
7
# 转换成一维数组

a.reshape(12,) # 参数内只写一个数,且数字为数组的大小

a.flatten() # flatten是numpy.ndarray.flatten的一个函数,即返回一个一维数组,默认按行降维.参数"A"省略

a.flatten("F") # 加入参数“F"变为按列降维
1
2
3
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
array([ 0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11])
1
2
3
4
5
# 变成其他维度(形状),用reshape()并指定行列数

a.reshape(2,6)

a.reshape(4,-1) # 参数中的”-1“ 代表自动计算。(据已知条件自动计算)
1
2
3
4
5
6
7
array([[ 0,  1,  2,  3,  4,  5],
[ 6, 7, 8, 9, 10, 11]])

array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])

创建等值的矩阵

  1. np.zeros代表全是0
  2. np.ones代表全是1
1
np.zeros(5, dtype=np.int32)  
1
array([0, 0, 0, 0, 0])
1
np.zeros((2, 5), dtype=np.int32)  
1
2
array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]])
1
np.ones(5, dtype=np.float16)
1
array([1., 1., 1., 1., 1.], dtype=float16)
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
import pandas as pd
import numpy as np

# 创建一维数组
a = np.array([1, 2, 3, 4]) # 数组a: [1 2 3 4]
b = np.arange(1, 5) # 数组b: [1 2 3 4]
type(a) # a类型是:<class 'numpy.ndarray'>

# 创建二维数组
c = np.array([[1, 2, 3], [4, 5, 6]])
d = np.arange(1, 7).reshape((2, 3))

# 创建三维数组或更高维度的数组
e = np.arange(24).reshape(2, 3, 4)
f = np.arange(24).reshape(2, 2, 2, 3)
f.shape # 返回值为: (2,2,2,3)
print('''
数组e:{}

数组f:{}'''.format(e, f))

# 数组的维度转换
g = a.reshape(2, 2) # 转成2行12列的二维数组
h = g.reshape(-1, 2) # reshape函数中元组中出现“-1”,则表示根据已知条件自动计算出
i = g.reshape(4,) # 传递给reshape函数的元组中只有1个数表示转化成1维数组,注意有逗号,逗号后为空
j = g.flatten() # 与上面的结果相同. array([1, 2, 3, 4])

# 创建特殊数组
np.zeros(5, dtype=np.int32) # array([0, 0, 0, 0, 0])
np.ones(5, dtype=np.float16) # array([1., 1., 1., 1., 1.], dtype=float16)
np.zeros((2, 5), dtype=np.int32) # 生成2行5列的二维数组,值都为0,数据类型为int32

# 查看数组属性
f.ndim # 返回值:4 表示4维数组
f.shape # 返回值: (2, 2, 2, 3)
f.size # 返回值: 24
x = c.reshape(c.size,) # 数组x: array([1, 2, 3, 4, 5, 6])
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
numpy.ndarray
(2, 2, 2, 3)
数组e:[[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]

[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]]

数组f:[[[[ 0 1 2]
[ 3 4 5]]

[[ 6 7 8]
[ 9 10 11]]]

[[[12 13 14]
[15 16 17]]

[[18 19 20]
[21 22 23]]]]
array([0, 0, 0, 0, 0])

array([1., 1., 1., 1., 1.], dtype=float16)

array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]])

4

(2, 2, 2, 3)
24

创建等分数组

1
2
3
# 将1-5分段,有两个端点

np.linspace(1, 5, 2, dtype=np.float32)
1
array([1., 5.], dtype=float32)
1
2
# 将1-5分段,有3个端点
np.linspace(1, 5, 3)
1
array([1., 3., 5.])
1
2
# 将1-5分段,有36个端点
np.linspace(1, 5, 6)
1
array([1. , 1.8, 2.6, 3.4, 4.2, 5. ])

高斯分布(正态分布)

1
2
np.random.randn(2,5)  # 生成对应形状(shape)的高斯分布
np.random.normal(3, 1, 12) # 生成均值为loc,标准差为scale,形状(shape)为size的高斯分布
1
2
3
4
5
6
array([[-0.62751446,  2.29446202, -0.53109692, -0.07013024,  0.28581247],
[-1.02490725, -0.18025872, -1.00725205, -0.0991576 , -0.68541257]])

array([3.04006092, 2.57668325, 4.54845812, 4.48776295, 3.01108357,
5.68784587, 2.80187253, 3.85604824, 4.36074347, 3.00090056,
1.55342793, 4.60112417])

均匀分布

1
2
np.random.rand(2, 3)  # 生成对应形状(shape)的均匀分布
np.random.uniform(11, 19, 6) # 生成一个从[low, high)中随机采样的,样本数量为size的均匀分布
1
2
3
4
5
array([[0.24771356, 0.63015361, 0.46175306],
[0.39705638, 0.13455475, 0.01309569]])

array([18.47429041, 17.74433573, 15.09945145, 18.10811743, 13.92652713,
18.28708122])

数组索引

  • Numpy提供了几种索引数组的方法。

切片(Slicing)

  • 与Python列表类似,可以对numpy数组进行切片。由于数组可能是多维的,因此必须为数组的每个维指定一个切片:
1
2
3
4
5
6
7
8
9
# 切片
a = np.arange(12).reshape(3, 4)

a[:, 1:3] # 所有行的0列
a[:, 0: 2] # 所有行的0,2列
a[1:2, :] # 1行的所有列

b = a[:2, 1:3]
b
1
2
3
4
5
6
7
8
9
10
11
12
array([[ 1,  2],
[ 5, 6],
[ 9, 10]])

array([[0, 1],
[4, 5],
[8, 9]])

array([[4, 5, 6, 7]])

array([[1, 2],
[5, 6]])

整数与切片混合索引

  • 这样做会产生比原始数组更低级别的数组。
1
2
3
4
a = np.arange(12).reshape(2, 2, 3)
a

a[:,0,:]# 全部块的0行全部列
1
2
3
4
5
6
7
8
array([[[ 0,  1,  2],
[ 3, 4, 5]],

[[ 6, 7, 8],
[ 9, 10, 11]]])

array([[0, 1, 2],
[6, 7, 8]])
1
2
3
4
5
6
7
8
# 整数索引与切片索引混合使用

a = np.arange(12).reshape(4, 3)

a
a[1,0:2]
a[1,[0,2]]
a[[1,2],[0,2]]
1
2
3
4
5
6
7
8
9
10
array([[ 0,  1,  2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])

array([3, 4])

array([3, 5])

array([3, 8])

整数数组索引

  • 使用切片索引到numpy数组时,生成的数组视图将始终是原始数组的子数组。
  • 相反,整数数组索引允许你使用另一个数组中的数据构造任意数组
1
2
3
4
5
6
7
8
9
10
11
12
13
# 整数组索引

a = np.arange(12).reshape(4, 3)
a[[0, 1, 2], [0, 1, 0]]

# 整数组索引的技巧
b = np.array([0, 2, 0, 1])
a[np.arange(4), b]

# 将索引的每个位置的数值加上10

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

array([ 0, 5, 6, 10])

array([[10, 1, 2],
[ 3, 4, 15],
[16, 7, 8],
[ 9, 20, 11]])

布尔组索引

1
2
3
4
5
6
7
a = np.arange(12).reshape(4, 3)
print(a)

b = a > 5
a[b]

a[a < 4]
1
2
3
4
5
6
7
8
[[ 0  1  2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]

array([ 6, 7, 8, 9, 10, 11])

array([0, 1, 2, 3])

Numpy的数据类型

  1. 用dtype属性查看数组的数据类型 如:a.dtype
  2. 用astype()函数指定或改变数组的数据类型
  3. 数据类型
    字符 对应类型
    b 布尔型
    i (有符号) 整型
    u 无符号整型 integer
    f 浮点型
    c 复数浮点型
    m timedelta(时间间隔)
    M datetime(日期时间)
    O (Python) 对象
    S, a (byte-)字符串
    U Unicode
    V 原始数据 (void)
  4. 数值类型
    Numpy 的类型 C 的类型 描述
    np.int8 int8_t 字节(-128到127)
    np.int16 int16_t 整数(-32768至32767)
    np.int32 int32_t 整数(-2147483648至2147483647)
    np.int64 int64_t 整数(-9223372036854775808至9223372036854775807)
    np.uint8 uint8_t 无符号整数(0到255)
    np.uint16 uint16_t 无符号整数(0到65535)
    np.uint32 uint32_t 无符号整数(0到4294967295)
    np.uint64 uint64_t 无符号整数(0到18446744073709551615)
    np.intp intptr_t 用于索引的整数,通常与索引相同 ssize_t
    np.uintp uintptr_t 整数大到足以容纳指针
    np.float32 float
    np.float64 / np.float_ double 请注意,这与内置python float的精度相匹配。
    np.complex64 float complex 复数,由两个32位浮点数(实数和虚数组件)表示
    np.complex128 / np.complex_ double complex 请注意,这与内置python 复合体的精度相匹配。

数组运算

  1. 数组的广播机制,对数组内的每个数据分别进行运算

  2. 维度方向运算

    1. axis=0,对各列
    2. axis=1,对各行
  3. 两个维度不同的数组不能算数运算

  4. 两个行列数都不同的数组不能运算

  5. 两个维度相同,行数或列数有其一相同,不同的为1的数组可以运算

    1. 如a:(3,4) b:(3,4)可以运算
    2. 如a:(3,4) b:(4,3)不可以运算
    3. 如a:(3,4) b:(1,4) 行数为1,列数相同,可以运算
    4. 如a:(3,4) b:(3,1) 行数相同,列数为1,可以运算

运算函数

1
2
3
4
# 对整个进行某种运算,如求和,求最大,最小,平均等等
a = np.arange(1, 13).reshape(3, 4)

a.sum(), a.max(), a.min(), a.mean()
1
(78, 12, 1, 6.5)
1
2
3
4
5
6
7
# 累加

np.cumsum(a)

# 累差

np.diff(a)
1
2
3
4
5
array([ 1,  3,  6, 10, 15, 21, 28, 36, 45, 55, 66, 78])

array([[1, 1, 1],
[1, 1, 1],
[1, 1, 1]])
1
2
3
# 中间值

np.median(a)
1
6.5
1
2
3
4
5
# 对每个数据求sin值
np.sin(a)

# 对每个数平方
a**2
1
2
3
4
5
6
7
array([[ 0.84147098,  0.90929743,  0.14112001, -0.7568025 ],
[-0.95892427, -0.2794155 , 0.6569866 , 0.98935825],
[ 0.41211849, -0.54402111, -0.99999021, -0.53657292]])

array([[ 1, 4, 9, 16],
[ 25, 36, 49, 64],
[ 81, 100, 121, 144]])

按维度方向计算

  • a.sum(axis=1) 计算各列
  • a.max(axis=0) 计算各行
1
2
3
4
5
a = np.arange(1, 13).reshape(3, 4)
print(a)

a.sum(axis=1)
a.max(axis=0)
1
2
3
4
5
6
7
[[ 1  2  3  4]
[ 5 6 7 8]
[ 9 10 11 12]]

array([10, 26, 42])

array([ 9, 10, 11, 12])

数组与数组进行运算

1
2
3
4
# 同维度的数组各自对应位置进行运算
a = np.arange(1, 13).reshape(3, 4)
b = np.arange(100, 112).reshape((3, 4))
a+b
1
2
3
array([[101, 103, 105, 107],
[109, 111, 113, 115],
[117, 119, 121, 123]])
1
2
3
4
5
# 与1行同列数的数组运算

a = np.arange(1, 13).reshape(3, 4)
c = np.arange(100, 104).reshape(1, 4)
a+c
1
2
3
array([[101, 103, 105, 107],
[105, 107, 109, 111],
[109, 111, 113, 115]])
1
2
3
4
5
# 数组与数组进行运算. 与1列同行数的数组运算
a = np.arange(1, 13).reshape(3, 4)
d = np.arange(100, 103).reshape(3, 1)

a+d
1
2
3
array([[101, 102, 103, 104],
[106, 107, 108, 109],
[111, 112, 113, 114]])

数组排序和转置

  • 排序
    1. axis=0 按列排序
    2. axis=1 按行排序
  • 数组行列转置
  • 简便遍历多维数组 arr.flat表示数组的单元

默认按行排序

  • axis=1
1
2
3
ar1 = np.array([[8, 12, 6], [13, 9, 27], [1, 5, 3]])

np.sort(ar1)
1
2
3
array([[ 6,  8, 12],
[ 9, 13, 27],
[ 1, 3, 5]])

按列排序

1
2
3
ar1 = np.array([[8, 12, 6], [13, 9, 27], [1, 5, 3]])

np.sort(ar1, axis=0)
1
2
3
array([[ 1,  5,  3],
[ 8, 9, 6],
[13, 12, 27]])

全部排序

  • 行和列都排序
1
np.sort(np.sort(ar1, axis=0), axis=1)
1
2
3
array([[ 1,  3,  5],
[ 6, 8, 9],
[12, 13, 27]])

数组的转置

1
2
3
4
5
# 创建一个3行4列的数组
arr5 = np.arange(12).reshape(3, 4)

# 行列转置,变成4行3列
arr5.T
1
2
3
4
array([[ 0,  4,  8],
[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11]])

数组的遍历

列表解析法

1
2
3
4
5
6
7
# 因为是多维数组,有、1个for循环解析得到的依然是个二维列表
a = np.arange(12).reshape(3, 4)

[i for i in a]

# 2个for循环即可遍历2维数组的全部元素
[j for i in a for j in i]
1
2
3
[array([0, 1, 2, 3]), array([4, 5, 6, 7]), array([ 8,  9, 10, 11])]

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

For循环法

1
2
3
4
5
6
list1 = []
for i in a:
for j in i:
list1.append(j)

list1
1
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
1
2
3
4
5
6
# .flat:表示在数组单元中遍历,这样对多维数组简化了for循环
list2 = []
for i in a.flat:
list2.append(i)

list2
1
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
1
2
3
4
5
6
7
8
# np.nditer(a) 表示在数组单元中遍历,这样对多维数组简化了for循环
# 这里的i实际是:arrary(0)等,将数组转成列表 i.tolist()
list3 = []

for i in np.nditer(a):
list3.append(i.tolist())

list3
1
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

限制数组中的值

  • np.clip
  • 这个函数将将数组中的元素限制在a_min, a_max之间,大于a_max的就使得它等于 a_max,小于a_min,的就使得它等于a_min。
1
2
3
a = np.arange(1, 37, 4).reshape(3, 3)

np.clip(a, 10, 25)
1
2
3
array([[10, 10, 10],
[13, 17, 21],
[25, 25, 25]])

数组合并

np.vstack()

  • 行堆栈,一行一行的堆叠
  • 按水平方向(列顺序)堆叠数组构成一个新的数组
1
2
3
4
5
a = np.arange(15).reshape(3, 5)
b = np.array(list("ABCDEFGHIJKLMNO")).reshape(3, 5)

# 将2个2维数组按竖直方向(行)堆栈 变成6行5列的数组
np.vstack((a, b))
1
2
3
4
5
6
array([['0', '1', '2', '3', '4'],
['5', '6', '7', '8', '9'],
['10', '11', '12', '13', '14'],
['A', 'B', 'C', 'D', 'E'],
['F', 'G', 'H', 'I', 'J'],
['K', 'L', 'M', 'N', 'O']], dtype='<U11')
1
2
3
4
5
6
# 将1个1维数组按竖直方向(行)堆栈
np.vstack(a[0])


# 将1个2维数组按竖直方向(行)堆栈,结果不变还是原来的样子
np.vstack(a)
1
2
3
4
5
6
7
8
9
array([[0],
[1],
[2],
[3],
[4]])

array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])

np.hstack()

  • 列堆栈,一列一列的堆叠
  • 按竖直方向(行顺序)堆叠数组构成一个新的数组
1
2
# hstack() 可以将一个二维数组展开
np.hstack(a)
1
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])
1
2
# 将2个2维数组按水平方向(列)堆栈,相当于在数组右侧增加新的数组
np.hstack((a, b))
1
2
3
4
array([['0', '1', '2', '3', '4', 'A', 'B', 'C', 'D', 'E'],
['5', '6', '7', '8', '9', 'F', 'G', 'H', 'I', 'J'],
['10', '11', '12', '13', '14', 'K', 'L', 'M', 'N', 'O']],
dtype='<U11')

np. dstack()

  • 按深度方向堆栈,改变数组的维度.
1
2
# 将2个2维数组按深度方向堆栈,变成3块5行2列的数组
np.dstack((a, b))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
array([[['0', 'A'],
['1', 'B'],
['2', 'C'],
['3', 'D'],
['4', 'E']],

[['5', 'F'],
['6', 'G'],
['7', 'H'],
['8', 'I'],
['9', 'J']],

[['10', 'K'],
['11', 'L'],
['12', 'M'],
['13', 'N'],
['14', 'O']]], dtype='<U11')

数组的分割

  • np.split(a,3,0)

等分割1维数组

1
2
3
4
5
a = np.arange(10)  

np.split(a, 2)

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

[array([0, 1]), array([2, 3]), array([4, 5]), array([6, 7]), array([8, 9])]

等分割2维数组

  • np.split(ary, indices_or_sections, axis=0)
1
2
3
4
5
6
7
8
a = np.arange(1, 21).reshape(4, 5)

# 按行方向分割成4个一维数组,个数必须是原数组行数的整除数
np.split(a, 4, axis=0)


# 按列方向分割成5个一维数组,个数必须是原数组列数的整除数
np.split(a, 5, axis=1)
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
[array([[1, 2, 3, 4, 5]]),
array([[ 6, 7, 8, 9, 10]]),
array([[11, 12, 13, 14, 15]]),
array([[16, 17, 18, 19, 20]])]

[array([[ 1],
[ 6],
[11],
[16]]),
array([[ 2],
[ 7],
[12],
[17]]),
array([[ 3],
[ 8],
[13],
[18]]),
array([[ 4],
[ 9],
[14],
[19]]),
array([[ 5],
[10],
[15],
[20]])]