初入Python数据分析库——Numpy(四)

一、切片

(一)含义理解

笔者对切片的理解是:获取 被切片列表、数组 的一段地址

我们可以举一个超能力猪肉的例子。假设我们要切片的对象就是这么一块超能力猪肉,但是这块猪肉不管被怎么切,它都不会少
现在顾客A想要瘦肉的部分,于是我们就从猪肉中切取瘦肉的部分;然后顾客B想要一半肥肉一半瘦肉,我们同样将想要的猪肉切给他。
因为是超能力猪肉,所以,顾客A切过之后,顾客B 还是可以切到瘦肉

这就是切片的含义,相信读者已经可以理解了。

(二)标准写法:列表名[start:stop:step]

注意1:

stop 不包含在内

设计原理:

  1. 可以直接计算出元素个数,末 - 初
  2. 分成两个部分,前一部分不包含,后一部分直接开始

注意2:

数组切片是原始数组视图(切改原改)。 如果不想改原始数组,我们就要进行显式的复制,从而得到它的副本。

关于这个注意2,我们继续用上面的例子。
当顾客A和顾客B得到猪肉之后,打算带回家料理。
顾客A先到家,并先将瘦肉切成片。这时候,我手上的超能力猪肉瘦肉的部分也被切成片了
之后,顾客B也回到家了,他决定直接将一大块肥瘦兼并的猪肉一起放到水里煮。这时候,我手上的猪瘦肉的部分就自动粘回在一起了,并且,那半肥半瘦的部位开始发烫

相信读者已经理解了,注意2的意思。如果不理解也没关系,下文有代码解释。

(三)Python中的切片

# 切片值 不会受到任何影响
a_list = [1,2,3,4]
b_list = a_list
c_list = a_list[:]   # [:] 就是全部都切
d_list = a_list[1:3]
# 两者的改变 会 影响原始值,不会影响 被赋值的切片
a_list[1] = 10     # a_list 变 --> b_list变、c_list 不变、d_list 不变
b_list[2] = 10     # b_list 变 --> a_list变、c_list 不变、d_list 不变
# 被赋值的切片 被改变 不会 影响原始值
c_list[2] = 20     # c_list 变 --> a_list 不变、b_list 不变、d_list 不变
print(a_list)
print(b_list)
print(c_list)
print(d_list)

# --------------------------------------
[1, 10, 10, 4]
[1, 10, 10, 4]
[1, 2, 20, 4]
[2, 3]

1.浅拷贝 copy

两者互相打扰!!!

import copy
a_list = [100,[200,300]]
b_list = a_list.copy()
a_list[1][0] = 500
b_list[1][1] = 600
print(a_list)
print(b_list)
print(b_list[1][0])

# --------------------------------------
[100, [500, 600]]
[100, [500, 600]]
500

2.深拷贝 copy.deepcopy

两者互不干扰!!!

import copy
a_list = [100,[200,300]]
b_list = copy.deepcopy(a_list)
a_list[1][0] = 500
b_list[1][0] = 600
print(a_list)	 
print(b_list)	 

# --------------------------------------
[100, [500, 300]]
[100, [600, 300]]

(四)Ndarray中的切片

1.一维数组

# 示例1:
ar = np.arange(10)
print(ar)
# 切片本身被改变了
ar[5] = 100
ar[7:9] = 200
print(ar)

# --------------------------------------
[0 1 2 3 4 5 6 7 8 9]
[  0   1   2   3   4 100   6 200 200   9]
# 示例2:
ar1 = np.arange(10)
print(ar1)
ar2 = ar1[2:7:2]
print(ar2)
ar3 = ar1[2:7]
print(ar3)

# --------------------------------------
[0 1 2 3 4 5 6 7 8 9]
[2 4 6]
[2 3 4 5 6]

2.二维数组

切片可以使用 ...如果在行位置使用省略号,那么返回值将包含所有行元素;反之则包含所有列元素。

# 示例1:
ar4 = np.arange(20).reshape(4,5)
print(ar4)
# 获得行切片
ar4[2:]
# 获得列切片
ar4[...,1]
ar4[...,1:]

# --------------------------------------
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])
       
# 获得行切片
array([[10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])

# 获得列切片
array([ 1,  6, 11, 16])

array([[ 1,  2,  3,  4],
       [ 6,  7,  8,  9],
       [11, 12, 13, 14],
       [16, 17, 18, 19]])
# 示例2:
ar4 = np.arange(20).reshape(4,5)
print(ar4)
# 交集的思路  -->  行是所有行,列是所有列。两者相交
print(ar4[1,2])      #   此处的中括号里面是  ,  代表满足交集思路
# 降维的思路 -->  先ar4[1]  ,出来之后在   [2]
print(ar4[1][2])

# 降维证明 -->  先ar4[...]  ,出来之后在 ar5[1]
print(ar4[...][1])
ar5 = ar4[...]
print(ar5[1])

# --------------------------------------
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])
7
7
[5 6 7 8 9]
[5 6 7 8 9]

