数据操作之numpy模块3——数组的排序、乱序、索引与上下限设置

系列其他文章
数据分析之numpy模块1——数组的创建、属性、数据类型
数据分析之numpy模块2——数组的切片、变形、级联、拆分与数学计算

数组的排序操作

1. np.sort:数组全局排序

  • 类似于Python的内置函数sorted,将数组从小到大排序之后返回(一个新数组)。
arr3 = np.array([4, 2, 3, 6, 5, 1])
arr3

输出:array([4, 2, 3, 6, 5, 1])

new = np.sort(arr3)
new

输出:array([1, 2, 3, 4, 5, 6])

2. np.partition:分隔数组部分排序

  • partiton:n.分隔;v.把…分成几部分;
  • np.partition(arr, n):找出arr中第n + 1小的元素(将arr排序之后该元素索引值为n),然后返回以该元素作为分隔点的新数组。
arr2 = np.array([66, 15, 27, 33, 19, 13, 10])
arr2

输出:array([66, 15, 27, 33, 19, 13, 10])

np.partition(arr2, 3)
# 第4小的元素(排完序之后索引值为3)显然是19
# 那么将19放在索引为3的位置,然后左边的元素比它小,右边的元素比它大
# 至于19两边的顺序则没有要求

输出:array([15, 13, 10, 19, 27, 33, 66])

  • 虽然我们可以使用sort,但是sort是全局排序,如果数组数据量非常大,我们只希望选择最小的10个元素,直接通过np.partition(arr, 9)即可;然后只对这选出来的10个元素排序即可,而无需对整个大数组进行排序。

  • 同理还可以从后往前找, 比如:

np.partition(arr2, -2)
# 找到第2大的元素(将arr排序之后索引-2的元素)即33,放在数组索引为-2的地方
# 然后左边元素比它小,右边元素比它大

输出:array([13, 10, 27, 15, 19, 33, 66])


数组的乱序操作

1. np.random.permutation:返回乱序新数组

  • 输入为整数x,则生成一个x个数据的整数序列并打乱顺序;
x = np.random.permutation(10)
x

输出:[1 6 7 2 5 8 4 3 9 0]

  • 输入为数组或列表,则返回顺序打乱后的数组或列表;
y = np.random.permutation([0,1,2,3,4,5,6,7,8,9])
y

输出:[6 5 7 9 8 0 4 1 2 3]

2. np.random.shuffle:将原数组乱序

  • 二者区别:

shuffle:在原有数据的基础上操作,打乱元素的顺序,无返回值;
permutation:不是在原有数据的基础上操作,而是返回一个新的打乱顺序的数组;

z = np.array([0,1,2,3,4,5,6,7,8,9])
np.random.shuffle(z)
z

输出:[3 2 1 4 8 7 6 0 5 9]


数组的索引操作

1. 简单的基本索引

  • 基本索引操作和列表同理,更复杂的操作将在fancy indexing中介绍。
arr = np.random.randint(1,100,size=(5,6))
arr

输出:array([[19, 35, 62, 60, 45, 39],
      [80, 85, 68, 72, 34, 85],
      [ 7, 72, 48, 74, 24, 35],
      [12, 52, 96, 40, 2, 58],
      [39, 94, 50, 56, 49, 62]])

  • 取出单行数据:
arr[1]  #取出了numpy数组中的下标为1的行数据

输出:array([80, 85, 68, 72, 34, 85])

  • 取出多行数据:
arr[[1,3,4]] #取出多行

输出:array([[80, 85, 68, 72, 34, 85],
      [12, 52, 96, 40, 2, 58],
      [39, 94, 50, 56, 49, 62]])

  • 取出单个元素:
arr[0][2] #取出第1行第三列数据

输出:62

2. 利用arg相关函数索引

  • arg开头的函数区别于原始函数,不取数据,只取该数据对应的索引下标;
import numpy as np
arr = np.array([3, 22, 4, 11, 2, 44, 9])
arr

输出:array([ 3, 22, 4, 11, 2, 44, 9])

2.1 argmin:获取数组中最大元素对应的索引下标

print(np.min(arr))    #最小值为2
print(np.argmin(arr)) #2的索引下标为4

输出:2
   4

2.2 argmax:获取数组中最大元素对应的索引下标

print(np.max(arr)) #最大值为44
print(np.argmax(arr)) #44的索引下标为5

输出:44
   5

