numpy中的argpartition
numpy.argpartition(a, kth, axis=-1, kind='introselect', order=None)
在快排算法中,有一个典型的操作:partition
。这个操作指:根据一个数值x,把数组中的元素划分成两半,使得index前面的元素都不大于x,index后面的元素都不小于x。
numpy中的argpartition()
函数就是起的这个作用。对于传入的数组a,先用O(n)复杂度求出
第k大的数字`,然后利用这个第k大的数字将数组a划分成两半。
(第k大的数字, 就是排序(从小到大)后的数组,第k个位置的元素,自己理解的)
此函数不对原数组进行操作,它只返回分区之后的下标。一般numpy中以arg开头的函数都是返回下标而不改变原数组。
此函数还有另外两个参数:
kind
:用于指定partition的算法order
:表示排序的key,也就是按哪些字段进行排序
当我们只关心topK时,我们不需要使用np.sort()
对数组进行全量排序,np.argpartition()
已经够用了。
$ import numpy as np
$ a = np.array([9, 4, 4, 3, 3, 9, 0, 4, 6, 0])
$ print(np.argpartition(a, 4))
#将数组a中所有元素(包括重复元素)从小到大排列,比第5大的元素小的放在前面,大的放在后面,输出新数组索引
>> [6 9 4 3 7 2 1 5 8 0]
$ a[np.argpartition(a, 4)] #输出新数组索引对应的数组
>> array([0, 0, 3, 3, 4, 4, 4, 9, 6, 9])
注意,排序规则是从0开始排序,即,第0大的元素为“0”,第1大的元素还为“0”,第2大的元素为“3”
>>> arr = np.array([8,7,6,5,4,3,2,1])
>>> np.argpartition(arr, 0)
array([7, 1, 2, 3, 4, 5, 6, 0], dtype=int32)
>>> np.argpartition(arr, 1)
array([7, 6, 2, 3, 4, 5, 1, 0], dtype=int32)
>>> np.argpartition(arr, 2)
array([7, 6, 5, 3, 4, 2, 1, 0], dtype=int32)
>>> np.argpartition(arr, 3)
array([6, 7, 5, 4, 3, 1, 2, 0], dtype=int32)
>>> np.argpartition(arr, 4)
array([4, 7, 6, 5, 3, 1, 2, 0], dtype=int32)
>>> np.argpartition(arr, 5)
array([4, 7, 6, 5, 3, 2, 1, 0], dtype=int32)
>>> np.argpartition(arr, 6)
array([4, 7, 6, 5, 3, 2, 1, 0], dtype=int32)
>>> np.argpartition(arr, 7)
array([4, 7, 6, 5, 3, 2, 1, 0], dtype=int32)
第一次调用,给第二个参数传了0,说明我需要返回最小值得索引index。得到的返回值是array([7, 1, 2, 3, 4, 5, 6, 0], dtype=int32),在这个返回的array中,我关心的是第0个值(7),它是原数组arr的索引,arr[7]就是我要找的最小值。请注意返回值中的其他几个索引值,和原数组的索引比起来,他们基本上没有什么变化。接下来的几次调用也是这种情况,其实这也就说明argpartition没有对他不关心的数据做太大的改动或者操作。
$ import numpy as np
$ a = np.array([9, 4, 4, 3, 3, 9, 0, 4, 6, 0])
$ a[np.argpartition(a, -5)[-5:]]
>> array([4, 4, 9, 6, 9])
Clip
:如何使数组中的值保持在一定区间内
numpy.clip(a, a_min, a_max, out=None)[source]
在很多数据处理和算法中(比如强化学习中的 PPO),我们需要使得所有的值保持在一个上下限区间内。Numpy 内置的 Clip 函数
可以解决这个问题。Numpy clip () 函数
用于对数组中的值进行限制。给定一个区间范围,区间范围外的值将被截断到区间的边界上。例如,如果指定的区间是 [-1,1],小于-1 的值将变为-1,而大于 1 的值将变为 1
Clip
示例:限制数组中的最小值为 2,最大值为 6。
array = np.array([10, 7, 4, 3, 2, 2, 5, 9, 0, 4, 6, 0])
np.clip(array,2,5)
# array([5, 5, 4, 3, 2, 2, 5, 5, 2, 4, 5, 2])
array = np.array([10, -1, 4, -3, 2, 7, 5, 9, 0, 4, 6, 0])
# array([6, 2, 4, 2, 2, 2, 5, 6, 2, 4, 6, 2])
高维数组也是一样的
x=np.array([[1,2,3,5,6,7,8,9],[1,2,3,5,6,7,8,9]])
np.clip(x,3,8)
Out[90]:
array([[3, 3, 3, 5, 6, 7, 8, 8],
[3, 3, 3, 5, 6, 7, 8, 8]])
numpy.where()
函数,此函数返回数组中满足某个条件的元素的索引
1. np.where(condition, x, y)
三目运算满足condition,为x;不满足condition,则为y
score = np.array([[80, 88], [82, 81], [84, 75], [86, 83], [75, 81]])
# 如果数值小于80,替换为0,如果大于等于80,替换为90
re_score = np.where(score < 80, 0, 90)
print(re_score)
shuchu:
[[90 90]
[90 90]
[90 0]
[90 90]
[ 0 90]]
2. np.where(condition)
只有条件 (condition
),没有x和y,则输出满足条件 (即非0) 元素的坐标 (等价于numpy.nonzero
)。这里的坐标以tuple
的形式给出,通常原数组有多少维,输出的tuple中就包含几个数组,分别对应符合条件元素的各维坐标。
//这里我们输出x数据中大于5的元素的索引
y=np.where(x>5)
print(y)
输出结果:
(array([1, 2, 2, 2], dtype=int64), array([2, 0, 1, 2], dtype=int64))
//使用索引取出元素"
print(x[y])
输出结果:
[6 7 8 9]
Extract
:从数组中提取符合条件的元素
numpy.extract()
函数,和where函数有一点相,不过extract函数是返回满足条件的元素,而不是元素索引
可以使用 Numpy extract () 函数
从数组中提取符合条件的特定元素。
arr = np.arange(10)
arrarray([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])# Define the codition, here we take MOD 3 if zero
condition = np.mod(arr, 3)==0
#conditionarray([ True, False, False, True, False, False, True, False, False,True])
np.extract(condition, arr)
#array([0, 3, 6, 9])
同样地,如果有需要,我们可以用 AND 和 OR 组合的直接条件,如下所示:
np.extract(((arr > 2) & (arr < 8)), arr)
#array([3, 4, 5, 6, 7])
#定义条件,(元素 % 2==0)
condition=np.mod(x,2)==0
print(condition)
输出结果:
[[False True False]
[ True False True]
[False True False]]
返回满足条件的元素:
//获取满足条件的元素
print(np.extract(condition,x))
输出结果:
[2 4 6 8]
setdiff1d
:如何找到仅在 A 数组中有而 B 数组没有的元素
setdiff1d(ar1, ar2, assume_unique=False)
1.功能:找到2个数组中集合元素的差异。
2.返回值:在ar1中但不在ar2中的'已排序'的'唯一值'。
3.参数:
ar1:array_like 输入数组。
ar2:array_like 输入比较数组。
assume_unique:bool。如果为True,则假定输入数组是唯一的,即可以加快计算速度。 默认值为False。
返回数组中不在另一个数组中的独有元素。这等价于两个数组元素集合的差集。
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
b = np.array([3,4,7,6,7,8,11,12,14])
c = np.setdiff1d(a,b)
carray([1, 2, 5, 9])
numpy.intersect1d()
求两个数组的交集
>>> np.intersect1d([1, 3, 4, 3], [3, 1, 2, 1])
array([1, 3])
要求交集的数组多于两个, 可使用functools.reduce
:
>>> from functools import reduce
>>> reduce(np.intersect1d, ([1, 3, 4, 3], [3, 1, 2, 1], [6, 3, 4, 2]))
array([3])
numpy.nonzero()
函数
numpy.nonzero(a)[source]
返回数组a中非零元素的索引值数组。
(1)只有a中非零元素才会有索引值,那些零值元素没有索引值;
(2)返回的索引值数组是一个2维tuple数组,该tuple数组中包含一维的array数组。其中,一维array向量的个数与a的维数是一致的。
(3)索引值数组的每一个array均是从一个维度上来描述其索引值。比如,如果a是一个二维数组,则索引值数组有两个array,第一个array从行维度来描述索引值;第二个array从列维度来描述索引值。
(4) 该np.transpose(np.nonzero(x))
函数能够描述出每一个非零元素在不同维度的索引值。
(5)通过a[nonzero(a)]
得到所有a中的非零值
nz = np.nonzero([1,2,0,0,4,0])
nz
#(array([0, 1, 4], dtype=int64),)
nz[0]
#array([0, 1, 4], dtype=int64)
nz[0]
#array([0, 1, 4], dtype=int64)
numpy.pad()
函数
np.pad(array,pad_width,mode,**kwars)
解释:
第一个参数是待填充数组
第二个参数是填充的形状,(2,3)表示前面两个,后面三个
第三个参数是填充的方法
填充方法:
constant连续一样的值填充,有关于其填充值的参数。 constant_values=(x, y)时前面用x填充,后面用y填充。缺参数是为0000。。。
edge用边缘值填充
linear_ramp边缘递减的填充方式
maximum, mean, median, minimum分别用最大值、均值、中位数和最小值填充
reflect, symmetric都是对称填充。前一个是关于边缘对称,后一个是关于边缘外的空气对称╮(╯▽╰)╭
wrap用原数组后面的值填充前面,前面的值填充后面
也可以有其他自定义的填充方法
np.diag()
函数
numpy.diag(v, k=0)
Parameters:
v : array_like
If v is a 2-D array, return a copy of its k-th diagonal. If v is a 1-D array, return a 2-D array with v on the k-th diagonal.
k : int, optional
Diagonal in question. The default is 0. Use k>0 for diagonals above the main diagonal, and k<0 for diagonals below the main diagonal.
对角线的位置,大于零位于对角线上面,小于零则在下面。
Returns:
out : ndarray
The extracted diagonal or constructed diagonal array.
np.diag()可以提取一个矩阵的对角线数值,或是提供对角线数值让其构建一个矩阵
提取矩阵的对角线值
>>> x = np.arange(9).reshape((3,3))
>>> x
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> np.diag(x)
array([0, 4, 8])
根据值创建矩阵
>>> np.diag(array([0, 4, 8]))
array([[0, 0, 0],
[0, 4, 0],
[0, 0, 8]])
创建一个5*5矩阵,对角线下方值为1,2,3,4
Z = np.diag(1+np.arange(4),k=-1)
print(Z)
[[0 0 0 0 0]
[1 0 0 0 0]
[0 2 0 0 0]
[0 0 3 0 0]
[0 0 0 4 0]]
numpy.unravel_index()
函数
numpy.unravel_index()
函数的作用是获取一个/组int类型的索引值在一个多维数组中的位置。
numpy.unravel_index(indices, dims, order='C')
有一个ndarray数组A,A.shape = [3, 3, 3, 2],A.dtype=np.int64。如何找到A中最大元素的索引???
>>> import numpy as np
>>> A=np.random.randint(1,100,size=(3,3,3,2))
>>> A
array([[[[25, 36],
[78, 83],
[97, 11]],
[[32, 37],
[14, 10],
[72, 92]],
[[34, 72],
[90, 61],
[62, 31]]],
[[[59, 41],
[53, 12],
[33, 62]],
[[72, 25],
[ 9, 19],
[64, 93]],
[[76, 42],
[98, 21],
[31, 40]]],
[[[58, 27],
[64, 78],
[52, 34]],
[[63, 45],
[79, 3],
[78, 2]],
[[ 5, 31],
[84, 15],
[64, 38]]]])
可以使用np.argmax()
函数来完成:
>>> ind_max=np.argmax(A)
>>> ind_max
32
此时得到的最大值索引是将A进行flatten
成一维数组之后的索引值,如何得到最大元素在原数组A中的索引呢?这就是np.unravel_index()
函数做的事情:
>>> ind_max_src=np.unravel_index(ind_max, A.shape)
>>> ind_max_src
(1, 2, 1, 0)
>>> A[1,2,1,0]
98
np.unravel_index()
函数的第一个参数indices除了可以是int型标量值,还可以是一个int型数组,当indices为int型数组时,
numpy数组扩展函数repeat和
tile`用法
numpy数组扩展函数有repeat
和tile
,由于数组不能进行动态扩展,故函数调用之后都重新分配新的空间来存储扩展后的数据。
repeat
函数功能:对数组中的元素进行连续重复复制
用法有两种:
1) numpy.repeat(a, repeats, axis=None)
2) a.repeats(repeats, axis=None)
a为数组,repeats为重复的次数,axis表示数组维度
tile函数
功能:对整个数组进行复制拼接
用法:numpy.tile(a, reps)
其中a为数组,reps为重复的次数
日期格式、dtype='datetime64[D]'
Z = np.arange('2016-07', '2016-08', dtype='datetime64[D]')
print(Z)
'''
array(['2016-07-01', '2016-07-02', '2016-07-03', '2016-07-04',
'2016-07-05', '2016-07-06', '2016-07-07', '2016-07-08',
'2016-07-09', '2016-07-10', '2016-07-11', '2016-07-12',
'2016-07-13', '2016-07-14', '2016-07-15', '2016-07-16',
'2016-07-17', '2016-07-18', '2016-07-19', '2016-07-20',
'2016-07-21', '2016-07-22', '2016-07-23', '2016-07-24',
'2016-07-25', '2016-07-26', '2016-07-27', '2016-07-28',
'2016-07-29', '2016-07-30', '2016-07-31'], dtype='datetime64[D]')
'''
numpy.fromiter()
函数
此函数从任何可迭代对象构建一个ndarray对象,返回一个新的一维数组。
numpy.fromiter(iterable, dtype, count = -1)
iterable 任何可迭代对象
dtype 返回数组的数据类型
count 需要读取的数据数量,默认为-1,读取所有数据
给定一个生成器函数,可以生成10个整数,使用它来创建一个数组
def generate():
for x in range(10):
yield x
Z = np.fromiter(generate(),dtype=float,count=-1)
print(Z)
#[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]
numpy.itemsize
这一数组属性返回数组中每个元素的字节单位长度。
9
10
11
12
13
14
import numpy as np
a = np.array([1, 2, 3, 4, 5], dtype=np.int8) # 数组的 dtype 为 int8(一个字节)
b = np.array([1, 2, 3, 4, 5], dtype=np.float32) # 数组的 dtype 现在为 float32(四个字节)
print("a:", a)
print("a.itemsize:", a.itemsize)
print("b:", b)
print("b.itemsize:", b.itemsize)
# output:
# a: [1 2 3 4 5]
# a.itemsize: 1
# b: [1. 2. 3. 4. 5.]
# b.itemsize: 4
ndarray.ndim
这一数组属性返回数组的维数。
15
16
17
18
19
20
21
22
import numpy as np
a = np.arange(24)
b = a.reshape(2, 4, 3)
print("a:", a)
print("a.ndim:", a.ndim)
print("b:", b)
print("b.ndim:", b.ndim)
# output:
# a: [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]
# a.ndim: 1
# b: [[[ 0 1 2]
# [ 3 4 5]
# [ 6 7 8]
# [ 9 10 11]]
#
# [[12 13 14]
# [15 16 17]
# [18 19 20]
# [21 22 23]]]
# b.ndim: 3
numpy.linspace
此函数类似于arange()函数。 在此函数中,指定了范围之间的均匀间隔数量,而不是步长。 此函数的用法如下。
numpy.linspace(start, stop, num, endpoint, retstep, dtype)
创建一个长度为10的数组,值为0~1之间,不包含首尾
Z = np.linspace(0,1,11,endpoint=False)[1:]
print(Z)
np.allclose()
numpy的allclose方法,比较两个array是不是每一元素都相等,默认在1e-05的误差范围内
np.array_equal()
np.all()
对所有的数据进行比较,如果都满足条件则返回True
np.any()
只要有一个数据满足条件就返回True
np.put()
numpy.put(a, ind, v, mode='raise')[source]
参数
----------
a:ndarray
目标数组。
ind:array_like
目标索引,解释为整数。
v:array_like
在目标指数的“a”中放置的值。 如果`v`比`ind`短,它将在必要时重复。
mode:{'raise','wrap','clip'},optional指定越界索引的行为方式。
*'加注' - 引发错误(默认)
*'包裹' - 环绕
*'剪辑' - 剪辑到范围
'clip'模式意味着所有过大的索引都被索引沿着该轴的最后一个元素所取代。 请注意,这会禁用带负数的索引。
Examples
--------
>>> a = np.arange(5)
>>> np.put(a, [0, 2], [-44, -55])
>>> a
array([-44, 1, -55, 3, 4])
>>> a = np.arange(5)
>>> np.put(a, 22, -5, mode='clip')
>>> a
array([ 0, 1, 2, 3, -5])
当索引地址超过数组的索引地址时,利用所给值直接替换数组的最后一个值
将p个元素随机放置在二维数组中
n = 10
p = 3
Z = np.zeros((n,n))
np.put(Z,
np.random.choice(range(n*n), p, replace=False),
1)
print(Z)
np.percentile()
分位数函数
在python中计算一个多维数组的任意百分比分位数,此处的百分位是从小到大排列,只需用np.percentile
即可……
numpy.percentile(a, q, axis=None, out=None, overwrite_input=False, interpolation='linear', keepdims=False)
a : np数组
q : float in range of [0,100] (or sequence of floats)
Percentile to compute。
要计算的q分位数。
axis : 那个轴上运算。
keepdims :bool是否保持维度不变。
import numpy as np
a = np.array([1,2,3,4,5])
p = np.percentile(a, 50) # 求中位数
>>> a = np.array([[10, 7, 4], [3, 2, 1]])
>>> a
array([[10, 7, 4],
[ 3, 2, 1]])
>>> np.percentile(a, 50) #50%的分位数,就是a里排序之后的中位数
3.5
>>> np.percentile(a, 50, axis=0) #axis为0,在纵列上求
array([[ 6.5, 4.5, 2.5]])
>>> np.percentile(a, 50, axis=1) #axis为1,在横行上求
array([ 7., 2.])
>>> np.percentile(a, 50, axis=1, keepdims=True) #keepdims=True保持维度不变
array([[ 7.],
[ 2.]])