0%

第一章 数据类型及数组创建

常量

numpy.nan

  • 表示空值。

nan = NaN = NAN

两个numpy.nan是不相等的。

1
2
import numpy as np 
print(np.nan == np.nan) #False
  • numpy.isnan(x, args, *kwargs)
1
2
3
4
5
6
7
8
9
import numpy as np 
x = np.array([1, 2, nan, 4])
print(x) #[1, 2, nan, 4]

y = np.isnan(x)
print(y) #[False False False True False]

z = np.cout_nonzero(y)
print(z) # 1 True == 1, False == 0

numpy.inf

  • 表示正无穷大。

Inf = inf = infty = Infinity = PINF

numpy.pi

  • 表示圆周率
1
pi = 3.1415926535897932384626433...

numpy.e

  • 表示自然常数
1
e = 2.71828182845904523536028747135266249775724709369995...

数据类型

常见数据类型

类型 备注 说明
bool_ = bool8 8位 布尔类型
int8 = byte 8位 整型
int16 = short 16位 整型
int32 = intc 32位 整型
int_ = int64 = long = int0 = intp 64位 整型
uint8 = ubyte 8位 无符号整型
uint16 = ushort 16位 无符号整型
uint32 = uintc 32位 无符号整型
uint64 = uintp = uint0 = uint 64位 无符号整型
float16 = half 16位 浮点型
float32 = single 32位 浮点型
float_ = float64 = double 64位 浮点型
str_ = unicode_ = str0 = unicode \ Unicode 字符串
datetime64 \ 日期时间类型
timedelta64 \ 表示两个时间之间的间隔

创建数据类型

numpy的数值类型实际上是dtype对象的实例。

1
2
3
class dtype(object):
def __init__(self, obj, align=False, copy=False):
pass

每个内建类型都有一个唯一定义它的字符代码,如下:

字符 对应类型 备注
b boolean ‘b1’
i signed integer ‘i1’, ‘i2’, ‘i4’, ‘i8’
u unsigned integer ‘u1’, ‘u2’ ,’u4’ ,’u8’
f floating-point ‘f2’, ‘f4’, ‘f8’
c complex floating-point
m timedelta64 表示两个时间之间的间隔
M datetime64 日期时间类型
O object
S (byte-)string S3表示长度为3的字符串
U Unicode Unicode 字符串
V void

例:

1
2
import numpy as np
a = np.dtype('b1')

数据类型信息

Python 的浮点数通常是64位浮点数,几乎等同于 np.float64

NumPy和Python整数类型的行为在整数溢出方面存在显着差异,与 NumPy 不同,Python 的int 是灵活的。这意味着Python整数可以扩展以容纳任何整数并且不会溢出。

1
2
3
4
5
6
7
class iinfo(object):
def __init__(self, int_type):
pass
def min(self):
pass
def max(self):
pass
1
2
class finfo(object):
def _init(self, dtype):

时间日期和时间增量

datetime64基础

在 numpy 中,我们很方便的将字符串转换成时间日期类型 datetime64datetime 已被 python 包含的日期时间库所占用)。

datatime64是带单位的日期时间类型,其单位如下:

日期单位 代码含义 时间单位 代码含义
Y h 小时
M m 分钟
W s
D ms 毫秒
- - us 微秒
- - ns 纳秒
- - ps 皮秒
- - fs 飞秒
- - as 阿托秒

例:从字符串创建 datetime64 类型时,默认情况下,numpy 会根据字符串自动选择对应的单位。

1
2
a = np.datetime64('2020-03-08 20:00:05')
print(a, a.dtype) # 2020-03-08T20:00:05 datetime64[s]

例:从字符串创建 datetime64 类型时,可以强制指定使用的单位。

1
2
3
4
5
6
7
8
9
10
import numpy as np

a = np.datetime64('2020-03', 'D')
print(a, a.dtype) # 2020-03-01 datetime64[D]

a = np.datetime64('2020-03', 'Y')
print(a, a.dtype) # 2020 datetime64[Y]

print(np.datetime64('2020-03') == np.datetime64('2020-03-01')) # True
print(np.datetime64('2020-03') == np.datetime64('2020-03-02')) #False

由上例可以看出,2019-03 和 2019-03-01 所表示的其实是同一个时间。 事实上,如果两个 datetime64 对象具有不同的单位,它们可能仍然代表相同的时刻。并且从较大的单位(如月份)转换为较小的单位(如天数)是安全的。

例:从字符串创建 datetime64 数组时,如果单位不统一,则一律转化成其中最小的单位。

1
2
3
4
5
import numpy as np

a = np.array(['2020-03', '2020-03-08', '2020-03-08 20:00'], dtype='datetime64')
print(a, a.dtype)
# ['2020-03-01T00:00' '2020-03-08T00:00' '2020-03-08T20:00'] datetime64[m]

