NumPy 超详细教程(2):数据类型

系列文章地址

NumPy 最详细教程(1):NumPy 数组
NumPy 超详细教程(2):数据类型
NumPy 超详细教程(3):ndarray 的内部机理及高级迭代



1、NumPy 数据类型

1.1、NumPy 中的数据类型

NumPy 支持比 Python 更多种类的数值类型,下表所列的数据类型都是 NumPy 内置的数据类型,为了区别于 Python 原生的数据类型,boolintfloatcomplexstr 等类型名称末尾都加了 _

print(numpy.dtype) 所显示的都是 NumPy 中的数据类型,而非 Python原生数据类型。

类型名称描述
bool_布尔类型
unicode_ / unicode / str_ / str0(零非字母O)Unicode 字符串
int8 / byte
int16 / short
int32 / intc / int_ / long
int64 / longlong / intp / int0(零非字母O)
uint8 / ubyte
uint16 / ushort
uint32 / uintc
uint64 / ulonglong / uintp / uint0(零非字母O)
float16 / half半精度浮点数,包括:1 个符号位,5 个指数位,10 个尾数位
float32 / single单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位
float64 / float_ / double双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位
complex64 / singlecomplex复数,表示双 32 位浮点数(实数部分和虚数部分)
complex128 / complex_ / cfloat / cdouble /
longcomplex / clongfloat / clongdouble
复数,表示双 64 位浮点数(实数部分和虚数部分)
datetime64NumPy 1.7 开始支持的日期时间类型
timedelta64表示两个时间之间的间隔

这里有点不理解,我是 win7 64 位系统,上述的类型都是我实测得到的,但是,我查看源码,里面却是如下定义的。总之,为了安全起见,还是建议用 int32、int64 等无歧义的类型。

int_ = long
intp = long
int64 = long
int0 = long

class long(signedinteger):
    """ 64-bit integer. Character code 'l'. Python int compatible. """
    pass
补充:复数的概念

我们把形如 z=a+bi(a, b均为实数)的数称为复数,其中 a 称为实部,b 称为虚部,i 称为虚数单位。
当虚部 b=0 时,复数 z 是实数;
当虚部 b!=0 时,复数 z 是虚数;
当虚部 b!=0,且实部 a=0 时,复数 z 是纯虚数。

1.2、datetime64 的使用

1.2.1、简单示例

例一:

import numpy as np

a = np.datetime64('2019-03-01')
print(a)

输出:

2019-03-01

例二:

import numpy as np

a = np.datetime64('2019-03')
print(a)

输出:

2019-03

看到没有,可以仅显示到“月”,是不是很赞?

1.2.2、单位使用

datetime64 可以指定使用的单位,单位包括年(‘Y’),月(‘M’),周(‘W’)和天(‘D’),而时间单位是小时(‘h’),分钟(‘m’) ),秒(‘s’),毫秒(‘ms’),微秒(‘us’),纳秒(‘ns’),皮秒(‘ps’),飞秒(‘fs’),阿托秒(‘as’)。

例三:
周(‘W’)是一个比较奇怪的单位,如果是周四,则显示当前,如果不是,则显示上一个周四。后来我想,大概是因为 1970-01-01 是周四

import numpy as np

a = np.datetime64('2019-03-07', 'W')
b = np.datetime64('2019-03-08', 'W')
print(a, b)

输出:(2019-03-07 是周四)

2019-03-07 2019-03-07

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

import numpy as np

a = np.datetime64('2019-03-08 20:00')
print(a.dtype)

输出:

datetime64[m]

例五:
也可以强制指定使用的单位。

import numpy as np

a = np.datetime64('2019-03', 'D')
print(a)

输出:

2019-03-01

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

import numpy as np

print(np.datetime64('2019-03') == np.datetime64('2019-03-01'))

输出:

True

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

import numpy as np

a = np.array(['2019-03', '2019-03-08', '2019-03-08 20:00'], dtype='datetime64')
print(a)
print(a.dtype)

输出:

['2019-03-01T00:00' '2019-03-08T00:00' '2019-03-08T20:00']
datetime64[m]
1.2.3、配合 arange 函数使用

**例八:**一个月的所有天数

import numpy as np

a = np.arange('2019-02', '2019-03', dtype='datetime64[D]')
print(a)

