Python列表的一些操作
1、列表(list)的元素删除方法
- a.pop(index):删除列表a中index处的值,返回值就是这个被pop出来的值
- del(a[index]):删除列表a中index处的值,无返回值,index可以是切片,可以实现批量删除
- a.remove(value):这是删除列表a中第一次等于value的值
可以看下面的示例:
>>> import numpy as np
>>> a = [1, 2, 3, 4, 2]
>>> a.pop(0)
1
>>> a
[2, 3, 4, 2]
>>> del(a[1:3])
>>> a
[2, 2]
>>> a.remove(2)
>>> a
[2]
2、列表(list)的拼接方法
- a.append(b):向列表a尾部追加一个新元素,可以是单个元素,也可以是一个新列表,一个新字符串,b都被视为一个整体,只占一个索引位,此函数返回None
- a.extend(b):向列表a尾部追加b列表中的元素,是逐个加入,在原有列表上增加,此函数返回None,与这种写法效果一样:a += b
- a + b:与extend()唯一不同的是,实际上生成了一个新列表,来存放这两个列表的拼接结果,本身没有变
- 可以看下面的示例:
>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> ret = a.append(b)
>>> a
[1, 2, 3, [4, 5, 6]]
>>> print(ret)
None
>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> ret = a.extend(b)
>>> a
[1, 2, 3, 4, 5, 6]
>>> print(ret)
None
>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> a += b
>>> a
[1, 2, 3, 4, 5, 6]
>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> ret = a + b
>>> ret
[1, 2, 3, 4, 5, 6]
>>> a
[1, 2, 3]
>>> b
[4, 5, 6]
numpy array的一些操作
对于用惯MATLAB的人来说,会发现numpy数组方法很杂乱,一开始上手觉得不像MATLAB里面那么简洁统一,可以去这里过渡一下
自我感觉有几点主要的不同:
MATLAB | numpy |
---|---|
用end表示最后一个索引 | 用-1表示最后一个索引 |
下标从1开始,索引左闭右闭 | 下标从0开始,索引左闭右开 |
赋值给另一个变量相当于开辟另一个内存空间 | 赋值是指向同一个内存单元,只是“引用名”不一样 |
取特定行特定列:a([2,4,5],[1,3]) | 取特定行特定列:a[[1,3,4]][:,[0,2]] |
下面介绍几个学到的函数,个人建议去看英文官方文档,里面也有一些示例
1、numpy.argsort()
本函数官网链接
numpy.argsort(a, axis=-1, kind=None, order=None)
- 输入array,返回索引 index_array (从小到大排序,返回值为int型ndarray)
- 对于2维array,axis=0表明沿着纵向排序;axis=1表明沿着横向排序
- 对于1维array,a[index_array]就是排完序后的数组,更一般的可以用这个来返回排完序后的数组:np.take_along_axis(a, index_array, axis=axis)
# 一维的
>>> x = np.array([3, 1, 2])
>>> np.argsort(x)
array([1, 2, 0])
# 两维的
>>> x = np.array([[0, 3], [2, 2]])
>>> x
array([[0, 3],
[2, 2]])
>>> ind = np.argsort(x, axis=0) # sorts along first axis (down)
>>> ind
array([[0, 1],
[1, 0]])
>>> np.take_along_axis(x, ind, axis=0) # same as np.sort(x, axis=0)
array([[0, 2],
[2, 3]])
>>> ind = np.argsort(x, axis=1) # sorts along last axis (across)
>>> ind
array([[0, 1],
[0, 1]])
>>> np.take_along_axis(x, ind, axis=1) # same as np.sort(x, axis=1)
array([[0, 3],
[2, 2]])
2、numpy.reshape()
本函数官网链接
numpy.reshape(a, newshape, order='C')
- 输入array a,返回重新改变完形状的reshaped_array,newshape以元组的形式给出
- order='C' 就是按行抽取,order='F' 就是按列抽取
- newshape元组里面有维度可以是-1,这一维度的值会自行推断出来
注意!!:python里面的赋值操作都是指向同一个内存,可看下面的避坑模块
>>> a = np.arange(6).reshape((3, 2))
>>> a
array([[0, 1],
[2, 3],
[4, 5]])
>>> np.reshape(a, (2, 3)) # C-like index ordering
array([[0, 1, 2],
[3, 4, 5]])
>>> a = np.array([[1,2,3], [4,5,6]])
>>> np.reshape(a, 6)
array([1, 2, 3, 4, 5, 6])
>>> np.reshape(a, 6, order='F')
array([1, 4, 2, 5, 3, 6])
>>> np.reshape(a, (3,-1)) # the unspecified value is inferred to be 2
array([[1, 2],
[3, 4],
[5, 6]])
3、numpy.stack() vstack() hstack()
numpy.stack() 函数官网链接
numpy.stack(arrays, axis=0, out=None)
- 输入的是arrays:就维度相同的一些array序列,返回的是堆叠后的数组stacked
- axis=0 默认按第一维度堆叠,axis=1 axis=2以此类推,axis=-1按最后一个维度堆叠
- 堆叠后的stacked要比原来的arrays多出一个维度
>>> arrays = [np.random.randn(3, 4) for _ in range(10)]
>>> np.stack(arrays, axis=0).shape
(10, 3, 4)
>>> np.stack(arrays, axis=1).shape
(3, 10, 4)
>>> np.stack(arrays, axis=2).shape
(3, 4, 10)
>>> a = np.array([1, 2, 3])
>>> b = np.array([2, 3, 4])
>>> np.stack((a, b))
array([[1, 2, 3],
[2, 3, 4]])
>>> np.stack((a, b), axis=-1)
array([[1, 2],
[2, 3],
[3, 4]])
numpy.vstack() 函数官网链接
numpy.vstack(tup) 英文解释:Stack arrays in sequence vertically (row wise)就是在垂直方向上堆叠
- 输入:把要垂直方向上堆叠的数组以元组形式输入,如果是1-D数组得有相同长度
- 输出:stacked的数组 至少2-D维度
>>> a = np.array([1, 2, 3])
>>> b = np.array([2, 3, 4])
>>> np.vstack((a,b))
array([[1, 2, 3],
[2, 3, 4]])
>>> a = np.array([[1], [2], [3]])
>>> b = np.array([[2], [3], [4]])
>>> np.vstack((a,b))
array([[1],
[2],
[3],
[2],
[3],
[4]])
numpy.hstack() 函数官网链接
numpy.hstack(tup)与之前差不多,直接给出示例:
>>> a = np.array((1,2,3))
>>> b = np.array((2,3,4))
>>> np.hstack((a,b))
array([1, 2, 3, 2, 3, 4])
>>> a = np.array([[1],[2],[3]])
>>> b = np.array([[2],[3],[4]])
>>> np.hstack((a,b))
array([[1, 2],
[2, 3],
[3, 4]])
发现输出没有“至少是2-D的了”
4、numpy.split() array_split()
numpy.split() 函数官网链接
numpy.split(ary, indices_or_sections, axis=0)
- 输入的是array:ary就是要被分出子数组的数组;输出是列表,里面的元素是一个个子数组
- indices_or_sections:可以是一个整数,也可以是一个1-D的数组。如果是一个整数,则表示沿着axis等分;如果是一个一维数组的话,例如[2,3](假设axis=0),则会被分成ary[:2]、ary[2:3]、ary[3:]。索引超出数组维度,会在相应位置返回一个空的子数组
- axis:默认是0
- 如果被给整数,但不能等分,会报错
>>> x = np.arange(9.0)
>>> np.split(x, 3)
[array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7., 8.])]
>>> x = np.arange(8.0)
>>> np.split(x, [3, 5, 6, 10])
[array([0., 1., 2.]),
array([3., 4.]),
array([5.]),
array([6., 7.]),
array([], dtype=float64)]
numpy.array_split() 函数官网链接
numpy.array_split(ary, indices_or_sections, axis=0)
与numpy.split()惟一的不同就是:indices_or_sections输入为一个整数时,可以不等分,不会报错。
如果输入长度为I,要分成n份,会返回I % n个长度为 (I // n) + 1的子数组,其余的数组长度为 I // n
>>> x = np.arange(8.0)
>>> np.array_split(x, 3)
[array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7.])]
>>> x = np.arange(7.0)
>>> np.array_split(x, 3)
[array([0., 1., 2.]), array([3., 4.]), array([5., 6.])]
类似的函数还有numpy.vsplit() 、numpy.hsplit()都是建立在numpy.split()的基础上,numpy.vsplit()就是split中axis=0(无论是怎样的维度,都沿axis=0),numpy.hsplit()就是split中axis=1(无论是怎样的维度,都沿axis=1)
5、numpy.concatenate()
本函数官网链接
numpy.concatenate((a1, a2, ...), axis=0, out=None)
- 输入的是数组序列:a1, a2,...除了指定的axis的维度的shape可以不一样,这些数组其他维度的shape必须一样;输出是组合后的数组
- axis:指定数组组合一起的轴,默认是0,如果axis=None则数组会被拉平
>>> a = np.array([[1, 2], [3, 4]])
>>> b = np.array([[5, 6]])
>>> np.concatenate((a, b), axis=0)
array([[1, 2],
[3, 4],
[5, 6]])
>>> np.concatenate((a, b.T), axis=1)
array([[1, 2, 5],
[3, 4, 6]])
>>> np.concatenate((a, b), axis=None)
array([1, 2, 3, 4, 5, 6])
6、numpy.repeat()
本函数官网链接
numpy.repeat(a, repeats, axis=None)
- 输入的是array a:返回的是重复后的数组repeated_array,在给定的axis方向上多出一些,其他维度的shape和输入一样
- repeats:可以是单个整数,也可以是整数数组,指明沿axis每个元素广播(重复)的次数
- axis:默认就是把原来的数组拉平了再广播,返回的也是拉平的数组,可以指定
>>> np.repeat(3, 4)
array([3, 3, 3, 3])
>>> x = np.array([[1,2],[3,4]])
>>> np.repeat(x, 2)
array([1, 1, 2, 2, 3, 3, 4, 4])
>>> np.repeat(x, 3, axis=1)
array([[1, 1, 1, 2, 2, 2],
[3, 3, 3, 4, 4, 4]])
>>> np.repeat(x, [1, 2], axis=0)
array([[1, 2],
[3, 4],
[3, 4]])
Python语法其他一些避坑
1、赋值与深浅拷贝
这一篇里面已经讲的很清楚了,我也试过,他里面的结论是正确的(Python版本3.5.2),这里罗列归纳一下:
- 对于数字和字符串的==赋值、浅拷贝、深拷贝==在内存当中用的都是同一块地址
- 对于字典、列表、元祖:
赋值:在内存中使用的是同一块地址
浅拷贝:只拷贝第一层地址
深拷贝:里面嵌套也都会变地址