例:使用arange()创建 datetime64 数组,用于生成日期范围。

1
2
3
4
5
6
7
import numpy as np

a = np.arange('2020-08-01', '2020-08-10', dtype=np.datetime64)
print(a)
# ['2020-08-01' '2020-08-02' '2020-08-03' '2020-08-04' '2020-08-05'
# '2020-08-06' '2020-08-07' '2020-08-08' '2020-08-09']
print(a.dtype) # datetime64[D]

datetime64和timedelta64运算

例:timedelta64 表示两个 datetime64 之间的差。timedelta64 也是带单位的,并且和相减运算中的两个 datetime64 中的较小的单位保持一致。

1
2
3
4
5
6
import numpy as np

a = np.datetime64('2020-03') + np.timedelta64(20, 'D')
b = np.datetime64('2020-06-15 00:00') + np.timedelta64(12, 'h')
print(a, a.dtype) # 2020-03-21 datetime64[D]
print(b, b.dtype) # 2020-06-15T12:00 datetime64[m]

生成 timedelta64时,要注意年(’Y’)和月(’M’)这两个单位无法和其它单位进行运算(一年有几天?一个月有几个小时?这些都是不确定的)。

例:numpy.datetime64 与 datetime.datetime 相互转换

1
2
3
4
5
6
7
8
9
10
11
import numpy as np
import datetime

dt = datetime.datetime(year=2020, month=6, day=1, hour=20, minute=5, second=30)
dt64 = np.datetime64(dt, 's')
print(dt64, dt64.dtype)
# 2020-06-01T20:05:30 datetime64[s]

dt2 = dt64.astype(datetime.datetime)
print(dt2, type(dt2))
# 2020-06-01 20:05:30 <class 'datetime.datetime'>

datetime64的应用

  • numpy.busday_offset(dates, offsets, roll=’raise’, weekmask=’1111100’, holidays=None, busdaycal=None, out=None)

    将指定的偏移量应用于工作日,单位天(’D’)。计算下一个工作日,如果当前日期为非工作日,默认报错。可以指定 forwardbackward 规则来避免报错。(一个是向前取第一个有效的工作日,一个是向后取第一个有效的工作日)

    可以指定偏移量为 0 来获取当前日期向前或向后最近的工作日,当然,如果当前日期本身就是工作日,则直接返回当前日期。

  • numpy.is_busday(dates, weekmask=’1111100’, holidays=None, busdaycal=None, out=None)

例:自定义周掩码值,即指定一周中哪些星期是工作日。

1
2
3
4
5
# 2020-07-10 星期五
a = np.is_busday('2020-07-10', weekmask=[1, 1, 1, 1, 1, 0, 0])
b = np.is_busday('2020-07-10', weekmask=[1, 1, 1, 1, 0, 0, 1])
print(a) # True
print(b) # False

例:返回两个日期之间的工作日数量。

1
2
3
4
5
6
7
8
9
import numpy as np

# 2020-07-10 星期五
begindates = np.datetime64('2020-07-10')
enddates = np.datetime64('2020-07-20')
a = np.busday_count(begindates, enddates)
b = np.busday_count(enddates, begindates)
print(a) # 6
print(b) # -6

数组的创建

numpy 提供的最重要的数据结构是ndarray,它是 python 中list的扩展。

1. 依据现有数据来创建ndarray

(a)通过array()函数进行创建

1
def array(p_object, dtype=None, copy=True, order='K', subok=False, ndmin=0): 

例:

1
2
3
4
5
import numpy as np

d = np.array([[(1.5, 2, 3), (4, 5, 6)],
[(3, 2, 1), (4, 5, 6)]])
print(d, type(d))

(b)通过asarray()函数进行创建

array()asarray()都可以将结构数据转化为 ndarray,但是array()asarray()主要区别就是当数据源是ndarray 时,array()仍然会 copy 出一个副本,占用新的内存,但不改变 dtype 时 asarray()不会。

1
2
def asarray(a, dtype=None, order=None):
return array(a, dtype, copy=False, order=order)

(c)通过fromfunction()函数进行创建

给函数绘图的时候可能会用到fromfunction(),该函数可从函数中创建数组。

1
def fromfunction(function, shape, **kwargs):

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import numpy as np

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]]

x = np.fromfunction(lambda i, j: i == j, (3, 3), dtype=int)
print(x)
# [[ True False False]
# [False True False]
# [False False True]]

x = np.fromfunction(lambda i, j: i + j, (3, 3), dtype=int)
print(x)
# [[0 1 2]
# [1 2 3]
# [2 3 4]]

2. 依据ones和zeros填充方式

在机器学习任务中经常做的一件事就是初始化参数,需要用常数值或者随机值来创建一个固定大小的矩阵。