输出:

['2019-02-01' '2019-02-02' '2019-02-03' '2019-02-04' '2019-02-05'
 '2019-02-06' '2019-02-07' '2019-02-08' '2019-02-09' '2019-02-10'
 '2019-02-11' '2019-02-12' '2019-02-13' '2019-02-14' '2019-02-15'
 '2019-02-16' '2019-02-17' '2019-02-18' '2019-02-19' '2019-02-20'
 '2019-02-21' '2019-02-22' '2019-02-23' '2019-02-24' '2019-02-25'
 '2019-02-26' '2019-02-27' '2019-02-28']

例九:
间隔也可以是 3 天(‘3D’)这种形式哦。

import numpy as np

a = np.arange('2019-02', '2019-03', dtype='datetime64[3D]')
print(a)

输出:

['2019-02-01' '2019-02-04' '2019-02-07' '2019-02-10' '2019-02-13'
 '2019-02-16' '2019-02-19' '2019-02-22' '2019-02-25']

发现没有,这里少了 2019-02-28。我认为是个 BUG,没道理去掉的。

1.2.4、Datetime64 和 Timedelta64 运算

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

import numpy as np

a = np.datetime64('2019-03-08') - np.datetime64('2019-03-07')
b = np.datetime64('2019-03-08') - np.datetime64('2019-03-07 08:00')
c = np.datetime64('2019-03-08') - np.datetime64('2019-03-07 23:00', 'D')

print(a, a.dtype)
print(b, b.dtype)
print(c, c.dtype)

输出:

1 days timedelta64[D]
960 minutes timedelta64[m]
1 days timedelta64[D]

看 c 的表达式,因为强制限定了单位,所以 np.datetime64('2019-03-07 23:00', 'D') 所表示的时间其实是 2019-03-07,那么结果是 1 也就好理解了。

例二:

import numpy as np

a = np.datetime64('2019-03') + np.timedelta64(20, 'D')
print(a)

输出:

2019-03-21
1.2.5、Timedelta64 单独的运算

**例一:**生成 Timedelta64

import numpy as np

a = np.timedelta64(1, 'Y')    # 方式一
b = np.timedelta64(a, 'M')    # 方式二
print(a)
print(b)

输出:

1 years
12 months

**例二:**加减乘除

import numpy as np

a = np.timedelta64(1, 'Y')
b = np.timedelta64(6, 'M')

print(a + b)
print(a - b)
print(2 * a)
print(a / b)

输出:

18 months
6 months
2 years
2.0

例三:
但是,年(‘Y’)和月(‘M’)这两个单位是经过特殊处理的,它们无法和其他单位进行运算,一年有几天?一个月有几个小时?这些都是不确定的。

import numpy as np

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'
1.2.6、numpy.datetime64 与 datetime.datetime 相互转换
import numpy as np
import datetime

dt = datetime.datetime(2018, 9, 1)
dt64 = np.datetime64(dt, 'D')
print(dt64, dt64.dtype)

dt2 = dt64.astype(datetime.datetime)
print(dt2)

输出:

2018-09-01 datetime64[D]
2018-09-01
1.2.7、工作日功能(busday)

busday 默认周一至周五是工作日。该实现基于一个 weekmask,包含 7 个布尔标志,用于工作日。

**例一:**busday_offset
busday_offset 将指定的偏移量应用于工作日,单位天(‘D’)。例如计算下一个工作日:

import numpy as np

a = np.busday_offset('2019-03-08', 1)
print(a)

输出:

2019-03-11

例二:
如果当前日期为非工作日,则默认是报错的。

import numpy as np

a = np.busday_offset('2019-03-09', 1)
print(a)

输出:

ValueError: Non-business day date in busday_offset

例三:
可以指定 forwardbackward 规则来避免报错。

import numpy as np

a = np.busday_offset('2019-03-09', 1, roll='forward')
b = np.busday_offset('2019-03-09', 1, roll='backward')
print(a)
print(b)

c = np.busday_offset('2019-03-09', 0, roll='forward')
d = np.busday_offset('2019-03-09', 0, roll='backward')
print(c)
print(d)

输出:

2019-03-12
2019-03-11
2019-03-11
2019-03-08

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

例四:

import numpy as np

