0%

numpy学习——02数据类型

本文是根据 DataWhale『巨硬的 numpy』文档进行学习, 辅之以天池平台, 之前学习过, 此时进行进一步的整理, 着重学习未完全熟悉的知识点.

详细的代码我也放入了天池学习的AI训练营合集中

常量

空值

使用 np.nan 来表示空值, 需要注意的是: 空值之间并不相等!

1
2
print(np.nan == np.nan)  # False
print(np.nan != np.nan) # True

可以使用 np.isnan 来检查空值

1
2
3
4
x = np.array([1, 1, 8, np.nan, 10])
y = np.isnan(x)
print(y)
# [False False False True False]

如果需要计算空值的个数, 则可以使用计算非零数 count_nonzero 来等价使用, 因为布尔值就分别代表了 01.

1
2
z = np.count_nonzero(y)
print(z) # 1

无穷大

以下这几个都可以

1
2
3
4
5
np.inf
np.Inf
np.Infinity
np.infty
np.PINF

圆周率 \(\pi\)

1
np.pi

自然常数 \(e\)

1
np.e

数据类型

在原生的 python 中, 数据类型较少, 但进行科学计算的时候, 需要对数据有更多的控制, 所以数据类型相对而言很丰富了.

在后续的创建数组时, 可以使用参数 dtype 来规定数据的类型. 与 python 原生类型相同的, 则会在类型后加入一个下划线以示区分, 例如 bool_, 常见的数据类型如下:

类型 备注 说明
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 表示两个时间之间的间隔

而我们内建的数据类型会有一个与其唯一对应的字符代码, 如下:

字符 对应类型 备注
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

查看数据类型

type 是查看对象的类型, 而想要查看矩阵内的元素类型, 则可以使用 dtype.

1
2
a = np.array([1,2,3], dtype=np.float32)
print(a.dtype)

日期和时间

日期时间类型 datetime64

很多情况下, 我们需要字符串日期转化为时间类型, 在 numpy 中可以很方便的将字符串转换成时间日期类型 datetime64.

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

从字符串创建 datetime64 类型时, 会自动选择对应的单位.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
a = np.datetime64('2022-02')
print(a, a.dtype) # 2022-02 datetime64[M]

a = np.datetime64('2022-02-19')
print(a, a.dtype) # 2022-02-19 datetime64[D]

a = np.datetime64('2022-02-19 17')
print(a, a.dtype) # 2022-02-19T17 datetime64[h]

a = np.datetime64('2022-02-19 17:16')
print(a, a.dtype) # 2022-02-19T17:16 datetime64[m]

a = np.datetime64('2022-02-19 17:16:02')
print(a, a.dtype) # 2022-02-19T17:16:02 datetime64[s]

但也能够强制指定类型

1
2
a = np.datetime64('2022-02', 'Y')
print(a, a.dtype) # 2022 datetime64[Y]

在时间数组中, 若单位不统一, 则全部转化为最小的单位.

1
2
3
a = np.array(['2022-02', '2022-02-19', '2020-02-19 17:16'], dtype='datetime64')
print(a, a.dtype)
# ['2022-02-01T00:00' '2022-02-19T00:00' '2020-02-19T17:16'] datetime64[m]

使用 arange 也可以生成时间类型的数组, 若时间单位不一致, 则按照较小的单位作为间隔生成时间区间.

1
2
3
4
5
a = np.arange('2022-02', '2022-05', dtype=np.datetime64)
print(a) # ['2022-02' '2022-03' '2022-04']

a = np.arange('2022', '2022-05', dtype=np.datetime64)
print(a) # ['2022-01' '2022-02' '2022-03' '2022-04']

日期时间差 timedelta64

timedelta64 表示两个 datetime64 之间的差, 其单位与相减运算中的两个 datetime64 中的较小的单位保持一致.

1
2
3
4
5
6
7
8
a = np.datetime64('2022-02-19') - np.datetime64('2022-02-02')
print(a, a.dtype) # 17 days timedelta64[D]

b = np.datetime64('2022-02-19') - np.datetime64('2022-02-18 08')
print(b, b.dtype) # 16 hours timedelta64[h]

