NumPy之:ndarray多维数组操作(numpy库的ndarray数组属性)
off999 2024-11-06 11:23 15 浏览 0 评论
简介
NumPy一个非常重要的作用就是可以进行多维数组的操作,多维数组对象也叫做ndarray。我们可以在ndarray的基础上进行一系列复杂的数学运算。
本文将会介绍一些基本常见的ndarray操作,大家可以在数据分析中使用。
创建ndarray
创建ndarray有很多种方法,我们可以使用np.random来随机生成数据:
import numpy as np
# Generate some random data
data = np.random.randn(2, 3)
data
array([[ 0.0929, 0.2817, 0.769 ],
[ 1.2464, 1.0072, -1.2962]])
除了随机创建之外,还可以从list中创建:
data1 = [6, 7.5, 8, 0, 1]
arr1 = np.array(data1)
array([6. , 7.5, 8. , 0. , 1. ])
从list中创建多维数组:
data2 = [[1, 2, 3, 4], [5, 6, 7, 8]]
arr2 = np.array(data2)
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
使用np.zeros创建初始值为0的数组:
np.zeros(10)
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
创建2维数组:
np.zeros((3, 6))
array([[0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0.]])
使用empty创建3维数组:
np.empty((2, 3, 2))
array([[[0., 0.],
[0., 0.],
[0., 0.]],
[[0., 0.],
[0., 0.],
[0., 0.]]])
注意,这里我们看到empty创建的数组值为0,其实并不是一定的,empty会从内存中随机挑选空间来返回,并不能保证这些空间中没有值。所以我们在使用empty创建数组之后,在使用之前,还要记得初始化他们。
使用arange创建范围类的数组:
np.arange(15)
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
指定数组中元素的dtype:
arr1 = np.array([1, 2, 3], dtype=np.float64)
arr2 = np.array([1, 2, 3], dtype=np.int32)
ndarray的属性
可以通过data.shape获得数组的形状。
data.shape
(2, 3)
通过ndim获取维数信息:
arr2.ndim
2
可以通过data.dtype获得具体的数据类型。
data.dtype
dtype('float64')
ndarray中元素的类型转换
在创建好一个类型的ndarray之后,还可以对其进行转换:
arr = np.array([1, 2, 3, 4, 5])
arr.dtype
dtype('int64')
float_arr = arr.astype(np.float64)
float_arr.dtype
dtype('float64')
上面我们使用astype将int64类型的ndarray转换成了float64类型的。
如果转换类型的范围不匹配,则会自动进行截断操作:
arr = np.array([3.7, -1.2, -2.6, 0.5, 12.9, 10.1])
arr.astype(np.int32)
array([ 3, -1, -2, 0, 12, 10], dtype=int32)
注意,这里是把小数截断,并没有向上或者向下取整。
ndarray的数学运算
数组可以和常量进行运算,也可以和数组进行运算:
arr = np.array([[1., 2., 3.], [4., 5., 6.]])
arr * arr
array([[ 1., 4., 9.],
[16., 25., 36.]])
arr + 10
array([[11., 12., 13.],
[14., 15., 16.]])
arr - arr
array([[0., 0., 0.],
[0., 0., 0.]])
1 / arr
array([[1. , 0.5 , 0.3333],
[0.25 , 0.2 , 0.1667]])
arr ** 0.5
array([[1. , 1.4142, 1.7321],
[2. , 2.2361, 2.4495]])
数组之间还可以进行比较,比较的是数组中每个元素的大小:
arr2 = np.array([[0., 4., 1.], [7., 2., 12.]])
arr2 > arr
array([[False, True, False],
[ True, False, True]])
index和切片
基本使用
先看下index和切片的基本使用,index基本上和普通数组的使用方式是一样的,用来访问数组中某一个元素。
切片要注意的是切片后返回的数组中的元素是原数组中元素的引用,修改切片的数组会影响到原数组。
# 构建一维数组
arr = np.arange(10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# index访问
arr[5]
5
# 切片访问
arr[5:8]
array([5, 6, 7])
# 切片修改
arr[5:8] = 12
array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9])
# 切片可以修改原数组的值
arr_slice = arr[5:8]
arr_slice[1] = 12345
arr
array([ 0, 1, 2, 3, 4, 12, 12345, 12, 8,
9])
# 构建二维数组
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
arr2d[2]
array([7, 8, 9])
# index 二维数组
arr2d[0][2]
3
# index二维数组
arr2d[0, 2]
3
# 构建三维数组
arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
arr3d
array([[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]])
# index三维数组
arr3d[0]
array([[1, 2, 3],
[4, 5, 6]])
# copy是硬拷贝,和原数组的值相互不影响
old_values = arr3d[0].copy()
arr3d[0] = 42
arr3d
array([[[42, 42, 42],
[42, 42, 42]],
[[ 7, 8, 9],
[10, 11, 12]]])
arr3d[0] = old_values
arr3d
array([[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]])
# index 三维数组
arr3d[1, 0]
array([7, 8, 9])
x = arr3d[1]
x
array([[ 7, 8, 9],
[10, 11, 12]])
x[0]
array([7, 8, 9])
index with slice
slice还可以作为index使用,作为index使用表示的就是一个index范围值。
作为index表示的slice可以有多种形式。
有头有尾的,表示index从1开始到6-1结束:
arr[1:6]
array([ 1, 2, 3, 4, 64])
无头有尾的,表示index从0开始,到尾-1结束:
arr2d[:2]
array([[1, 2, 3],
[4, 5, 6]])
有头无尾的,表示从头开始,到所有的数据结束:
arr2d[:2, 1:]
array([[2, 3],
[5, 6]])
arr2d[1, :2]
array([4, 5])
boolean index
index还可以使用boolean值,表示是否选择这一个index的数据。
我们先看下怎么构建一个boolean类型的数组:
names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
names == 'Bob'
array([ True, False, False, True, False, False, False])
上面我们通过比较的方式返回了一个只包含True和False的数组。
这个数组可以作为index值来访问数组:
# 构建一个7 * 4 的数组
data = np.random.randn(7, 4)
array([[ 0.275 , 0.2289, 1.3529, 0.8864],
[-2.0016, -0.3718, 1.669 , -0.4386],
[-0.5397, 0.477 , 3.2489, -1.0212],
[-0.5771, 0.1241, 0.3026, 0.5238],
[ 0.0009, 1.3438, -0.7135, -0.8312],
[-2.3702, -1.8608, -0.8608, 0.5601],
[-1.2659, 0.1198, -1.0635, 0.3329]])
# 通过boolean数组来访问:
data[names == 'Bob']
array([[ 0.275 , 0.2289, 1.3529, 0.8864],
[-0.5771, 0.1241, 0.3026, 0.5238]])
在索引行的时候,还可以索引列:
data[names == 'Bob', 3]
array([0.8864, 0.5238])
可以用 ~符号来取反:
data[~(names == 'Bob')]
array([[-2.0016, -0.3718, 1.669 , -0.4386],
[-0.5397, 0.477 , 3.2489, -1.0212],
[ 0.0009, 1.3438, -0.7135, -0.8312],
[-2.3702, -1.8608, -0.8608, 0.5601],
[-1.2659, 0.1198, -1.0635, 0.3329]])
我们可以通过布尔型数组设置值,在实际的项目中非常有用:
data[data < 0] = 0
array([[0.275 , 0.2289, 1.3529, 0.8864],
[0. , 0. , 1.669 , 0. ],
[0. , 0.477 , 3.2489, 0. ],
[0. , 0.1241, 0.3026, 0.5238],
[0.0009, 1.3438, 0. , 0. ],
[0. , 0. , 0. , 0.5601],
[0. , 0.1198, 0. , 0.3329]])
data[names != 'Joe'] = 7
array([[7. , 7. , 7. , 7. ],
[0. , 0. , 1.669 , 0. ],
[7. , 7. , 7. , 7. ],
[7. , 7. , 7. , 7. ],
[7. , 7. , 7. , 7. ],
[0. , 0. , 0. , 0.5601],
[0. , 0.1198, 0. , 0.3329]])
Fancy indexing
Fancy indexing也叫做花式索引,它是指使用一个整数数组来进行索引。
举个例子,我们先创建一个 8 * 4的数组:
arr = np.empty((8, 4))
for i in range(8):
arr[i] = i
arr
array([[0., 0., 0., 0.],
[1., 1., 1., 1.],
[2., 2., 2., 2.],
[3., 3., 3., 3.],
[4., 4., 4., 4.],
[5., 5., 5., 5.],
[6., 6., 6., 6.],
[7., 7., 7., 7.]])
然后使用一个整数数组来索引,那么将会以指定的顺序来选择行:
arr[[4, 3, 0, 6]]
array([[4., 4., 4., 4.],
[3., 3., 3., 3.],
[0., 0., 0., 0.],
[6., 6., 6., 6.]])
还可以使用负值来索引:
arr[[-3, -5, -7]]
array([[5., 5., 5., 5.],
[3., 3., 3., 3.],
[1., 1., 1., 1.]])
花式索引还可以组合来使用:
arr = np.arange(32).reshape((8, 4))
arr
array([[ 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, 25, 26, 27],
[28, 29, 30, 31]])
上面我们构建了一个8 * 4的数组。
arr[[1, 5, 7, 2], [0, 3, 1, 2]]
array([ 4, 23, 29, 10])
然后取他们的第2列的第一个值,第6列的第三个值等等。最后得到一个1维的数组。
数组变换
我们可以在不同维度的数组之间进行变换,还可以转换数组的轴。
reshape方法可以将数组转换成为任意的形状:
arr = np.arange(15).reshape((3, 5))
arr
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
数组还提供了一个T命令,可以将数组的轴进行对调:
arr.T
array([[ 0, 5, 10],
[ 1, 6, 11],
[ 2, 7, 12],
[ 3, 8, 13],
[ 4, 9, 14]])
对于高维数组,可以使用transpose来进行轴的转置:
arr = np.arange(16).reshape((2, 2, 4))
arr
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15]]])
arr.transpose((1, 0, 2))
array([[[ 0, 1, 2, 3],
[ 8, 9, 10, 11]],
[[ 4, 5, 6, 7],
[12, 13, 14, 15]]])
上面的transpose((1, 0, 2)) 怎么理解呢?
其含义是将x,y轴对调,z轴保持不变。
上面我们通过使用reshape((2, 2, 4))方法创建了一个3维,也就是3个轴的数组。 其shape是 2 * 2 * 4 。
先看下对应关系:
(0,0)-》 [ 0, 1, 2, 3]
(0,1)-》 [ 4, 5, 6, 7]
(1,0)-》 [ 8, 9, 10, 11]
(1,1)-》 [12, 13, 14, 15]
转换之后:
(0,0)-》 [ 0, 1, 2, 3]
(0,1)-》 [ 8, 9, 10, 11]
(1,0)-》[ 4, 5, 6, 7]
(1,1)-》 [12, 13, 14, 15]
于是得到了我们上面的的结果。
多维数组的轴转换可能比较复杂,大家多多理解。
还可以使用 swapaxes 来交换两个轴,上面的例子可以重写为:
arr.swapaxes(0,1)
本文已收录于 http://www.flydean.com/09-python-numpy-ndarray/
最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!
相关推荐
- Python钩子函数实现事件驱动系统(created钩子函数)
-
钩子函数(HookFunction)是现代软件开发中一个重要的设计模式,它允许开发者在特定事件发生时自动执行预定义的代码。在Python生态系统中,钩子函数广泛应用于框架开发、插件系统、事件处理和中...
- Python函数(python函数题库及答案)
-
定义和基本内容def函数名(传入参数):函数体return返回值注意:参数、返回值如果不需要,可以省略。函数必须先定义后使用。参数之间使用逗号进行分割,传入的时候,按照顺序传入...
- Python技能:Pathlib面向对象操作路径,比os.path更现代!
-
在Python编程中,文件和目录的操作是日常中不可或缺的一部分。虽然,这么久以来,钢铁老豆也还是习惯性地使用os、shutil模块的函数式API,这两个模块虽然功能强大,但在某些情况下还是显得笨重,不...
- 使用Python实现智能物流系统优化与路径规划
-
阅读文章前辛苦您点下“关注”,方便讨论和分享,为了回馈您的支持,我将每日更新优质内容。在现代物流系统中,优化运输路径和提高配送效率是至关重要的。本文将介绍如何使用Python实现智能物流系统的优化与路...
- Python if 语句的系统化学习路径(python里的if语句案例)
-
以下是针对Pythonif语句的系统化学习路径,从零基础到灵活应用分为4个阶段,包含具体练习项目和避坑指南:一、基础认知阶段(1-2天)目标:理解条件判断的逻辑本质核心语法结构if条件:...
- [Python] FastAPI基础:Path路径参数用法解析与实例
-
查询query参数(上一篇)路径path参数(本篇)请求体body参数(下一篇)请求头header参数本篇项目目录结构:1.路径参数路径参数是URL地址的一部分,是必填的。路径参...
- Python小案例55- os模块执行文件路径
-
在Python中,我们可以使用os模块来执行文件路径操作。os模块提供了许多函数,用于处理文件和目录路径。获取当前工作目录(CurrentWorkingDirectory,CWD):使用os....
- python:os.path - 常用路径操作模块
-
应该是所有程序都需要用到的路径操作,不废话,直接开始以下是常用总结,当你想做路径相关时,首先应该想到的是这个模块,并知道这个模块有哪些主要功能,获取、分割、拼接、判断、获取文件属性。1、路径获取2、路...
- 原来如此:Python居然有6种模块路径搜索方式
-
点赞、收藏、加关注,下次找我不迷路当我们使用import语句导入模块时,Python是怎么找到这些模块的呢?今天我就带大家深入了解Python的6种模块路径搜索方式。一、Python模块...
- 每天10分钟,python进阶(25)(python进阶视频)
-
首先明确学习目标,今天的目标是继续python中实例开发项目--飞机大战今天任务进行面向对象版的飞机大战开发--游戏代码整编目标:完善整串代码,提供完整游戏代码历时25天,首先要看成品,坚持才有收获i...
- python 打地鼠小游戏(打地鼠python程序设计说明)
-
给大家分享一段AI自动生成的代码(在这个游戏中,玩家需要在有限时间内打中尽可能多的出现在地图上的地鼠),由于我现在用的这个电脑没有安装sublime或pycharm等工具,所以还没有测试,有兴趣的朋友...
- python线程之十:线程 threading 最终总结
-
小伙伴们,到今天threading模块彻底讲完。现在全面总结threading模块1、threading模块有自己的方法详细点击【threading模块的方法】threading模块:较低级...
- Python信号处理实战:使用signal模块响应系统事件
-
信号是操作系统用来通知进程发生了某个事件的一种异步通信方式。在Python中,标准库的signal模块提供了处理这些系统信号的机制。信号通常由外部事件触发,例如用户按下Ctrl+C、子进程终止或系统资...
- Python多线程:让程序 “多线作战” 的秘密武器
-
一、什么是多线程?在日常生活中,我们可以一边听音乐一边浏览新闻,这就是“多任务处理”。在Python编程里,多线程同样允许程序同时执行多个任务,从而提升程序的执行效率和响应速度。不过,Python...
- 用python写游戏之200行代码写个数字华容道
-
今天来分析一个益智游戏,数字华容道。当初对这个游戏颇有印象还是在最强大脑节目上面,何猷君以几十秒就完成了这个游戏。前几天写2048的时候,又想起了这个游戏,想着来研究一下。游戏玩法用尽量少的步数,尽量...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python自定义函数 (53)
- python进度条 (67)
- python吧 (67)
- python字典遍历 (54)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python串口编程 (60)
- python读取文件夹下所有文件 (59)
- java调用python脚本 (56)
- python操作mysql数据库 (66)
- python字典增加键值对 (53)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python人脸识别 (54)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)