a = np.busday_offset('2019-05', 1, roll='forward', weekmask='Sun')
print(a)

输出:

2019-05-12

母亲节是 5 月的第二个星期日,本例就可以用于返回母亲节具体的日期。来解释一下:weekmask 参数在这里可以传星期的英文简写(注意是简写 Mon、Tue、Wed、Thu、Fri、Sat、Sun,全拼报错的),指定向前或向后到星期几。上面代码的含义就是:前进道 2019-05-01 后的第二个(不要忘了下标从 0 开始的)星期日。

这个功能对老美来说也许有用,但是在中国,谁来给我求个端午节是几月几号?

**例五:**is_busday
返回指定日期是否是工作日。

import numpy as np

a = np.is_busday(np.datetime64('2019-03-08'))
b = np.is_busday('2019-03-09')
print(a)
print(b)

输出:

True
False

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

import numpy as np

a = np.busday_count(np.datetime64('2019-03-01'), np.datetime64('2019-03-10'))
b = np.busday_count('2019-03-10', '2019-03-01')
print(a)
print(b)

输出:

6
-6

**例七:**count_nonzero
统计一个 datetime64[‘D’] 数组中的工作日天数。

import numpy as np

c = np.arange('2019-03-01', '2019-03-10', dtype='datetime64')
d = np.count_nonzero(np.is_busday(c))
print(d)

输出:

6

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

import numpy as np

a = np.is_busday('2019-03-08', weekmask=[1, 1, 1, 1, 0, 1, 0])
b = np.is_busday('2019-03-09', weekmask='1111010')
print(a)
print(b)

输出:

False
True

周掩码值还可以直接用星期单词缩写列出所有的工作日,下面所示的周掩码表示的工作日是:周一周二周三周四周六周日,周五为休息日。

weekmask='Mon Tue Wed Thu Sat Sun'

1.3、数据类型对象:dtype

数据类型对象是用来描述与数组对应的内存区域如何使用,这依赖如下几个方面:

  • 数据的类型(整数,浮点数或者 Python 对象)
  • 数据的大小(例如, 整数使用多少个字节存储)
  • 数据的字节顺序(小端法"<“或大端法”>",大端法高字节在前低字节在后,小端法低字节在前高字节在后)
  • 在结构化类型的情况下,字段的名称、每个字段的数据类型和每个字段所取的内存块的部分(见例三)
  • 如果数据类型是子数组,它的形状和数据类型字节顺序是通过对数据类型预先设定"<“或”>"来决定的。
1.3.1、实例化 dtype 对象

dtype 对象构造语法:

numpy.dtype(obj, align=False, copy=False)
参数描述
object要转换为数据类型对象的对象
align如果为 True,填充字段使其类似 C 的结构体,只有当 object 是字典或逗号分隔的字符串时才可以是 True
copy复制 dtype 对象,如果为 False,则是对内置数据类型对象的引用

例一:
int8, int16, int32, int64 四种数据类型可以使用字符串 ‘i1’, ‘i2’, ‘i4’, ‘i8’ 代替。(见字符代码)

import numpy as np

dt = np.dtype('i4')
print(dt)

输出:

int32

例二:

import numpy as np

dt = np.dtype('<i4')
print(dt)

输出:

int32

例三:
本例定义一个结构化数据类型 student,包含字符串字段 name,整数字段 age,并将这个 dtype 应用到 ndarray 对象。

import numpy as np
student = np.dtype([('name', 'S20'), ('age', 'i1')])
print(student)

a = np.array([('tom', 21), ('Jerry', 18)], dtype=student)
print(a)

输出:

[('name', 'S20'), ('age', 'i1')]
[(b'tom', 21) (b'Jerry', 18)]
1.3.2、字符代码
字符代码对应类型
b布尔型
i有符号整型,‘i1’, ‘i2’, ‘i4’, ‘i8’ 对应 int8, int16, int32, int64
u无符号整型,‘u1’, ‘u2’, ‘u4’, ‘u8’ 对应 uint8, uint16, uint32, uint64
f浮点型,‘f2’, ‘f4’, ‘f8’ 对应 float16, float32, float64
c复数,‘c8’, ‘c16’ 对应 complex64, complex128
mtimedelta64(时间间隔),本质上是个 int64
M(大写)datetime64(日期时间)
O(大写)Python 对象
S(大写)/ a(byte-)字符串,只能包含 ASCII 码字符,S 或 a 后带数字表示字符串长度,超出部分将被截断,例如 S20、a10
U(大写)Unicode 字符串,U 后带数字表示字符串长度,超出部分将被截断,例如 U20
V(大写)bytes 数组,V 后带数字表示数组长度,超出部分将被截断,不足则补零