c = np.datetime64('2022-02-19') - np.datetime64('2022-02-17 23:00', 'D')
print(c, c.dtype) # 2 days timedelta64[D]

除了计算时间差得到 timedelta64 类型, 该类型还可以直接创建, 表示有多少个时间单位, 并可以进行四则运算.

1
2
3
4
a = np.timedelta64(2, 'Y')
print(a) # 2 years
b = np.timedelta64(a, 'M')
print(b) # 24 months

需要注意的是: 'Y'和'M'类型是无法与其他类型进行计算的, 因为无法确定一年有多少天, 一个月有多少天的问题.

那么这样可以进行加法计算, 实现在多久之前多久之后的计算.

计算结果的单位依旧以较小的为准

1
2
3
4
5
a = np.datetime64('2022-02') + np.timedelta64(20, 'D')
print(a, a.dtype) # 2022-02-21 datetime64[D]

b = np.datetime64('2022-02-15 00:00') + np.timedelta64(12, 'h')
print(b, b.dtype) # 2022-02-15T12:00 datetime64[m]

数组的时间格式 datetime64datetime 库中的时间格式 datetime 相互转换

1
2
3
4
5
6
7
8
9
10
import datetime

dt = datetime.datetime(year=2022, month=2, day=19, hour=17, minute=22, second=30)
dt64 = np.datetime64(dt, 's')
print(dt64, dt64.dtype)
# 2022-02-19T17:22:30 datetime64[s]

dt2 = dt64.astype(datetime.datetime)
print(dt2, type(dt2))
# 2022-02-19 17:22:30 <class 'datetime.datetime'>

工作日

有些应用场景只有工作日的数据需要操作, 那么在这里也包含了 busday 功能, 可以计算 offset 天后的工作日.

1
2
3
# 2022-02-18 是星期五
a = np.busday_offset('2022-02-18', offsets=1)
print(a) # 2022-02-21

若操作的时间本身不是工作日, 则会报错, 例如 '2022-02-19' 是周六, 那么将会抛出 ValueError.

这时可以使用参数 roll 来找到前一个 (forward) 或后一个 (backward) 工作日.

前一个指: 例如 21 号在 19 号之前; 后一个指: 例如 18 号在 19 号之后; 这个概念和平时理解的前天后天顺序不一样, 是类似数字大小的概念 😂.

1
2
3
4
5
# 2022-02-19 是星期六
a = np.busday_offset('2022-02-19', offsets=1, roll='forward')
print(a) # 2022-02-22
b = np.busday_offset('2022-02-19', offsets=1, roll='backward')
print(b) # 2022-02-21

判断是否是工作日也很简单, 使用 np.is_busday 即可.

1
2
3
4
a = np.is_busday('2022-02-18')
print(a) # True
b = np.is_busday('2022-02-19')
print(b) # False

例如统计数组中的工作日天数, 可以结合布尔值和计算非零数的方法 count_nonzero 进行解决.

1
2
3
a = np.arange('2022-02-01', '2022-03', dtype=np.datetime64)
cnt = np.count_nonzero(np.is_busday(a))
print(cnt) # 20

对于日期区间内的工作日天数, 则可以直接使用 busday_count 来计算.

1
2
cnt = np.busday_count('2022-02', '2022-03')
print(cnt) # 20

最后, 工作日还可以进行自定义, 毕竟一周可不是只上班五天呢~ (不是). 使用 0/1 表示周几属于工作日.

1
2
3
4
5
6
# 2022-02-18 是星期五
# 自定义设置工作日为 一 二 三 四 六
a = np.is_busday('2022-02-18', weekmask=[1,1,1,1,0,1,0])
b = np.is_busday('2022-02-19', weekmask=[1,1,1,1,0,1,0])
print(a) # False
print(b) # True

个人收获

本章对数据类型进行了一个汇总, 尤其是数据类型对于的字符代码, 之前不是很清楚什么 U 啊之类的, 这次整理好了, 可以方便以后查询.

还有日期类型, 之前还好奇为何多了一个 64datetime 后面, 原来是为了进行区分. 并熟悉了工作日的使用方法.

还有一个就是学到了计算非零数的函数 count_nonzero 可以与布尔数组联合使用, 达到计算满足条件的元素个数的目的.

------ 本文结束------