二、索引

1.正向索引,则索引值从 0 开始
2.反向索引,则索引值从 -1 开始

(一)整数数组索引

# 示例1:
# 创建二维数组
x = np.array([
    [1,2],
    [3,4],
    [5,6] ])
# [0,1,2]:行索引;
# [0,1,0]:列索引。
# 0->0:1  ;     1->1:4 ;     2->0:5
y = x[[0,1,2],[0,1,0]]
y

# --------------------------------------
array([1, 4, 5])
# 示例2:
a = np.arange(12).reshape(4,3)
print(a)
b = a[  [0,0,3,3],[0,2,0,2]  ]
#为什么要 reshape --> 因为四维的不好理解,三维又存不下,所有换成 2*2 
r = np.array([  [0,0],[3,3]  ]).reshape(4)
l = np.array([  [0,2],[0,2]  ]).reshape(4)
s = a[r,l].reshape((2,2))
print(s)

#--------------------------------------
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
 
[[ 0  2]
 [ 9 11]]
# 示例3:
a = np.arange(1,10).reshape(3,3)
print(a)
b = a[1:3,1:3]
c = a[1:3,[1,2]]      # 此处以第一个 , 为界限。[1,2]代表了:索引为1、2的列都取
d = a[...,1:]
print(b)
print(c)
print(d)

#--------------------------------------
[[1 2 3]
 [4 5 6]
 [7 8 9]]
 
[[5 6]
 [8 9]]
 
[[5 6]
 [8 9]]
 
[[2 3]
 [5 6]
 [8 9]]

练习:创建一个 8*8 的国际象棋棋盘矩阵(黑块为0,白块为1)

Z = np.zeros((8,8),dtype = int)
Z[1::2,0::2] = 1      # 行从1开始,以2为跨步;列从0开始,以2为跨步。两者相交
Z[0::2,1::2] = 1
print(Z)

#--------------------------------------
[[0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]
 [0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]
 [0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]
 [0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]]

(二)布尔数组索引

1.布尔索引 简单理解就是:保留 True值 的索引

练习1:提取出数组中所有奇数

a = np.arange(0,12).reshape(4,3)
b = a[a%2 == 1]    # 余数为1的值判断为True,然后将索引值放入
b

#--------------------------------------
array([ 1,  3,  5,  7,  9, 11])

练习2:将修改奇数值为 -1
–> 此题出得不是很好,因为下标和索引是一样的。

a = np.arange(0,12).reshape(4,3)
a[a%2 == 1] = -1
a

#--------------------------------------
array([[ 0, -1,  2],
       [-1,  4, -1],
       [ 6, -1,  8],
       [-1, 10, -1]])

2.& | 的运用

x = np.arange(0,12).reshape((4,3))
x1 = x[(x>4) & (x<9)]      # 合运算
x2 = x[(x<4) | (x>9)]      # 或运算
print(x1)
print(x2)

#--------------------------------------
[5 6 7 8]
[ 0  1  2  3 10 11]

3.True 和 False 的形式表示需要和不需要的数据
(索引的“真”数量要一样,否则行列不匹配,就会报错!)

# 示例1:
ar1 = np.arange(12).reshape(3,4)
print(ar1)
# 行变量 存在3个元素
row = np.array([False,True,True])      # 只有为True的才能打印出来,数量是2
# 列变量 存在4个元素
colum = np.array([True,False,True,False])      # 只有为True的才能打印出来,数量是2
# 单独运行 行
print(ar1[row])
print(ar1[[1,2],:])
print(ar1[[1,2],...])
# 单独运行 列
print(ar1[:,colum])
print(ar1[:,[0,2]])

#--------------------------------------
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]

# 单独运行 行 
[[ 4  5  6  7]
 [ 8  9 10 11]]
 
[[ 4  5  6  7]
 [ 8  9 10 11]]
 
[[ 4  5  6  7]
 [ 8  9 10 11]]
 
 # 单独运行 列
[[ 0  2]
 [ 4  6]
 [ 8 10]]
 
[[ 0  2]
 [ 4  6]
 [ 8 10]]
# 示例2:
ar1 = np.arange(20).reshape(5,4)
print(ar1)
row = np.array([False,True,True,False,True])      # 只有为True的才能打印出来,数量是3
colum = np.array([True,False,True,False])      # 只有为True的才能打印出来,数量是2

#--------------------------------------
运行错误,True的数量不匹配,无法打印
# 示例3:
a = np.arange(12).reshape(3,4)
print(a)
b1 = np.array([False,True,True])
​
b2 = np.array([True,False,True,False])
# 使用 布尔型索引之后,会返回 数组的对角线
print(a[b1,b2])
​
# 如果想要返回 都为“真” 的数组,那就需要用  np.ix_()  函数
print(a[np.ix_(b1,b2)])

