数据分析三剑客:NumPy库入门2

前言

书接上回:
数据分析三剑客:NumPy库入门1

复制和视图

  在操作数组时,有时会将其数据复制到新数组中,有时不复制。

  对于初学者来说,这通常会引起混乱。有以下三种情况:

完全没有复制

import numpy as np
a = np.random.randint(0,100,size = (4,5))
b = a
a is b # 返回True a和b是两个不同名字对应同一个内存对象
b[0,0] = 1024 # 命运共同体
display(a,b)
#输出:
array([[1024,   17,   53,   20,   55],
       [  12,    1,   76,   29,   65],
       [  28,   60,   41,   79,   28],
       [  75,   95,   80,   34,   95]], dtype=int32)
array([[1024,   17,   53,   20,   55],
       [  12,    1,   76,   29,   65],
       [  28,   60,   41,   79,   28],
       [  75,   95,   80,   34,   95]], dtype=int32)

查看或浅拷贝

  不同的数组对象可以共享相同的数据。该view方法创建一个查看相同数据的新数组对象。

import numpy as np
a = np.random.randint(0,100,size = (4,5))
b = a.view() # 使用a中的数据创建一个新数组对象
a is b # 返回False a和b是两个不同名字对应同一个内存对象
b.base is a # 返回True,b视图的根数据和a一样
b.flags.owndata # 返回False b中的数据不是其自己的
a.flags.owndata # 返回True a中的数据是其自己的
b[0,0] = 1024 # a和b的数据都发生改变
display(a,b)
输出:
array([[1024,   44,   95,   41,   63],
       [  20,   40,   67,    6,   26],
       [  48,   52,   79,   72,   24],
       [   5,    6,    0,   32,   95]], dtype=int32)
array([[1024,   44,   95,   41,   63],
       [  20,   40,   67,    6,   26],
       [  48,   52,   79,   72,   24],
       [   5,    6,    0,   32,   95]], dtype=int32)

深拷贝

import numpy as np
a = np.random.randint(0,100,size = (4,5))
b = a.copy()
b is a # 返回False
b.base is a # 返回False
b.flags.owndata # 返回True
a.flags.owndata # 返回True
b[0,0] = 1024 # b改变,a不变,分道扬镳
display(a,b)
输出:
array([[97, 44, 93, 94,  6],
       [68, 56, 98, 12, 90],
       [73, 10, 22, 79, 35],
       [75, 27, 32, 70, 83]], dtype=int32)
array([[1024, 44, 93, 94, 6],
       [  68, 56, 98, 12, 90],
       [  73, 10, 22, 79, 35],
       [  75, 27, 32, 70, 83]], dtype=int32)

  copy应该在不再需要原来的数组情况下,切片后调用。例如,假设a是一个巨大的中间结果,而最终结果b仅包含的一小部分a,则在b使用切片进行构造时应制作一个深拷贝:

import numpy as np 
a = np.arange(1e8) 
b = a[::1000000].copy() # 每100万个数据中取一个数据 
del a # 不在需要a,删除占大内存的a 
b.shape # shape(100,)

索引、切片和迭代

基本索引和切片

  numpy中数组切片是原始数组的视图,这意味着数据不会被复制,视图上任何数据的修改都会反映到原数组上。

arr = np.array([0,1,2,3,4,5,6,7,8,9])
arr[5] #索引 输出 5
arr[5:8] #切片输出:array([5, 6, 7])
arr[2::2] # 从索引2开始每两个中取一个 输出 array([2, 4, 6, 8])
arr[::3] # 不写索引默认从0开始,每3个中取一个 输出为 array([0, 3, 6, 9])
arr[1:7:2] # 从索引1开始到索引7结束,左闭右开,每2个数中取一个 输出 array([1, 3, 5])
arr[::-1] # 倒序 输出 array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
arr[::-2] # 倒序 每两个取一个 输出 array([9, 7, 5, 3, 1])
arr[5:8]=12 # 切片赋值会赋值到每个元素上,与列表操作不同
temp = arr[5:8]
temp[1] = 1024
arr # 输出:array([ 0, 1, 2, 3, 4, 12, 1024, 12, 8, 9])

  对于二维数组或者高维数组,我们可以按照之前的知识来索引,当然也可以传入一个以逗号隔开的索引列表来选区单个或多个元素。

arr2d = np.array([[1,3,5],[2,4,6],[-2,-7,-9],[6,6,6]]) # 二维数组 shape(3,4)
arr2d[0,-1] #索引 等于arr2d[0][-1] 输出 5
arr2d[0,2] #索引 等于arr2d[0][2] == arr2d[0][-1] 输出 5