(a)零数组

  • zeros()函数:返回给定形状和类型的零数组。
  • zeros_like()函数:返回与给定数组形状和类型相同的零数组。
1
2
def zeros(shape, dtype=None, order='C'):
def zeros_like(a, dtype=None, order='K', subok=True, shape=None):

(b)1数组

  • ones()函数:返回给定形状和类型的1数组。
  • ones_like()函数:返回与给定数组形状和类型相同的1数组。
1
2
def ones(shape, dtype=None, order='C'):
def ones_like(a, dtype=None, order='K', subok=True, shape=None):

(c)空数组

  • empty()函数:返回一个空数组,数组元素为随机数。
  • empty_like函数:返回与给定数组具有相同形状和类型的新数组。
1
2
def empty(shape, dtype=None, order='C'): 
def empty_like(prototype, dtype=None, order='K', subok=True, shape=None):

(d)单位数组

  • eye()函数:返回一个对角线上为1,其它地方为零的单位数组。
  • identity()函数:返回一个方的单位数组。
1
2
def eye(N, M=None, k=0, dtype=float, order='C'):
def identity(n, dtype=None):

(e)对角数组

  • diag()函数:提取对角线或构造对角数组。

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import numpy as np

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]]

(f)常数数组

  • full()函数:返回一个常数数组。
  • full_like()函数:返回与给定数组具有相同形状和类型的常数数组。
1
2
def full(shape, fill_value, dtype=None, order='C'):
def full_like(a, fill_value, dtype=None, order='K', subok=True, shape=None):

3. 利用数值范围来创建ndarray

  • arange()函数:返回给定间隔内的均匀间隔的值。
  • linspace()函数:返回指定间隔内的等间隔数字。
  • logspace()函数:返回数以对数刻度均匀分布。
  • numpy.random.rand() 返回一个由[0,1)内的随机数组成的数组。
1
2
3
4
5
6
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):

4. 结构数组的创建

结构数组,首先需要定义结构,然后利用np.array()来创建数组,其参数dtype为定义的结构。

(a)利用字典来定义结构

1
2
3
4
5
6
7
8
9
10
11
import numpy as np

personType = np.dtype({
'names': ['name', 'age', 'weight'],
'formats': ['U30', 'i8', 'f8']})

a = np.array([('Liming', 24, 63.9), ('Mike', 15, 67.), ('Jan', 34, 45.8)],
dtype=personType)
print(a, type(a))
# [('Liming', 24, 63.9) ('Mike', 15, 67. ) ('Jan', 34, 45.8)]
# <class 'numpy.ndarray'>

(b)利用包含多个元组的列表来定义结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import numpy as np

personType = np.dtype([('name', 'U30'), ('age', 'i8'), ('weight', 'f8')])
a = np.array([('Liming', 24, 63.9), ('Mike', 15, 67.), ('Jan', 34, 45.8)],
dtype=personType)
print(a, type(a))
# [('Liming', 24, 63.9) ('Mike', 15, 67. ) ('Jan', 34, 45.8)]
# <class 'numpy.ndarray'>

# 结构数组的取值方式和一般数组差不多,可以通过下标取得元素:
print(a[0])
# ('Liming', 24, 63.9)

print(a[-2:])
# [('Mike', 15, 67. ) ('Jan', 34, 45.8)]

# 我们可以使用字段名作为下标获取对应的值
print(a['name'])
# ['Liming' 'Mike' 'Jan']
print(a['age'])
# [24 15 34]
print(a['weight'])
# [63.9 67. 45.8]

数组的属性

在使用 numpy 时,你会想知道数组的某些信息。很幸运,在这个包里边包含了很多便捷的方法,可以给你想要的信息。

  • numpy.ndarray.ndim用于返回数组的维数(轴的个数)也称为秩,一维数组的秩为 1,二维数组的秩为 2,以此类推。
  • numpy.ndarray.shape表示数组的维度,返回一个元组,这个元组的长度就是维度的数目,即 ndim 属性(秩)。
  • numpy.ndarray.size数组中所有元素的总量,相当于数组的shape中所有元素的乘积,例如矩阵的元素总量为行与列的乘积。
  • numpy.ndarray.dtype ndarray 对象的元素类型。
  • numpy.ndarray.itemsize以字节的形式返回数组中每一个元素的大小。
1
2
3
4
5
6
class ndarray(object):
shape = property(lambda self: object(), lambda self, v: None, lambda self: None)
dtype = property(lambda self: object(), lambda self, v: None, lambda self: None)
size = property(lambda self: object(), lambda self, v: None, lambda self: None)
ndim = property(lambda self: object(), lambda self, v: None, lambda self: None)
itemsize = property(lambda self: object(), lambda self, v: None, lambda self: None)

ndarray中所有元素必须是同一类型,否则会自动向下转换,int->float->str