#--------------------------------------
[[ 0  1  2  3]
[ 4  5  6  7]
[ 8  9 10 11]]

[ 4 10]

[[ 4  6]
[ 8 10]]

练习3:要 np.arange(12).reshape(3,4) 第1、3行的 1、3、4列

a = np.arange(12).reshape(3,4)
print(a)
b = a[[0,2],...]
print(b)
c = b[...,[0,2,3]]
print(c)
​
#-------------------------------------- ```
# 注意:由于形状不一样,所以不可以直接就 a[[0,2],[0,2,3]]
[[ 0  1  2  3]
[ 4  5  6  7]
[ 8  9 10 11]]

[[ 0  1  2  3]
[ 8  9 10 11]]

[[ 0  2  3]
[ 8 10 11]]

三、练习

练习1:创建0到24的5*5数组ar,通过索引,其ar[4]、ar[:2,3:]、ar[3][2]分别是多少

ar1 = np.arange(25).reshape(5,5)
print(ar1)
print(ar1[4])
print(ar1[:2,3:])   #  :之后的数值是不包含的
print(ar1[3][2])

# --------------------------------------
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]
 [20 21 22 23 24]]
 
[20 21 22 23 24]

[[3 4]
 [8 9]]
 
17

练习2:创建0到9的2*5数组ar,筛选出元素值大于5的值并生成新的数组

ar2 = np.arange(2,12).reshape(2,5)
print(ar2)
x = ar2[ar2 > 5]   # 为 True 的留下
print(x)

# --------------------------------------
[[ 2  3  4  5  6]
 [ 7  8  9 10 11]]
 
[ 6  7  8  9 10 11]

练习3:创建一个2维10*10数组,使该数组边界值为1,内部的值为0

ar3 = np.zeros((10,10))
ar3[...,[0,-1]] = 1      # 所有行的 -->  第一列 和 最后一列
ar3[[0,-1],...] = 1      # 所有列的 -->  第一行 和 最后一行
ar3

# ----------------------------------------------------
array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
       [1., 0., 0., 0., 0., 0., 0., 0., 0., 1.],
       [1., 0., 0., 0., 0., 0., 0., 0., 0., 1.],
       [1., 0., 0., 0., 0., 0., 0., 0., 0., 1.],
       [1., 0., 0., 0., 0., 0., 0., 0., 0., 1.],
       [1., 0., 0., 0., 0., 0., 0., 0., 0., 1.],
       [1., 0., 0., 0., 0., 0., 0., 0., 0., 1.],
       [1., 0., 0., 0., 0., 0., 0., 0., 0., 1.],
       [1., 0., 0., 0., 0., 0., 0., 0., 0., 1.],
       [1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]])

练习4:创建一个从10到49的ndarray对象,并进行倒序复制给另一个变量

ar4 = np.arange(10,50)
ar4_1 = ar4[::-1]     # 意思就是从起点,向后倒着走一个⚪
ar4_1

# ----------------------------------------------------
array([49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33,
       32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16,
       15, 14, 13, 12, 11, 10])

练习5:a=np.arange(0,20).reshape(4,5),需要更换第二行和三行的位置

import copy
ar5 = np.arange(0,20).reshape(4,5)
print(ar5)
ar5_1 = copy.deepcopy(ar5[1])
ar5_2 = copy.deepcopy(ar5[2])
ar5[1] = ar5_2
ar5[2] = ar5_1
print(ar5)

# ----------------------------------------------------
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
 
[[ 0  1  2  3  4]
 [10 11 12 13 14]
 [ 5  6  7  8  9]
 [15 16 17 18 19]]

练习6:分别反转练习5中二维数组的列和行
这里直接介绍一下转置,转置需要用到的函数就是 transpose()

示例1的转置比较容易理解,示例2的可能就不怎么好理解了。大家先看看代码,下面会介绍一个统一的方法。

# 示例1:
x = np.arange(4).reshape((2,2))
print(x)
x = x.transpose()
print(x)

# ----------------------------------------------------
[[0 1]
 [2 3]]
 
[[0 2]
 [1 3]]

示例1:
在这里插入图片描述
0轴表示一维,1轴上放二维的数字。当发生转置的时候,两轴互换位置,相当于从纸里面向外看。

# 示例2:
x = np.arange(16).reshape(2,3,4)
print(x)
x = x.transpose()
print(x)

# ----------------------------------------------------
[[[ 0  1  2  3]
 [ 4  5  6  7]]
[[ 8  9 10 11]
 [12 13 14 15]]]


[[[ 0  8]
 [ 4 12]]

[[ 1  9]
 [ 5 13]]

[[ 2 10]
 [ 6 14]]

[[ 3 11]
 [ 7 15]]]

示例2:
在这里插入图片描述
2轴表示三维,第二个中括号 [[ 8 9 10 11] [12 13 14 15]] 的数字就叠放在0轴和1轴形成的平面上方。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值