2.3 argwhere:获取数组中满足条件的元素的索引下标

arr1 = np.array([1, 2, 3, 4, 5, 6, 7, 8])
arr1

输出:array([1, 2, 3, 4, 5, 6, 7, 8])

  • np.where:类似于C的条件表达式,where(索引条件,满足条件执行,否则执行);
np.where(arr1>4, arr1-10,arr1*10) #如果元素大于4, 那么减去10; 否则扩大十倍

输出:array([10, 20, 30, 40, -5, -4, -3, -2])

np.where(arr1>4,arr1,4) #如果元素大于4, 那么保持不变, 否则变成4

输出: array([4, 4, 4, 4, 5, 6, 7, 8])

  • argwhere:这个函数只接受一个参数,找出满足索引条件的元素对应的索引下标。
a = np.argwhere(arr1%2!=0)
a

输出:array([[0],
      [2],
      [4],
      [6]], dtype=int64)

  • 显然元素1、3、5、7在%2之后不为0,所以会筛选出它们的索引,因此是[0 2 4 6]。只不过默认不是一个一维数组,我们需要再调用一下flatten,将其扁平化。
a.flatten()
# flatten是numpy.ndarray.flatten的一个函数,即返回一个折叠成一维的数组。
# 但是该函数只能适用于numpy对象,即array或者mat

输出:array([0, 2, 4, 6], dtype=int64)

2.4 argsort:获取排序后的数组元素对应的原索引下标

  • argsort是返回从小到大排序之后元素在原数组中对应的索引下标;
  • np.argsort(arr)等价于arr.argsort()
np.argsort(arr3)
# 原数组中1在5号位上,所以返回的数组第一个数据应该是5

输出:array([5, 1, 2, 0, 4, 3], dtype=int64)

arr3.argsort().argsort()
# 要想查看原数组每个数字在排序后分别在那个位置,可以调用两次argsort
# 如原数组中的4在排序后应该在新数组的3号位,所以两次argsort返回的第一个元素是3

输出: array([3, 1, 2, 5, 4, 0], dtype=int64)

2.5 argpartition: 获取分隔后的数组元素对应的原索引下标

np.argpartition(arr2, 3)
# 原数组中第4小的数在原数组中下标为4

输出:array([1, 5, 6, 4, 2, 3, 0], dtype=int64)

np.argpartition(arr2,-2)
# 原数组中第2大的数在原数组中下标为3

输出:array([5, 6, 2, 1, 4, 3, 0], dtype=int64)

3. fancy indexing高级索引

  • 指传递索引数组以便一次得到多个数组元素。
  • 使用fancy indexing时要特别注意的一点是返回数组的shape反映的是索引数组的shape而不是被索引的原数组的shape。
import numpy as np

3.1 从一维数组中取数据

a = np.array([i for i in range(15)])
np.random.shuffle(a) #shuffle用于将序列随机排序
a

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

  • 使用一维数组作为索引,返回一个维数组,其数据在原数组中的下标对应索引数组内的数据;
  • 索引数组必须是整型数据!
index=[3,5,8]
a[index] #将index数组作为索引对象,获取原数组内对应下标位置的数据

输出:array([ 0, 4, 13])

  • 当要从一维数组x中取出数据构成二维数组时,只需要使索引数组变成二维即可
ind = np.array([[0,2],
                [1,3]])
a[ind]

输出:array([[ 7, 6],
      [10, 0]])

3.2 从二维数组中取数据

b = np.random.randint(0,20,size=(4,4))
b

输出:array([[ 8, 2, 0, 18],
      [16, 1, 12, 18],
      [ 5, 11, 19, 15],
      [14, 13, 10, 9]])

row=[0,1,2]
col=[1,2,3]
  • 相当于取出(0,1),(1,2),(2,3)
b[row,col]

输出: array([ 2, 12, 15])

  • 切片与索引数组混合使用(注意切片时stop下标不包含在结果内)
b[1:3,col]

输出: array([[ 1, 12, 18],
       [11, 19, 15]])

b[row,0:2]

输出:array([[ 8, 2],
      [16, 1],
      [ 5, 11]])

col = np.array([2, 1, 3])
b[:,col]

输出:array([[ 0, 2, 18],
      [12, 1, 18],
      [19, 11, 15],
      [10, 13, 9]])

  • 也可对行/列的索引数组中传入布尔值
row=[True,False,True,False]
col=[False,True,True,True]
b

