NumPy 超詳細教程(2):數據類型

系列文章地址


文章目錄

NumPy 數據類型1、NumPy 中的數據類型補充:複數的概念2、datetime64 的使用Ⅰ、簡單示例Ⅱ、單位使用Ⅲ、配合 arange 函數使用Ⅳ、Datetime64 和 Timedelta64 運算Ⅴ、Timedelta64 單獨的運算Ⅵ、numpy.datetime64 與 datetime.datetime 相互轉換Ⅶ、工作日功能(busday)3、數據類型對象:dtypeⅠ、實例化 dtype 對象Ⅱ、字符代碼4、numpy.datetime_data5、numpy.datetime_as_string


NumPy 數據類型

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 位浮點數(實數部分和虛數部分)
datetime64 NumPy 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 是純虛數。

2、datetime64 的使用

Ⅰ、簡單示例

例一:

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

看到沒有,可以僅顯示到“月”,是不是很贊?

Ⅱ、單位使用

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]

Ⅲ、配合 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,沒道理去掉的。

Ⅳ、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)

輸出:

days timedelta64[D]
960 minutes timedelta64[m]
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

Ⅴ、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
months
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'

Ⅵ、numpy.datetime64 與 datetime.datetime 相互轉換

import numpy as np
import datetime

dt = datetime.datetime(201891)
dt64 = np.datetime64(dt, 'D')
print(dt64, dt64.dtype)

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

輸出:

2018-09-01 datetime64[D]
2018-09-01

Ⅶ、工作日功能(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=[1111010])
b = np.is_busday('2019-03-09', weekmask='1111010')
print(a)
print(b)

輸出:

False
True

周掩碼值還可以直接用星期單詞縮寫列出所有的工作日,下面所示的周掩碼錶示的工作日是:週一週二週三週四週六週日,週五爲休息日。

weekmask='Mon Tue Wed Thu Sat Sun'

3、數據類型對象:dtype

數據類型對象是用來描述與數組對應的內存區域如何使用,這依賴如下幾個方面:

  • 數據的類型(整數,浮點數或者 Python 對象)
  • 數據的大小(例如, 整數使用多少個字節存儲)
  • 數據的字節順序(小端法"<"或大端法">",大端法高字節在前低字節在後,小端法低字節在前高字節在後)
  • 在結構化類型的情況下,字段的名稱、每個字段的數據類型和每個字段所取的內存塊的部分(見例三)
  • 如果數據類型是子數組,它的形狀和數據類型字節順序是通過對數據類型預先設定"<"或">"來決定的。

Ⅰ、實例化 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)]

Ⅱ、字符代碼

字符代碼對應類型
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
m timedelta64(時間間隔),本質上是個 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

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([12345], dt_25s).astype('timedelta64[s]')
print(b)
print(b.dtype)

輸出:

[ 25  50  75 100 125]
timedelta64[s]

本例中,b 是一個 narray,數據類型從 timedelta64[25s] 轉成了 timedelta64[s],所以數組中每個數都要乘以 25。

5、numpy.datetime_as_string

將日期時間數組轉換爲字符串數組。

語法:

numpy.datetime_as_string(arr, unit=None, timezone='naive', casting='same_kind')
參數描述
arr datetimes64 數組
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']
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章