这里主要讲下 M 和 V 的使用,其他都比较简单好理解,可以看上面的例子。

字符代码 M 的使用示例:

import numpy as np

student = np.dtype([('name', 'S4'), ('age', 'M8[D]')])
print(student)

a = np.array([('tom', '2011-01-01'), ('Jerry', np.datetime64('2012-05-17'))], dtype=student)
print(a)
print(a['age'].dtype)

输出:

[('name', 'S4'), ('age', '<M8[D]')]
[(b'tom', '2011-01-01') (b'Jerr', '2012-05-17')]
datetime64[D]

这里必须写成 M8[单位],不加单位报:Cannot cast NumPy timedelta64 scalar from metadata [D] to according to the rule ‘same_kind’

字符代码 V 的使用示例:

import numpy as np

student = np.dtype([('name', 'V8'), ('age', 'i1')])
print(student)

a = np.array([(b'tom', 21), (b'Jerry', 18)], dtype=student)
print(a)
print(a['name'].dtype)

输出:

[('name', 'V8'), ('age', 'i1')]
[(b'\x74\x6F\x6D\x00\x00\x00\x00\x00', 21)
 (b'\x4A\x65\x72\x72\x79\x00\x00\x00', 18)]
|V8

1.4、numpy.datetime_data

语法:

numpy.datetime_data(dtype, /)

**参数:**只能是 datetime64timedelta64 类型
**返回值:**返回一个元组 (‘单位’, 步长)

例一:

import numpy as np

dt_25s = np.dtype('timedelta64[25s]')
print(np.datetime_data(dt_25s))

输出:

('s', 25)

例二:

import numpy as np

dt_25s = np.dtype('timedelta64[25s]')
b = np.array([1, 2, 3, 4, 5], dt_25s).astype('timedelta64[s]')
print(b)
print(b.dtype)

输出:

[ 25  50  75 100 125]
timedelta64[s]

本例中,b 是一个 narray,数据类型从 timedelta64[25s] 转成了 timedelta64[s],所以数组中每个数都要乘以 25。

1.5、numpy.datetime_as_string

将日期时间数组转换为字符串数组。

语法:

numpy.datetime_as_string(arr, unit=None, timezone='naive', casting='same_kind')
参数描述
arrdatetimes64 数组
unit‘auto’ 或者 datetime64 单位。
timezone时区
casting在日期时间单位之间进行更改时允许进行转换。有以下可选值:‘no’, ‘equiv’, ‘safe’, ‘same_kind’, ‘unsafe’。

例一:

import numpy as np

dt_array = np.arange('2019-03-01', '2019-03-10', dtype='datetime64[D]')
str_array = np.datetime_as_string(dt_array)

print(str_array)
print(str_array.dtype)

输出:

['2019-03-01' '2019-03-02' '2019-03-03' '2019-03-04' '2019-03-05'
 '2019-03-06' '2019-03-07' '2019-03-08' '2019-03-09']
<U28

**例二:**unit的使用示例
默认情况下,unit=None,如果数组中的 datetime64 元素单位不一致,则会统一转化为其中最小的单位形式输出,如果 unit='auto' 则会保持原样输出。当然,如果指定了单位,则按指定的单位格式输出。

import numpy as np

dt_array = np.array(['2019-03', '2019-03-08', '2019-03-08 20:00'], dtype='datetime64')

str_array1 = np.datetime_as_string(dt_array)
str_array2 = np.datetime_as_string(dt_array, unit='auto')
str_array3 = np.datetime_as_string(dt_array, unit='D')
print(str_array1)
print(str_array2)
print(str_array3)

输出:

['2019-03-01T00:00' '2019-03-08T00:00' '2019-03-08T20:00']
['2019-03-01' '2019-03-08' '2019-03-08T20:00']
['2019-03-01' '2019-03-08' '2019-03-08']

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值