大家好,欢迎来到IT知识分享网。
Task01学习思维导图
注:为了节约行数,默认import numpy as np已经写在每段代码前,不再重复写入,如果有新的包引入,会在代码头部import
一、常量
前言:
1、正无穷大
numpy中正无穷大一共有五种表现形式:Inf = inf = infty = Infinity = PINF
【例一、1】判断Inf 、inf 、infty、Infinity、PINF的关系
print(np.Inf == np.inf) print(np.inf == np.infty) print(np.infty == np.Infinity) print(np.Infinity == np.PINF)
结果:
2、负无穷大
【例一、2】打印负无穷大
print(np.NINF)
结果:
-inf
3、正负零
【例一、3】打印正负零
正负零被认为是有限数
print(np.PZERO) print(np.NZERO)
结果:
4、非数值
非数值有三种表现形式:nan、NaN、NAN
Not a Number不等于无穷大。
【例一、4-1】判断两个非数值是否相等
#两个nan是不等的 print(np.nan == np.nan) print(np.NAN == np.NAN) print(np.NaN == np.NaN)
结果:
表示两个非数值是不相等的
【例一、4-2】判断nan、NaN、NAN的关系
#比较不同的NAN print(np.nan == np.NAN) print(np.nan == np.NaN) print(np.NAN == np.NaN)
结果:
表示不同形式的非数值常量不等
【例一、4-3】计算ndarray中非数值常量(nan)的数量
#打印array x = np.array([1.2, 5, np.nan , True , False]) print(x) #打印是否为nan y = np.isnan(x) print(y) #数不是0的数量 print(np.count_nonzero(y)) #那么可以用一个函数计算array中nan的数量 def countNaN(array): return np.count_nonzero(np.isnan(array)) print(countNaN(x)) z = np.array([NaN, 5, nan , NAN , False]) print(countNaN(z))
结果:
这里自定义了一个countNaN函数,先调用numpy的isnan方法,返回包含布尔变量的ndarray,然后继续使用numpy的count_nonzero方法,返回不是0(即False)的数量。
综上,countNaN函数返回的即是ndarray中nan的数量。
5、自然数e
【例一、5-1】打印自然数e
print(np.e)
结果:
2.9045
【例一、5-2】判断numpy中自然数e的有效位数
print(np.e == 2.9045) print(np.e == 2.874)
结果:
突发奇想,想看一下np.e和打印的浮点数是否相等,结果发现无论是小数点后15位和小数点后25位,均判断相等,这里先抛出一个疑问。
6、圆周率π
【例一、6】打印圆周率π
print(np.pi)
结果:
3.9793
7、伽马常数γ
【一、例7】伽马常数γ
print(np.euler_gamma)
结果:
0.15329
8、None(newaxis)
numpy.newaxis从字面上来理解就是用来创建新轴的,或者说是用来对array进行维度扩展的。
【例一、8-1】判断None和newaxis的关系
print(None == np.newaxis)
结果:
True
表示None和np.newaxis实际是一个常量,axis有轴的意思,我们可以通过几个例子看看为什么在numpy中引入newaxis常数:
【例一、8-2】newaxis的用法
>>>x = np.array([1, 0, 1, 9]) >>>print(x.shape) #表示x是一维的ndarray变量 (4,) >>>x1 = x[np.newaxis,:] >>>print(x1) >>>print(x1.shape) #表示x1是二维的ndarray变量 1*4 [[1 0 1 9]] (1, 4) >>>x2 = x[np.newaxis,:] >>>print(x2) >>>print(x2.shape) >#表示x2是二维的ndarray变量 4*1 [[1] [0] [1] [9]] (4, 1)
到这里我们可以清楚,np.newaxis的作用就是给ndarray增加维度,放在前面就是在前面添加维度(把之前的一维变量提炼成新的二维变量中),放在后面就是在后面添加维度(把之前的一维变量打散,充当二维变量中的一维变量)
二、数据类型
前言
numpy 支持的数据类型比 Python 内置的类型要多很多,基本上可以和 C 语言的数据类型对应上,其中部分类型对应为 Python 内置的类型。下表列举了常用 NumPy 基本类型。为了区别于 Python 原生的数据类型,bool、int、float、complex、str 等类型名称末尾都加了 “_”:
1、常见数据类型
1)整型:
类型 | 备注 | 说明 | 字符代码 |
---|---|---|---|
int8 = byte | 8位 | 整型 | ‘i1’ |
int16 = short | 16位 | 整型 | ‘i2’ |
int32 = intc | 32位 | 整型 | ‘i4’ |
int_ = int64 = long = int0 = intp | 64位 | 整型 | ‘i8’ |
2)无符号整型:
类型 | 备注 | 说明 | 字符代码 |
---|---|---|---|
uint8 = ubyte | 8位 | 无符号整型 | ‘u1’ |
uint16 = ushort | 16位 | 无符号整型 | ‘u2’ |
uint32 = uintc | 32位 | 无符号整型 | ‘u4’ |
uint64 = uintp = uint0 = uint | 64位 | 无符号整型 | ‘u8’ |
3)浮点型:
类型 | 备注 | 说明 | 字符代码 |
---|---|---|---|
float16 = half | 16位 | 浮点型 | ‘f2’ |
float32 = single | 32位 | 浮点型 | ‘f4’ |
float_ = float64 = double | 64位 | 浮点型 | ‘f8’ |
4)其他类型:
类型 | 备注 | 说明 | 字符代码 |
---|---|---|---|
bool_ = bool8 | 8位 | 布尔类型 | ‘b1’ |
str_ = unicode_ = str0 = unicode | Unicode 字符串 | ‘U’ | |
datetime64 | 日期时间类型 | ‘M’ | |
timedelta64 | 表示两个时间之间的间隔 | ‘m’ |
2、创建数据类型
#dtype源码 class dtype(object): def __init__(self, obj, align=False, copy=False): pass
【例二、2】创建不同数据类型
在这里,我们新建一个函数genDtype,用来生成查看不同数据类型,然后集中测试:
def genDtype(str): a = np.dtype(str) print(a.type) # <class 'numpy.bool_'> print(a.itemsize) #集中测试 strList = ['b1','i1','i2','i4','i8','u1','u2','u4','u8','f2','f4','f8','S','S3','U3'] for x in strList: genDtype(x)
我们注意到这里itemsize的单位是字节,值得注意的是类型为’S’的dtype大小为0,而’S3’大小为3,另外’U’的单个大小为4字节,即32位。
3、数据类型信息
Python 的浮点数通常是64位浮点数,几乎等同于 np.float64。
NumPy和Python整数类型的行为在整数溢出方面存在显着差异,与 NumPy 不同,Python 的int 是灵活的。这意味着Python整数可以扩展以容纳任何整数并且不会溢出,这就是说numpy是有长度显示的,那么我们来看一下不同数据类型的显示范围。
#iinfo定义源码 class iinfo(object): def __init__(self, int_type): pass def min(self): pass def max(self): pass
可以看到iinfo类的初始化参数里面有一个int_type,是提供给调用者使用。
【例二、3-1】查看int16和int32的范围
ii16 = np.iinfo(np.int16) print(ii16.min) print(ii16.max) ii32 = np.iinfo(np.int32) print(ii32.min) print(ii32.max)
结果显示:
同理,浮点数在numpy中也有范围限制,先看定义:
#finfo定义源码 class finfo(object): def _init(self, dtype):
【例二、3-2】查看float16和float32的范围
ff16 = np.finfo(np.float16) print(ff16.bits) print(ff16.min) print(ff16.max) print(ff16.eps) ff32 = np.finfo(np.float32) print(ff32.bits) print(ff32.min) print(ff32.max) print(ff32.eps)
其中,eps是一个很小的非负数,除法的分母不能为0的,不然会直接跳出显示错误。使用eps将可能出现的零用eps来替换,这样不会报错。
三、时间日期和时间增量
引言
本章我们学习Numpy数据类型的时间日期(datetime64)和时间增量(timedelta64)
在 numpy 中,我们很方便的将字符串转换成时间日期类型 datetime64
(datetime
已被 python 包含的日期时间库所占用)。
datatime64
是带单位的日期时间类型,其单位如下:
日期单位 | 代码含义 | 时间单位 | 代码含义 |
---|---|---|---|
Y | 年 | h | 小时 |
M | 月 | m | 分钟 |
W | 周 | s | 秒 |
D | 天 | ms | 毫秒 |
– | – | us | 微秒 |
– | – | ns | 纳秒 |
– | – | ps | 皮秒 |
– | – | fs | 飞秒 |
– | – | as | 阿托秒 |
秒、毫秒、微bai秒、纳秒、皮秒、飞秒、阿托秒每两级之du间的换算进率为1000。
其中1阿托秒等于光飞越3粒氢阿子的时间。
比例上,一阿托秒之于一秒,如同一秒之于 317.1 亿年,约为宇宙年龄的两倍。
1、datetime64的使用:
【例三、1-1】datetime64的使用 自动选择对应单位
>>>a = np.datetime64('2020-10') >>>print(a,a.dtype) 2020-10 datetime64[M] >>>b = np.datetime64('2020-10-20') >>>print(b,b.dtype) 2020-10-20 datetime64[D] >>>c = np.datetime64('2020-10-20 19') >>>print(c,c.dtype) 2020-10-20T19 datetime64[h] >>>d = np.datetime64('2020-10-20 19:37') >>>print(d,d.dtype) 2020-10-20T19:37 datetime64[m] >>>e = np.datetime64('2020-10-20 19:37:21') >>>print(e,e.dtype) 2020-10-20T19:37:21 datetime64[s] ...
【例三、1-2】datetime64的使用 指定使用的单位
在这里,只用一个例子说明:
>>>a = np.datetime64('2020-10', 'D') >>>print(a) 2020-10-01
我们再来判断一下‘2020-10’和‘2020-10-01’的关系:
>>>print(np.datetime64('2020-10') == np.datetime64('2020-10-01')) True
【例三、1-3】字符串创建日期时间数组(详尽效应)
>>>a = np.array(['2020-10', '2020-10-20', '2020-10-20 20:00'], dtype='datetime64') >>>print(a) >>>print(a.dtype) ['2020-10-01T00:00' '2020-10-20T00:00' '2020-10-20T20:00'] datetime64[m]
可以看到,这里如果list中单位不统一,则统一用最详尽的方式表示日期(详尽效应)。
【例三、1-4】配合 arange 函数使用
配合arrange函数,用于生成日期范围
>>>a = np.arange('2020-10', '2020-11', dtype='datetime64[D]') >>>print(a) ['2020-10-01' '2020-10-02' '2020-10-03' '2020-10-04' '2020-10-05' '2020-10-06' '2020-10-07' '2020-10-08' '2020-10-09' '2020-10-10' '2020-10-11' '2020-10-12' '2020-10-13' '2020-10-14' '2020-10-15' '2020-10-16' '2020-10-17' '2020-10-18' '2020-10-19' '2020-10-20' '2020-10-21' '2020-10-22' '2020-10-23' '2020-10-24' '2020-10-25' '2020-10-26' '2020-10-27' '2020-10-28' '2020-10-29' '2020-10-30' '2020-10-31']
同理,年-年,月-月…的用法相同,不再赘述
另外,这种方式也满足详尽效应,例如:
>>>a = np.arange('2020-10-01 20', '2020-10-03', dtype='datetime64') >>>print(a) ['2020-10-01T20' '2020-10-01T21' '2020-10-01T22' '2020-10-01T23' '2020-10-02T00' '2020-10-02T01' '2020-10-02T02' '2020-10-02T03' '2020-10-02T04' '2020-10-02T05' '2020-10-02T06' '2020-10-02T07' '2020-10-02T08' '2020-10-02T09' '2020-10-02T10' '2020-10-02T11' '2020-10-02T12' '2020-10-02T13' '2020-10-02T14' '2020-10-02T15' '2020-10-02T16' '2020-10-02T17' '2020-10-02T18' '2020-10-02T19' '2020-10-02T20' '2020-10-02T21' '2020-10-02T22' '2020-10-02T23']
上述代码,h和D的datetime64变量,仍然取h进行展开
【例三、1-5】有趣的起始日期
>>>a = np.datetime64('2020-10-20', 'W') >>>b = np.datetime64('2020-10-22', 'W') >>>print(a, b) 2020-10-15 2020-10-22
跟【例三、1-2】不同的是,当用’W’去指定D类型的datetime64变量时,有如下规定:
2、关于Datetime64的运算
【例三、2-1】Datetime64 和 timedelta64 运算
timedelta64 表示两个 Datetime64 之间的差。timedelta64 也是带单位的,并且和相减运算中的两个 Datetime64 中的较小的单位保持一致。(详尽效应)
>>>a = np.datetime64('2020-10-20') - np.datetime64('2020-10-19') >>>b = np.datetime64('2020-10-20') - np.datetime64('2020-10-19 09:00') >>>c = np.datetime64('2020-10-20') - np.datetime64('2020-10-18 23:00', 'D') >>>print(a, a.dtype) >>>print(b, b.dtype) >>>print(c, c.dtype) 1 days timedelta64[D] 900 minutes timedelta64[m] 2 days timedelta64[D]
第三行同【例三、1-2】,’D’限制了天数之后的展示
下面是Datetime64 和 Timedelta64 运算:
>>>a = np.datetime64('2020-10') + np.timedelta64(20, 'D') >>>print(a,a.dtype) 2020-10-21 datetime64[D]
【例三、2-2】timedelta64 单独运算
#单独生成timedelta64 >>>a = np.timedelta64(1, 'Y') # 方式一 >>>b = np.timedelta64(a, 'M') # 方式二 >>>print(a) >>>print(b) 1 years 12 months #timedelta64加减乘除 >>>a = np.timedelta64(2, 'Y') >>>b = np.timedelta64(5, 'M') >>>print(a + b) >>>print(a - b) >>>print(2 * a) >>>print(a / b) 29 months 19 months 4 years 4.8
年(‘Y’)和月(‘M’)这两个单位是经过特殊处理的,它们无法和其他单位进行运算,一年有几天?一个月有几天?这些都是不确定的,比如:
>>>a = np.timedelta64(1, 'M') >>>b = np.timedelta64(a, 'D') TypeError: Cannot cast NumPy timedelta64 scalar from metadata [M] to [D] according to the rule 'same_kind'
【例三、2-3】numpy.datetime64 与 datetime.datetime 相互转换
datetime 模块是python中提供用于处理日期和时间的类。
在支持日期时间数学运算的同时,实现的关注点更着重于如何能够更有效地解析其属性用于格式化输出和数据操作。
>>>import datetime >>>dt = datetime.datetime(2020, 10, 20) >>>dt64 = np.datetime64(dt, 'D') >>>print(dt64, dt64.dtype) >>>dt2 = dt64.astype(datetime.datetime) >>>print(dt2,type(dt2)) 2020-10-20 datetime64[D] 2020-10-20 <class 'datetime.date'>
可以看到,我们可以直接用np.datetime64(datetime,dtype)来实现从后者到前者的转换,另外,我们可以通过datetime64.astype(datetime.datetime)实现从前者到前者的转换
3、工作日功能
为了允许在只有一周中某些日子有效的上下文中使用日期时间,NumPy包含一组“busday”(工作日)功能。
将指定的偏移量(offsets)应用于工作日,单位天(‘D’),偏移量为正表示朝着日历向后的方向
【例三、3-1】返回指定日期是否是工作日
# 2020-10-20 星期二 >>>a = np.is_busday('2020-10-18') >>>b = np.is_busday('2020-10-20') >>>print(a) >>>print(b) False True
【例三、3-2】返回下n个工作日
# 2020-07-10 星期五 >>>a = np.busday_offset('2020-10-20', offsets=1) >>>print(a) # 2020-07-13 2020-10-21 >>>a = np.busday_offset('2020-10-20', offsets=2) >>>print(a) 2020-10-22 >>>a = np.busday_offset('2020-10-18', offsets=2) >>>print(a) ValueError: Non-business day date in busday_offset >>>a = np.busday_offset('2020-10-18', offsets=0, roll='forward') >>>b = np.busday_offset('2020-10-18', offsets=0, roll='backward') >>>print(a) >>>print(b) 2020-10-19 2020-10-16 >>>a = np.busday_offset('2020-10-18', offsets=1, roll='forward') >>>b = np.busday_offset('2020-10-18', offsets=1, roll='backward') >>>print(a) >>>print(b) 2020-10-20 2020-10-19
可以指定偏移量为 0 来获取当前日期向前或向后最近的工作日,当然,如果当前日期本身就是工作日,则直接返回当前日期。如果当前日期为非工作日,默认报错。可以指定 forward
或 backward
规则来避免报错。
(注:forward指的是日历向后,backward指的是日历向前,如果从字面意思容易弄混)
小技巧:第一步先判断当天是否有工作日,若是则进行偏移;若不是,则需要根据
【例三、3-3】统计一个 datetime64[D]
数组中的工作日天数。
# 2020-10-20 星期二 >>>begindates = np.datetime64('2020-10-20') >>>enddates = np.datetime64('2020-11-01') >>>a = np.arange(begindates, enddates, dtype='datetime64') >>>b = np.count_nonzero(np.is_busday(a)) >>>c = np.busday_count(begindates, enddates) >>>print(a) >>>print(b) >>>print(c) ['2020-10-20' '2020-10-21' '2020-10-22' '2020-10-23' '2020-10-24' '2020-10-25' '2020-10-26' '2020-10-27' '2020-10-28' '2020-10-29' '2020-10-30' '2020-10-31'] 9
a和b的组合效果等于c,都是在计算一段日期范围的工作日天数,且前闭后开
【例三、3-4】自定义周掩码值,即指定一周中哪些星期是工作日。
# 2020-10-20 星期二 >>>a = np.is_busday('2020-10-20', weekmask=[1, 0, 1, 0, 1, 0, 1]) >>>b = np.is_busday('2020-10-20', weekmask='0') >>>c = np.is_busday('2020-10-20', weekmask='Tue') >>>print(a) >>>print(b) >>>print(c) False True True
如上,weekmask一共有三种设置方式,这里需要注意的是系统默认与真实世界的日历一一对应,即1970-01-01为星期四,是不是很有趣呢?
四、数组的创建
引言
NumPy 中定义的最重要的对象是称为 ndarray 的 N 维数组类型,它是描述相同类型的元素集合。ndarray 中的每个元素都是数据类型对象(dtype)的对象。ndarray 中的每个元素在内存中使用相同大小的块
ndarray的含义是The N-dimensional array,意思就是N维数组
1. 依据现有数据来创建 ndarray
【例四、1-1】通过array()函数进行创建。
def array(p_object, dtype=None, copy=True, order='K', subok=False, ndmin=0):
【例1-1】通过array()函数进行创建
>>>datas = [x for x in range(5)] # 创建一维数组 >>>a = np.array(datas) >>>b = np.array(tuple(datas)) >>>print(a, type(a)) >>>print(b, type(b)) >>>print(a.shape,b.shape) [0 1 2 3 4] <class 'numpy.ndarray'> [0 1 2 3 4] <class 'numpy.ndarray'> (5,) (5,) # 创建二维数组 >>>c = np.array([a]*2) >>>print(c, type(c)) [[0 1 2 3 4] [0 1 2 3 4]] <class 'numpy.ndarray'> (2, 5)
【例四、1-2】通过asarray()函数进行创建
array()
和asarray()
都可以将结构数据转化为 ndarray,但是array()
和asarray()
主要区别就是当数据源是ndarray 时,array()
仍然会 copy 出一个副本,占用新的内存,但不改变 dtype 时 asarray()
不会。
如果改变dtype,例如int转成float,那么不用占用新的内存,即保持一致。
def asarray(a, dtype=None, order=None): return array(a, dtype, copy=False, order=order)
#`array()`和`asarray()`都可以将结构数据转化为 ndarray >>>x = [[1, 1, 1], [1, 1, 1], [1, 1, 1]] >>>y = np.array(x) >>>z = np.asarray(x) >>>#改变x的数据 >>>x[1][2] = 2 >>>print(x,type(x)) [[1, 1, 1], [1, 1, 2], [1, 1, 1]] <class 'list'> >>>print(y,type(y)) [[1 1 1] [1 1 1] [1 1 1]] <class 'numpy.ndarray'> >>>print(z,type(z)) [[1 1 1] [1 1 1] [1 1 1]] <class 'numpy.ndarray'>
#当数据源是ndarray时 >>>x = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]]) >>>y = np.array(x) >>>z = np.asarray(x) >>>w = np.asarray(x, dtype=np.int) >>>x[1][2] = 2 >>>print(x,type(x),x.dtype) [[1 1 1] [1 1 2] [1 1 1]] <class 'numpy.ndarray'> int32 >>>print(y,type(y),y.dtype) [[1 1 1] [1 1 1] [1 1 1]] <class 'numpy.ndarray'> int32 >>>print(z,type(z),z.dtype) [[1 1 1] [1 1 2] [1 1 1]] <class 'numpy.ndarray'> int32 >>>print(w,type(w),w.dtype) [[1 1 1] [1 1 2] [1 1 1]] <class 'numpy.ndarray'> int32
可见w随着x的变化而变化,而不是在一个新的内存中
#更改为较大的dtype时,其大小必须是array的最后一个axis的总大小(以字节为单位)的除数 >>>x = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]]) >>>print(x, x.dtype) [[1 1 1] [1 1 1] [1 1 1]] int32 >>>x.dtype = np.float # ValueError: When changing to a larger dtype, its size must be a divisor of the total size in bytes of the last axis of the array.
怎么理解上面的错误,很简单,画个图示意一下:
假设我们之前有4个int8,总共32个单位,那么新的dtype可以是int16,可以是int32,但是不能是int64,因为int64装完32之后还有空余。
【例四、1-3】通过fromfunction()函数进行创建
给函数绘图的时候可能会用到fromfunction()
,该函数可从函数中创建数组。
def fromfunction(function, shape, kwargs):
#通过在每个坐标上执行一个函数来构造数组 >>>def f(x, y): >>> return 10 * x + y >>>x = np.fromfunction(f, (5, 4), dtype=int) >>>print(x) [[ 0 1 2 3] [10 11 12 13] [20 21 22 23] [30 31 32 33] [40 41 42 43]]
2. 依据 ones 和 zeros 等填充方式
在机器学习任务中经常做的一件事就是初始化参数,需要用常数值或者随机值来创建一个固定大小的矩阵。
【例四、2-1】零数组
zeros()
函数:返回给定形状和类型的零数组。zeros_like()
函数:返回与给定数组形状和类型相同的零数组。
def zeros(shape, dtype=None, order='C'): def zeros_like(a, dtype=None, order='K', subok=True, shape=None):
>>>x = np.zeros(5) >>>print(x) # [0. 0. 0. 0. 0.] >>>x = np.zeros([2, 3]) >>>print(x) [[0. 0. 0.] [0. 0. 0.]] >>>x = np.array([[1, 2, 3], [4, 5, 6]]) >>>y = np.zeros_like(x) >>>print(y) [[0 0 0] [0 0 0]]
1数组的用法和零数组相同,不加赘述
【例四、2-2】空数组
empty()
函数:返回一个空数组,数组元素为随机数。empty_like
函数:返回与给定数组具有相同形状和类型的新数组。
def empty(shape, dtype=None, order='C'): def empty_like(prototype, dtype=None, order='K', subok=True, shape=None):
【例】
>>>x = np.empty(5) >>>print(x) [0. 0. 0. 0. 0.] >>>x = np.empty((3, 2)) >>>print(x) [[0. 0.] [0. 0.] [0. 0.]]
【例四、2-3】单位数组
eye()
函数:返回一个对角线上为1,其它地方为零的单位数组。identity()
函数:返回一个方的单位数组。
def eye(N, M=None, k=0, dtype=float, order='C'): def identity(n, dtype=None):
>>>x = np.eye(4) >>>print(x) [[1. 0. 0. 0.] [0. 1. 0. 0.] [0. 0. 1. 0.] [0. 0. 0. 1.]] >>>x = np.eye(2, 3) >>>print(x) [[1. 0. 0.] [0. 1. 0.]] >>>x = np.identity(4) >>>print(x) [[1. 0. 0. 0.] [0. 1. 0. 0.] [0. 0. 1. 0.] [0. 0. 0. 1.]]
【例四、2-4】对角数组
diag()
函数:提取对角线或构造对角数组。
def diag(v, k=0):
>>>x = np.arange(9).reshape((3, 3)) >>>print(x) [[0 1 2] [3 4 5] [6 7 8]] >>>print(np.diag(x)) # [0 4 8] >>>print(np.diag(x, k=1)) # [1 5] >>>print(np.diag(x, k=-1)) # [3 7] >>>v = [1, 3, 5, 7] >>>x = np.diag(v) >>>print(x) [[1 0 0 0] [0 3 0 0] [0 0 5 0] [0 0 0 7]]
注:当参数是ndarray时,表示提取对角线;参数是list时,表示构建对角数组
【例四、2-5】常数数组
full()
函数:返回一个常数数组。full_like()
函数:返回与给定数组具有相同形状和类型的常数数组。
def full(shape, fill_value, dtype=None, order='C'): def full_like(a, fill_value, dtype=None, order='K', subok=True, shape=None):
#利用shape+value >>>x = np.full((2,), 7) >>>print(x) [7 7] #上述的变形 >>>x = np.full(2, 7) >>>print(x) [7 7] #shape是二维 >>>x = np.full((2, 7), 7) >>>print(x) [[7 7 7 7 7 7 7] [7 7 7 7 7 7 7]] >>>x = np.array([[1, 2, 3], [4, 5, 6]]) >>>y = np.full_like(x, 7) >>>print(y) [[7 7 7] [7 7 7]]
3. 利用数值范围来创建ndarray
arange()
函数:返回给定间隔内的均匀间隔的值。linspace()
函数:返回指定间隔内的等间隔数字。logspace()
函数:返回数以对数刻度均匀分布。numpy.random.rand()
返回一个由[0,1)内的随机数组成的数组。
def arange([start,] stop[, step,], dtype=None): def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0): def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=0): def rand(d0, d1, ..., dn):
【例四、3】利用数值范围来创建ndarray实例
>>>x = np.arange(5) >>>print(x) [0 1 2 3 4] # 3到7 步长为2 左闭右开 >>>x = np.arange(3, 7, 2) >>>print(x) [3 5] >>>x = np.linspace(start=0, stop=2, num=9) >>>print(x) [0. 0.25 0.5 0.75 1. 1.25 1.5 1.75 2. ] #其实就是求log以10为底y = x,x是0到1的分散数,求y的过程 >>>x = np.logspace(0, 1, 5) >>>print(np.around(x, 2)) [ 1. 1.78 3.16 5.62 10. ] #其实就是logspace(0,1,5)的过程 >>>x = np.linspace(start=0, stop=1, num=5) >>>x = [10 i for i in x] >>>print(np.around(x, 2)) [ 1. 1.78 3.16 5.62 10. ] >>>x = np.random.random(5) >>>print(x) [0.0 0. 0. 0. 0.]
4. 结构数组的创建
结构数组,首先需要定义结构,然后利用np.array()
来创建数组,其参数dtype
为定义的结构。
【例四、4-1】利用包含多个元组的列表来定义结构
>>>studentType = np.dtype([('name', 'U20'), ('age', 'i1'), ('class', 'i1')]) >>>print(studentType) [('name', '<U20'), ('age', 'i1'), ('class', 'i1')] >>>a = np.array([('ZhangSan', 25, 5), ('LiSi', 25, 6), ('WangWu', 24, 7)], dtype=studentType) >>>print(a, type(a)) [('ZhangSan', 25, 5) ('LiSi', 25, 6) ('WangWu', 24, 7)] <class 'numpy.ndarray'>
【例四、4-2】利用字典来定义结构
只需将
{ 'names': ['name', 'age', 'weight'],'formats': ['U30', 'i8', 'f8']}
填入dtype中即可
# 结构数组的取值方式和一般数组差不多,可以通过下标取得元素: >>>print(a[0]) ('ZhangSan', 25, 5) >>>print(a[-1]) ('WangWu', 24, 7) # 我们可以使用字段名作为下标获取对应的值 >>>print(a['name']) ['ZhangSan' 'LiSi' 'WangWu']
五、数组的属性
前言
在学过数组的创建之后,需要对数组进行进一步的了解,可以先从数组属性入手,Numpy中比较重要的数组属性如下:
属性 | 说明 |
---|---|
ndarray.ndim | 秩,即轴的数量或维度的数量 |
ndarray.shape | 数组的维度,对于矩阵,n 行 m 列 |
ndarray.size | 数组元素的总个数,相当于 .shape 中 n*m 的值 |
ndarray.dtype | ndarray 对象的元素类型 |
ndarray.itemsize | ndarray 对象中每个元素的大小,以字节为单位 |
ndarray.flags | ndarray 对象的内存信息 |
ndarray.real | ndarray 元素的实部(复数的实部) |
ndarray.imag | ndarray 元素的虚部(复数的虚部) |
ndarray.data | 包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。 |
接下来让我们分别介绍。
1.ndarray.ndim
【五、例1】返回数组的维数
>>>a = np.arange(18) >>>print(a) >>>print(a.ndim) [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17] 1 >>>b = a.reshape(2,3,3) >>>print(b) >>>print(b.ndim) [[[ 0 1 2] [ 3 4 5] [ 6 7 8]] [[ 9 10 11] [12 13 14] [15 16 17]]] 3 >>>print(a) [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17]
我们首先创建了一个1维Numpy数组a,数组元素有18个,通过ndarray.ndim属性可以查看数组a的维数是1。然后通过reshape方法生成数组b(注:此时数组a不被改变),然后打印数组b的维数为3。
2.ndarray.shape
【五、例2】返回数组的维度
>>>a = [x+1 for x in range(3)] >>>b = [x+3 for x in a] >>>c = np.array([a]+[b]) >>>print(c.shape,type(c.shape)) (2, 3) <class 'tuple'> #采用reshape方式 >>>d = c.reshape(3,2) >>>print(d,d.shape,type(d)) [[1 2] [3 4] [5 6]] <class 'numpy.ndarray'> #直接改shape >>>c.shape = (3,2) >>>print(c,d.shape,type(c)) [[1 2] [3 4] [5 6]] <class 'numpy.ndarray'>
可以看到shape属性可以返回数组的维度,在上述案例中,shape返回的是一个元组tuple。我们可以通过直接设置shape或者reshape改变一个数组的shape,请注意后者不直接改变原数组,而是生成一个新数组,如c生成了d,但是c本身没有变化,直到我们通过c.shape = (3,2)
改变了它。
3.ndarray.size
【五、例3】返回数组元素的总个数
>>>a = [x+1 for x in range(3)] >>>b = [x+3 for x in a] >>>def getSize(data): >>> return np.array(data).size >>>print(getSize(a),getSize(b),getSize([a]+[b])) 3 3 6
这里我们新建一个getSize函数,用来利用list新建ndarray数组并且返回其size。
4.ndarray.dtype
【五、例4】返回数组的元素类型
>>>x = np.arange(5, dtype = np.int8) >>>print(x.dtype) int8 >>>y = np.array(5, dtype = np.int16) >>>print(y.dtype) int16
这个在前面的数据类型里面有介绍,不加赘述。
5.ndarray.itemsize
【五、例5】返回数组中每一个元素的大小
>>>x = np.arange(5, dtype = np.int8) >>>print (x.itemsize) 1 >>>y = np.array(5, dtype = np.float64) >>>print (y.itemsize) 8
可以看到int8型数组元素大小为1字节,float64型数组元素大小为8字节。
6.ndarray.flags
属性 | 描述 |
---|---|
C_CONTIGUOUS © | 数据是在一个单一的C风格的连续段中 |
F_CONTIGUOUS (F) | 数据是在一个单一的Fortran风格的连续段中 |
OWNDATA (O) | 数组拥有它所使用的内存或从另一个对象中借用它 |
WRITEABLE (W) | 数据区域可以被写入,将该值设置为 False,则数据为只读 |
ALIGNED (A) | 数据和所有元素都适当地对齐到硬件上 |
UPDATEIFCOPY (U) | 这个数组是其它数组的一个副本,当这个数组被释放时,原数组的内容将被更新 |
【五、例6】返回数组的内存信息
>>>x = np.arange(5, dtype = np.int8) >>>print(x.flags) C_CONTIGUOUS : True F_CONTIGUOUS : True OWNDATA : True WRITEABLE : True ALIGNED : True WRITEBACKIFCOPY : False UPDATEIFCOPY : False
这里比较重要的是 flags.owndata
属性,它表示该数组是否拥有数据,会配合后面的深浅复制使用。
7.ndarray.real和ndarray.imag
【五、例7】返回数组的实部和虚部
>>>x = np.sqrt([1 + 0j, 2 + 1j]) >>>print(x.real) >>>print(x.imag) [1. 1.] [0. 0.]
np.sqrt是numpy提供的求平方根的方法,运算后我们利用real和imag提取的实部和虚部
8.ndarray.data
【五、例8】返回数组的缓冲区
>>>x = np.arange(5, dtype = np.int8) >>>print(x.data) <memory at 0x000001FF29FDA280>
由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。
六、练习
1.什么是numpy?
NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。
NumPy 的前身 Numeric 最早是由 Jim Hugunin 与其它协作者共同开发,2005 年,Travis Oliphant 在 Numeric 中结合了另一个同性质的程序库 Numarray 的特色,并加入了其它扩展而开发了 NumPy。NumPy 为开放源代码并且由许多协作者共同维护开发。
NumPy 是一个运行速度非常快的数学库,主要用于数组计算,包含:
- 一个强大的N维数组对象 ndarray
- 广播功能函数
- 整合 C/C++/Fortran 代码的工具
- 线性代数、傅里叶变换、随机数生成等功能
2.如何安装numpy?
以Windows10系统为例,可以通过PyCharm等IDE搭建Python环境,然后再安装numpy,即可运行,也可以先搭建Anaconda环境,然后再通过Anaconda去下载numpy包,然后即可切换环境后在终端运行:
Win10利用Anaconda搭建Numpy环境
3.什么是n维数组对象?
n维数组对象(ndarray)为numpy特有的一种数据类型,是一系列同类型数据的集合,以 0 下标为开始进行集合中元素的索引。
ndarray 对象是用于存放同类型元素的多维数组。
ndarray 中的每个元素在内存中都有相同存储大小的区域。
4.如何区分一维、二维、多维?
给定一个ndarray对象a,可以通过其a.ndim判断其维数,也可以通过len(b.shape)从维度间接判断
5.以下表达式运行的结果分别是什么?
(提示: NaN = not a number, inf = infinity)
0 * np.nan #nan
np.nan == np.nan #False
np.inf > np.nan #False
np.nan – np.nan #nan
0.3 == 3 * 0.1 #False
6.将numpy的datetime64对象转换为datetime的datetime对象。
>>>import datetime as datetime >>>dt64 = np.datetime64('2020-02-25 22:10:10') >>>x = dt64.astype(datetime.datetime) >>>print(x,type(x)) 2020-02-25 22:10:10 <class 'datetime.datetime'>
7.给定一系列不连续的日期序列。填充缺失的日期,使其成为连续的日期序列。
#求第一天和最后一天的日期差 >>>x = dates[-1]-dates[0] #生成一个一天的timedelta64 >>>incre = np.timedelta64(1, 'D') #计算要求的完整序列的长度 >>>num = int(x/incre) #生成完整日期List >>>result = [dates[0] + x*incre for x in range(num)] #List转成ndarray >>>totalDates = np.array(result) >>>print(totalDates) ['2020-02-01' '2020-02-02' '2020-02-03' '2020-02-04' '2020-02-05' '2020-02-06' '2020-02-07' '2020-02-08']
8.如何得到昨天,今天,明天的的日期
【知识点:时间日期】
(提示: np.datetime64, np.timedelta64)
>>>x = datetime.datetime.today() >>>today = np.datetime64(x,'D') >>>incre = np.timedelta64(1, 'D') >>>yesterday = today - incre >>>tomorrow = today + incre >>>print(yesterday,today,tomorrow) 2020-10-21 2020-10-22 2020-10-23
9.创建从0到9的一维数字数组。
【知识点:数组的创建】
如何创建一维数组?
>>>result = np.arange(10) >>>print(result) [0 1 2 3 4 5 6 7 8 9]
10.创建一个元素全为True的 3×3 数组。
【知识点:数组的创建】
如何创建一个布尔数组?
>>>result = np.array([[True]*3]*3) >>>print(result,result.shape) [[ True True True] [ True True True] [ True True True]] (3, 3)
11.创建一个长度为10并且除了第五个值为1的空向量
【知识点:数组的创建】
(提示: array[4])
>>>result = np.array([0]*10) >>>result[4] = 1 >>>print(result) [0 0 0 0 1 0 0 0 0 0]
12.创建一个值域范围从10到49的向量
【知识点:创建数组】
(提示: np.arange)
>>>result = np.arange(10,50) >>>print(result) [10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49]
13.创建一个 3x3x3的随机数组
【知识点:创建数组】
(提示: np.random.random)
>>>result = np.random.random([3,3,3]) >>>print(result) [[[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.]]]
14.创建一个二维数组,其中边界值为1,其余值为0
【知识点:二维数组的创建】
(提示: array[1:-1, 1:-1])
>>>result = np.ones([5,5]) >>>result[1:-1,1:-1] = 0 >>>print(result) [[1. 1. 1. 1. 1.] [1. 0. 0. 0. 1.] [1. 0. 0. 0. 1.] [1. 0. 0. 0. 1.] [1. 1. 1. 1. 1.]]
注:[5,5]换成(5,5)也可以实现。
15.创建长度为10的numpy数组,从5开始,在连续的数字之间的步长为3。
【知识点:数组的创建与属性】
如何在给定起始点、长度和步骤的情况下创建一个numpy数组序列?
>>>result = np.array([5+3*x for x in range(10)]) >>>print(result) [ 5 8 11 14 17 20 23 26 29 32]
16.将本地图像导入并将其转换为numpy数组。
【知识点:数组的创建与属性】
如何将图像转换为numpy数组?
>>>from PIL import Image >>>img = Image.open('ace0.jpg') >>>a = np.array(img) >>>print(a.shape,type(a)) (500, 500, 3) <class 'numpy.ndarray'>
至此,Task01全部结束,撒花完结
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/134032.html