输出:array([[ 8, 2, 0, 18],
      [16, 1, 12, 18],
      [ 5, 11, 19, 15],
      [14, 13, 10, 9]])

b[:3,col]

输出:array([[ 2, 0, 18],
      [ 1, 12, 18],
      [11, 19, 15]])

b[row,1:4]

输出:array([[ 2, 0, 18],
      [11, 19, 15]])

3.3 数组的比较运算

  • 对每一个数据单独进行判断;
  • 返回一个bool类型的数组;
a

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

a<5

输出: array([False, False, False, True, False, True, False, False, False,
      True, True, False, True, False, False])

a>5

输出:array([ True, True, True, False, False, False, True, True, True,
      False, False, True, False, True, True])

a!=5

输出:array([ True, True, True, True, False, True, True, True, True,
      True, True, True, True, True, True])

3*a==24-3*a

输出:array([False, False, False, False, False, True, False, False, False,
      False, False, False, False, False, False])

  • 二维数组中相同
b

输出:array([[ 8, 2, 0, 18],
      [16, 1, 12, 18],
      [ 5, 11, 19, 15],
      [14, 13, 10, 9]])

b>6

输出:array([[ True, False, False, True],
      [ True, False, True, True],
      [False, True, True, True],
      [ True, True, True, True]])

3*b==24-3*b

输出:array([[False, False, False, False],
      [False, False, False, False],
      [False, False, False, False],
      [False, False, False, False]])

3.4 数组的逻辑运算

  • 与:&
  • 或:|
  • 非:~
  • 将数组中的每个值都进行逻辑位运算,返回一个布尔数据类型的数组
a

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

(a%2==0)&(a>7)

输出:array([False, True, False, False, False, False, False, True, False,
      False, False, True, False, True, False])

(a<3)|(a>10)

输出:array([False, False, False, True, False, False, False, True, True,
      False, True, False, True, True, True])

~(a>10)

输出:array([ True, True, True, True, True, True, True, False, False,
      True, True, True, True, False, False])

3.5 多种运算复合

  • 比如将计数操作与比较运算相结合
  • 将True当做1,False当做0,计数非0的个数
a

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

np.sum(a<3) #小于3的数据个数

输出:3

np.count_nonzero(a<3) #该函数是统计数组中非零元素个数

输出:3

np.sum((a%2==0)&(a>7))

输出: 4

  • 二维数组中同理
b

输出:array([[ 8, 2, 0, 18],
      [16, 1, 12, 18],
      [ 5, 11, 19, 15],
      [14, 13, 10, 9]])

  • axis轴向的理解:

0:对判断结果进行垂直方向上求和,即:列
1:对判断结果进行水平方向上求和,即:行

np.sum(b%3==0,axis=1)

输出:array([2, 2, 1, 1])

np.count_nonzero((b<3)|(b>10),axis=0)

输出:array([2, 4, 3, 3], dtype=int64)

3.6 any和all的使用

  • any:用于判断整个数组是否存在该条件的数据;
  • all:用于判断整个数组是否都满足该条件;
a

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

np.any(a>5)

输出:True

np.all(a>5)

输出: False

b

输出:array([[ 8, 2, 0, 18],
      [16, 1, 12, 18],
      [ 5, 11, 19, 15],
      [14, 13, 10, 9]])

  • axis轴向的理解

0:判断一整列的数据是否存在/都符合条件
1:判断一整行的数据是否存在/都符合条件

np.any(b%2==0,axis=0)

输出:array([ True, True, True, True])

np.all(b%2==0,axis=0)

输出:array([False, False, False, False])

3.7 复杂运算

  • 取每行第三列能被三整除的行;
b[b[:,3]%3==0,:]
#b[;,3]:取所有行的第三列
#b[;,3]%3:这一列能被3整除的行为True
#[b[;,3]%3,:]:判定为True的行取所有列

输出:array([[ 8, 2, 0, 18],
      [16, 1, 12, 18],
      [ 5, 11, 19, 15],
      [14, 13, 10, 9]])


数组上下限设置:clip

  • np.clip(arr,a,b):返回一个数组,将原数组中小于a的替换为a,大于b的替换为b,在设置上下限的时候非常有用。
np.clip(arr1,2,6) # 小于2的换成2,大于6的换成6,一般

输出:array([2, 2, 3, 4, 5, 6, 6, 6])

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值