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

系列文章地址


NumPy 數據類型

一、NumPy 中的數據類型

NumPy 支持比 Python 更多種類的數值類型,下表所列的數據類型都是 NumPy 內置的數據類型,爲了區別於 Python 原生的數據類型,boolintfloatcomplexstr 等類型名稱末尾都加了 _python

print(numpy.dtype) 所顯示的都是 NumPy 中的數據類型,而非 Python原生數據類型。es6

類型名稱 描述
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 位系統,上述的類型都是我實測獲得的,可是,我查看源碼,裏面倒是以下定義的。總之,爲了安全起見,仍是建議用 int3二、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 是純虛數。安全

二、datetime64 的使用

Ⅰ、簡單示例

例一:bash

import numpy as np

a = np.datetime64('2019-03-01')
print(a)
複製代碼

輸出:函數

2019-03-01
複製代碼

例二:post

import numpy as np

a = np.datetime64('2019-03')
print(a)
複製代碼

輸出:ui

2019-03
複製代碼

看到沒有,能夠僅顯示到「月」,是否是很贊?spa

Ⅱ、單位使用

datetime64 能夠指定使用的單位,單位包括年('Y'),月('M'),周('W')和天('D'),而時間單位是小時('h'),分鐘('m') ),秒('s'),毫秒('ms'),微秒('us'),納秒('ns'),皮秒('ps'),飛秒('fs'),阿託秒('as')。scala

例三: 周('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)
複製代碼

輸出:

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
複製代碼

Ⅴ、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'
複製代碼

Ⅵ、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
複製代碼

Ⅶ、工做日功能(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'
複製代碼

三、數據類型對象: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
複製代碼

四、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。

五、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']
複製代碼

歡迎關注個人公衆號

大齡碼農的Python之路

掃碼關注個人我的公衆號
相關文章
相關標籤/搜索