arr2d[:2,-2:] #切片 第一维和第二维都进行切片 等于arr2d[:2][:,1:]
arr2d[:2,1:] #切片 1 == -2 一个是正序,另个一是倒序,对应相同的位置
# 输出:
#array([[3, 5],
#             [4, 6]])

花式索引和索引技巧

  整数数组进行索引即花式索引,其和切片不一样,它总是将数据复制到新数组中。

import numpy as np
#一维
arr1 = np.array([1,2,3,4,5,6,7,8,9,10])
arr2 = arr1[[1,3,3,5,7,7,7]] 
# 输出 array([2, 4, 4, 6, 8, 8, 8])
arr2[-1] = 1024 # 修改值,不影响arr1
#二维
arr2d = np.array([[1,3,5,7,9],[2,4,6,8,10],[12,18,22,23,37],[123,55,17,88,103]]) #shape(4,5)
arr2d[[1,3]] # 获取第二行和第四行,索引从0开始的所以1对应第二行
# 输出 array([[ 2, 4, 6, 8, 10],
#            [123, 55, 17, 88, 103]])
arr2d[([1,3],[2,4])] # 相当于arr2d[1,2]获取一个元素,arr2d[3,4]获取另一个元素
# 输出为 array([ 6, 103])
# 选择一个区域
arr2d[np.ix_([1,3,3,3],[2,4,4])] # 相当于 arr2d[[1,3,3,3]][:,[2,4,4]]
# ix_()函数可用于组合不同的向量
# 第一个列表存的是待提取元素的行标,第二个列表存的是待提取元素的列标
# 输出为
# array([[ 6, 10, 10],
#       [ 17, 103, 103],
#       [ 17, 103, 103],
#       [ 17, 103, 103]])

boolean值索引

names = np.array(['softpo','Brandon','Will','Michael','Will','Ella','Daniel','softpo','Will','Brandon'])
cond1 = names == 'Will'
cond1
# 输出array([False, False, True, False, True, False, False, False, True, False])
names[cond1] # array(['Will', 'Will', 'Will'], dtype='
arr = np.random.randint(0,100,size = (10,8)) # 0~100随机数
cond2 = arr > 90
# 找到所有大于90的索引,返回boolean类型的数组 shape(10,8),大于返回True,否则False
arr[cond2] # 返回数据全部是大于90的

形状操作

数组变形

import numpy as np
arr1 = np.random.randint(0,10,size = (3,4,5))
arr2 = arr1.reshape(12,5) # 形状改变,返回新数组
arr3 = arr1.reshape(-1,5) # 自动“整形”,自动计算

数组转置

import numpy as np
arr1 = np.random.randint(0,10,size = (3,5)) # shape(3,5)
arr1.T # shape(5,3) 转置
arr2 = np.random.randint(0,10,size = (3,6,4)) # shape(3,6,4)
np.transpose(arr2,axes=(2,0,1)) # transpose改变数组维度 shape(4,3,6)

数组堆叠

import numpy as np
arr1 = np.array([[1,2,3]])
arr2 = np.array([[4,5,6]])
np.concatenate([arr1,arr2],axis = 0)
# 串联合并shape(2,3) axis = 0表示第一维串联 输出为
# array([[1, 2, 3],
#       [4, 5, 6]])
np.concatenate([arr1,arr2],axis = 1)
# shape(1,6) axis = 1表示第二维串联 输出为:array([[1, 2, 3, 4, 5, 6]])
np.hstack((arr1,arr2)) 
# 水平方向堆叠 输出为:array([[1, 2, 3, 4, 5, 6]])
np.vstack((arr1,arr2))
# 竖直方向堆叠,输出为:
# array([[1, 2, 3],
#       [4, 5, 6]])

split数组拆分

import numpy as np
arr = np.random.randint(0,10,size = (6,5)) 
# shape(6,5)
np.split(arr,indices_or_sections=2,axis = 0) 
# 在第一维(6)平均分成两份
np.split(arr,indices_or_sections=[2,3],axis = 1) 
# 在第二维(5)以索引2,3为断点分割成3份
np.vsplit(arr,indices_or_sections=3) 
# 在竖直方向平均分割成3份
np.hsplit(arr,indices_or_sections=[1,4]) 
# 在水平方向,以索引1,4为断点分割成3

更多内容主页获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值