numpy 花哨的索引、排序和结构化数据

与世无争的帅哥 提交于 2020-02-24 03:58:20

花哨的索引

  • 使用数组作为索引叫花哨的索引(Fnacy Indexing)
  • 花哨的索引让我们快速访问复杂数组的子数据集
  • 使用花哨的索引同样可以对子数据集进行写操作
  • 利用花哨的索引获得的结果与索引的形状(Shape)⼀致,跟被索引的数组的形状无关。
import numpy as np
# 产⽣10个随机数字
x = np.random.randint(100, size=10)
print("x = ", x)
indx = [2,3,7]
#用数组作为索引就是花哨的索引
a = x[indx]
print("a = ",a)
# 结果的shape跟索引的shape⼀致
print("a.shape = ", a.shape)
x = [23 42 29 74 57 58 53 44 11 6]
a = [29 74 44]
a.shape = (3,)

使用⼀个2x2的数组作为索引

indx = np.array([2,3,5,7]).reshape((2,2))
print("indx.shape = ", indx.shape)
print()
# 使用⼀个2x2的数组作为索引
b = x[indx]
print("b = ", b)
print()
# 结果的shape跟索引的shape⼀致
print("b.shape = ", b.shape)
indx.shape = (2, 2)
b = [[29 74]
 [58 44]]
b.shape = (2, 2)

对于花哨的索引,可以使用两个数组分别表示,但是在索引的配对的时候,需要遵守广播规则才能⼀对⼀配对,例如下面例子:

x = np.arange(16).reshape((4,4))
print("x = ", x)
print()
print("x.shape = ", x.shape)
print()
# 我们会获得的结果是三个数字组成的数组
# 三个数字分别是(0,3), (2,1), (3,1)
r = np.array([0,2,3])
c = np.array([3,1,1])
a = x[r, c]
print("a = ", a)
print("a.shape = ",a.shape)
x = [[ 0 1 2 3]
 [ 4 5 6 7]
 [ 8 9 10 11]
 [12 13 14 15]]
x.shape = (4, 4)
a = [ 3 9 13]
a.shape = (3,)

花哨的索引还可以有更花哨的用法,比如:

import numpy as np
x = np.arange(20).reshape((4,5))
print("x = ", x)
print("x.shape = ", x.shape)
print()
x = [[ 0 1 2 3 4]
 [ 5 6 7 8 9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
x.shape = (4, 5)

简单的索引和花哨的索引组合使⽤

a = x[2, [3,2,1]]
print("x[2, [3,2,1]] = ", a)
print("a.shape = ", a.shape)
x[2, [3,2,1]] = [13 12 11]
a.shape = (3,)

花哨的索引+切片配合使用

print()
b = x[2:, [3,2,1]]
print("x[2:, [3,2,1]] = ", b)
print("b.shape = ", b.shape)
x[2:, [3,2,1]] = [[13 12 11]
 [18 17 16]]
b.shape = (2, 3)

花哨的索引+掩码

print(x)
mask = np.array([1,0,1,1,0], dtype=bool)
print(c)
c = x[[0,2,3], mask]
print("x[[0,2,3], mask] = \n", c)
print("c.shape = ", c.shape)
[[ 0 1 2 3 4]
 [ 5 6 7 8 9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
[ 0 12 18]
x[[0,2,3], mask] =
 [ 0 12 18]
c.shape = (3,)

利用户花哨的索引批量修改数据

x = np.arange(10)
x[[2,4,6,8]] = 999
print(x)
[ 0 1 999 3 999 5 999 7 999 9]

数组的排序

  • 数组排序默认使用户快排
  • 根据选择,可以选用其他方式排序
  • 可选参数还有axis,可以选择沿着哪个⽅向排序,此时把这个⽅向的数据当初独立数组对待

sort

  • 默认快排, 其他归并排序,堆排序, 稳定排序
  • 不修改源数据,返回排好的数据下使用np.sort(data)
  • 修改数据源,使用 data.sort()
x = np.random.randint(20, size =10)
print("排序前 X = ", x)
a = np.sort(x)
print("排序后 X = ", x)
print("排序后 a = ", a)
x.sort()
print("修改数据源排序后 X = ", x)
排序前 X = [ 3 8 5 7 17 0 16 16 1 8]
排序后 X = [ 3 8 5 7 17 0 16 16 1 8]
排序后 a = [ 0 1 3 5 7 8 8 16 16 17]
修改数据源排序后 X = [ 0 1 3 5 7 8 8 16 16 17]

argsort

返回排序后数据的索引

x = np.random.randint(20, size =10)
print("排序前 X = ", x)
a = np.argsort(x)
print("排序后的索引: ", a)
排序前 X = [10 2 0 6 10 3 9 2 18 8]
排序后的索引: [2 1 7 5 3 9 6 0 4 8]

分隔

  • 选择出前k个最小的值,以排序第k个值为界限,小于它的在前⾯,等于小于它的在后⾯
  • 选择结果在数组左侧,其余的在数组右侧
  • 两侧排序不规则
  • 使用方法是 np.partition(x, k)
x = np.random.randint(100, size=10)
print("排序前 x= ", x)
a = np.partition(x, 4)
print("分隔后的值 x= ", a)
排序前 x= [99 71 55 60 86 16 18 51 53 37]
分隔后的值 x= [16 51 18 37 53 71 55 60 86 99]
x = np.random.randint(100, size=(4,5))
print("排序前 x = \n", x)
a = np.partition(x, 3, axis=1)
print("沿着axis=1分隔后的数据是 \n", a)
排序前 x =
 [[33 16 2 12 51]
 [28 61 55 95 18]
 [30 23 72 57 89]
 [20 49 23 26 0]]
沿着axis=1分隔后的数据是
 [[12 2 16 33 51]
 [18 28 55 61 95]
 [57 30 23 72 89]
 [ 0 20 23 26 49]]

结构化数据

  • 用于存储异构数值,类似c语⾔的结构
  • 复杂结构建议使用Pandas的DataFrame
# 定义⼀个学⽣信息数组,包括姓名,成绩,身⾼
x = np.zeros(4, dtype={"names":("name", "score", "heigh"), \
 "formats":("U10", "i4", "f8")})
print("x = ", x)
print("x.dtype = ", x.dtype)
x = [('', 0, 0.) ('', 0, 0.) ('', 0, 0.) ('', 0, 0.)]
x.dtype = [('name', '<U10'), ('score', '<i4'), ('heigh', '<f8')]

可以对某⼀项进⾏统⼀赋值

x['name'] = "LIU Ying"
x['score'] = 98
x['heigh'] = 185
print("统⼀赋值后的x = \n", x )
统⼀赋值后的x =
 [('LIU Ying', 98, 185.) ('LIU Ying', 98, 185.) ('LIU Ying', 98, 185.)
 ('LIU Ying', 98, 185.)]

可以采⽤key的形式进⾏访问列,也可以采用索引的形式进行访问行

# 可以采⽤key的形式进⾏访问列
print("学⽣的姓名是: ", x['name'])
# 也可以采⽤索引的形式进⾏访问⾏
print("第⼀⾏的同学是: ", x[0])
学⽣的姓名是: ['LIU Ying' 'LIU Ying' 'LIU Ying' 'LIU Ying']
第⼀⾏的同学是: ('LIU Ying', 98, 185.)

可以对结构化数据进⾏批量赋值

names = ["Alice", "Bob", "Cindy", "Day"]
score = [86, 45,68,98]
heigh = [154, 184, 198,178]
x["name"] = names
x["score"] = score
x["heigh"] = heigh
print("统⼀赋值后的 x = \n", x)
统⼀赋值后的 x =
 [('Alice', 86, 154.) ('Bob', 45, 184.) ('Cindy', 68, 198.)
 ('Day', 98, 178.)]

结构化数据的掩码操作

# 选择成绩⼩于90的同学的姓名
print(x[x['score'] < 90]['name'])
['Alice' 'Bob' 'Cindy']

结构化数据的常用类型定义方式

结构化数组的类型的定义方式比较灵活,常⽤的有以下几种方式:
1.使用字典作为机构化数组的类型

a = np.dtype({"names":("name", "score", "heigh"), \
 "formats":("U10", "i4", "f8")})
print(a)
[('name', '<U10'), ('score', '<i4'), ('heigh', '<f8')]

2.使用python数据类型或者NumPy的dtype类型

b = np.dtype({"names":("name", "score", "heigh"), \
 "formats":((np.str_, 10), int, float)})
print(b)
[('name', '<U10'), ('score', '<i4'), ('heigh', '<f8')]

3.如果类型的名称不重要, 可以省略

c = np.dtype("S10, i4, f8")
print(c)
[('f0', 'S10'), ('f1', '<i4'), ('f2', '<f8')]

4.复合类型

# 此类型类似C语⾔中的结构
import numpy as np
# 定义⼀个结构
tp = np.dtype([('id', 'i8'), ('mat', 'f8', (4,4))])
# 利⽤定义的结构tp创建⼀份内容
x = np.zeros(2, dtype=tp)
#打印整个内容
print(x)
# 只打印出数据内容
print(x['mat'][0])
[(0, [[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.]])
 (0, [[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0.,
0.]])]
[[0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]]
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!