前言
上一期文章的传送门,接着说吧
这次文章应该会把索引什么的给讲完科科,看理解吧
反正我也是小白没学过哈
正文
0x05 Numpy中的索引和切片
基本的索引和普通的列表是一样的,
array_name[索引号]
多维数组的索引方法也是一样的,有C++基础的应该都知道
array_name[行索引号][列索引号]......
我们生成一个多维数组来试一下:
>>> a = np.arange(9).reshape((3,3))
>>> print(a)
[[0 1 2]
[3 4 5]
[6 7 8]]
>>> print(a[1])
[3 4 5] #这里输出了所有第1行的元素(从零开始计算)
>>> print(a[1][1])
4 #输出第一行第一个就是4
这里还有一种不同的表达形式,使用一个元组来确定索引,我们可以把行列的坐标写成一个元组的形式如[行坐标,列坐标],但是要记住这个元组的外面是方括号
>>> print(a)
[[0 1 2]
[3 4 5]
[6 7 8]]
>>> print(a[1,1])
4 #也是输出第一行第一个元素4
0x06切片
上面的元组,可以改写成切片的形式,也是可以使用的
>>> a = np.arange(9).reshape((3,3))
>>> print(a)
[[0 1 2]
[3 4 5]
[6 7 8]]
>>> print(a[:,1])
[1 4 7] #输出第一列
>>> print(a[1,:])
[3 4 5] #输出第一行
>>> print(a[1,0:2])
[3 4]#输出第一行的第0个元素到第二个(不包含第二个)
0x07迭代
这里我发现一个很好玩的现象
我们可以使用for来迭代array里面的每一行:
>>> print(a)
[[0 1 2]
[3 4 5]
[6 7 8]]
>>> for i in a:\
... print(i);\
... print('----');
...
[0 1 2]
---- #这里加分割行是为了区分每一次迭代的结果
[3 4 5]
----
[6 7 8]
----
>>>
但是我们能不能迭代每一列呢?
这里按道理来说是不可以的,但是我们可以转置列表,让列表的行变成列,列变成行,我们再去迭代不就行了?这里就要使用一下转置方法.T了,
我们可以先转置a
>>> print(a)
[[0 1 2]
[3 4 5]
[6 7 8]]
>>> print(a.T)
[[0 3 6]
[1 4 7]
[2 5 8]]
然后再迭代已经被转置的a.T,这样迭代出来的值不就是列了嘛:
>>> print(a)
[[0 1 2]
[3 4 5]
[6 7 8]]
>>> for i in a.T:\
... print(i);\
... print('----');
...
[0 3 6]
---- #这里加分割行是为了区分每一次迭代的结果
[1 4 7]
----
[2 5 8]
----
那么如果要迭代多维数组里面的每一个值呢?
难不成还像一样写C++那样写两个for然后print(a[x][y++])嘛?
没有效率!
在Python里面我们可以迭代一个列表(一位数组),但是多维数组就不行,
那么把一个多维数组转化成一个一位数组不就行了??
ndarray_name.flat
这个函数的作用是把一个数组转换成一个一维数组:
>>> print(a)
[[0 1 2]
[3 4 5]
[6 7 8]]
>>> print(a.flat) #这个返回的是一个可以迭代的对象
<numpy.flatiter object at 0x000001E712F1D3C0>
>>> print(a.flatten) #这个**什么也不是**我不知道为什么它可以输出
<built-in method flatten of numpy.ndarray object at 0x000001E7127889E0>
>>> print(a.flatten())#这个方法返回他的一位数组形式
[0 1 2 3 4 5 6 7 8]
现在我来试试看哪些方法是可以迭代的
#第一个是不能用来迭代的错误写法
>>> for i in a.flatten:\
... print(i);
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'builtin_function_or_method' object is not iterable
#下面两个写法是一样的
>>> for i in a.flat:\
... print(i);
...
0
1
2
3
4
5
6
7
8
>>> for i in a.flatten():\
... print(i);
...
0
1
2
3
4
5
6
7
8
后面两种的方法都可以迭代多维数组中的所有元素,但是这两种的原理却不一样
- 第一种.flat是生成一个可以迭代的对象进行迭代,有点像迭代器的写法
- 第二种.flatten()是先将这个多维数组转换成一个一维数组,然后再迭代这个数组
我还是更喜欢第二种吧,毕竟不想被单词嘛
array的合并与拼接
0x06 合并np.vstask((a,b))和hstack((a,b))
其实这个vstack是一个简写,原来是等于vertical stack(垂直的栈)
但是用这个vstack其实可以实现垂直和竖直的合并,
这里呢和上面的思路是一样的,把这个列的数组用T方法转置成行不就行了?
这里是垂直合并,意思是把上下两个合并在一起:
>>> import numpy as np
>>> a=np.array([1,2,3])
>>> b=np.array([4,5,6])
>>> print(np.vstack((a,b)))
[[1 2 3]
[4 5 6]]
当然我们也可以通过转置,把左右两个合并在一起:
>>> a = np.arange(3).reshape((3,1))
>>> b = np.arange(3).reshape((3,1))
>>> print(a)
[[0]
[1]
[2]]
>>> print(b)
[[0]
[1]
[2]]
>>> print(np.vstack((a.T,b.T)).T)#这里先转置a和b,合成为上下合并了形式,再把上下合并的转置成左右合并【我真他妈的聪明】
[[0 0]
[1 1]
[2 2]]
那我很好奇了,如果a和b的长度不一样怎么合并呢是不是又要广播了?
试一试:
>>> d = np.array([8,9])
>>> e = np.array([4,5,6])
>>> print(np.vstack((d,e)))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "D:\Users\15806.DESKTOP-A9HK574\Anaconda\lib\site-packages\numpy\core\shape_base.py", line 237, in vstack
return _nx.concatenate([atleast_2d(_m) for _m in tup], 0)
ValueError: all the input array dimensions except for the concatenation axis must match exactly
美滋滋你尽早打消这个念头吧
当然咯,你也可以正儿八经的使用hstack()来合并左右的数组
horizontal stack(水平线的栈)
但那多没有意思啊
其实这个hstack跟我之前想的上面的左右合并有些不一样
这个函数更像列表里面的append( )方法【确信】
所以我就叫他添加而不是合并了
下面是一个栗子:
>>> a=np.array([1,2,3])
>>> b=np.array([4,5,6])
>>> print(np.hstack((a,b)))
[1 2 3 4 5 6]
#不仅仅是合并了,真的可以当append用
>>> print(np.hstack((a,'4')))
['1' '2' '3' '4']
>>> print(np.hstack((b,7)))
[4 5 6 7]
美滋滋
那有人(dalao)就说了,为什么不把上面的a[1 2 3 4]拿去转置成
>>> print(a)
[[0]
[1]
[2]]
>>> print(b)
[[0]
[1]
[2]]
这一看就是dalao专门挑我不会的说(有水平,有水平.jpg)
这个嘛,其实是没有办法转置的,你观察一下上面的那个array,你会发现这其实是由三个列表组成的(每一个元素外面都套了一层的方括号)
或者我们可以开一下shape看一下
>>> print(b.shape)
(3,)
>>> print(b.reshape(3,1))
[[4]
[5]
[6]]
叫你嘴臭,纵向维度为0转置个p
不成你就添加一个维度进去嘛不就成了
np.newaxis
从字面意思应该也可以猜出来是什么意思,新添加一个维度
>>> print(a[:,np.newaxis])
[[1]
[2]
[3]]
>>> print(a)
[1 2 3]
那为什么不用reshape呢?
鬼知道科科
合并多个array怎么办呢?难不成for然后用stack三个三个的合并吗(v和hstack的最大合并数量为3)
np.concatenate 串联
一听就像一个很暴力的方法,但是还有更暴力的
这个方法提供了axis控制,也就是说
你可以自定义要把合并完的结果打印成二维数组或者一维数组或者更多
但是要注意一点,后面选择的维数一定一定不能超过原来array的维数
不然会挂掉:
>>> print(np.concatenate((a,b,a,b),axis=0))
[1 2 3 4 5 6 1 2 3 4 5 6]#原来a,b都是一维数组,axis就是0
>>> print(np.concatenate((a,b,a,b),axis=1))#这里如果用二维数组输出的话就是挂掉
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
numpy.core._internal.AxisError: axis 1 is out of bounds for array of dimension 1
后记
困了不想写了科科
复制和转码应该会在明后天写出来吧
有人问为什么断更了两天
【让你嘴臭,让你嘴臭小心我拔你网线】
其实这篇文章也就是把3.24写的给补完而已
参考资料:
莫烦Python
B站搜索Numpy有真相【md神奇的网站】
网友评论