結構化陣列#

簡介#

結構化陣列是 `ndarray`,其資料型別是由更簡單的資料型別組成,並組織為一系列具名的欄位。例如,

>>> x = np.array([('Rex', 9, 81.0), ('Fido', 3, 27.0)],
...              dtype=[('name', 'U10'), ('age', 'i4'), ('weight', 'f4')])
>>> x
array([('Rex', 9, 81.), ('Fido', 3, 27.)],
      dtype=[('name', '<U10'), ('age', '<i4'), ('weight', '<f4')])

這裡 x 是一個長度為二的一維陣列,其資料型別是一個具有三個欄位的結構:1. 一個名為 ‘name’ 的長度為 10 或更短的字串,2. 一個名為 ‘age’ 的 32 位元整數,以及 3. 一個名為 ‘weight’ 的 32 位元浮點數。

如果您在位置 1 對 x 進行索引,您會得到一個結構

>>> x[1]
np.void(('Fido', 3, 27.0), dtype=[('name', '<U10'), ('age', '<i4'), ('weight', '<f4')])

您可以使用欄位名稱進行索引,來存取和修改結構化陣列的個別欄位

>>> x['age']
array([9, 3], dtype=int32)
>>> x['age'] = 5
>>> x
array([('Rex', 5, 81.), ('Fido', 5, 27.)],
      dtype=[('name', '<U10'), ('age', '<i4'), ('weight', '<f4')])

結構化資料型別旨在模擬 C 語言中的 ‘structs’,並共享類似的記憶體佈局。它們用於與 C 程式碼介接,以及對結構化緩衝區進行低階操作,例如用於解譯二進位 blob。為了這些目的,它們支援諸如子陣列、巢狀資料型別和聯集等特殊功能,並允許控制結構的記憶體佈局。

尋求操作表格資料(例如儲存在 csv 檔案中)的使用者可能會發現其他 pydata 專案更適合,例如 xarray、pandas 或 DataArray。這些專案為表格資料分析提供高階介面,並且針對該用途進行了更好的最佳化。例如,與之相比,numpy 中結構化陣列的類似 C 結構的記憶體佈局可能會導致較差的快取行為。

結構化資料型別#

結構化資料型別可以被認為是具有特定長度(結構的 itemsize)的位元組序列,它被解譯為欄位的集合。每個欄位都有一個名稱、一個資料型別以及在結構內的位元組偏移量。欄位的資料型別可以是任何 numpy 資料型別,包括其他結構化資料型別,它也可以是子陣列資料型別,其行為類似於具有指定形狀的 ndarray。欄位的偏移量是任意的,欄位甚至可能重疊。這些偏移量通常由 numpy 自動決定,但也可以指定。

結構化資料型別建立#

結構化資料型別可以使用函式 numpy.dtype 建立。有 4 種替代的規格形式,它們在彈性和簡潔性上有所不同。這些在資料型別物件參考頁面中有更詳細的文檔說明,總結如下:

  1. 元組的列表,每個元組代表一個欄位

    每個元組的格式為 (fieldname, datatype, shape),其中 shape 是可選的。fieldname 是一個字串(如果使用標題,則為元組,請參閱下方的欄位標題),datatype 可以是任何可轉換為資料型別的物件,而 shape 是一個整數元組,用於指定子陣列形狀。

    >>> np.dtype([('x', 'f4'), ('y', np.float32), ('z', 'f4', (2, 2))])
    dtype([('x', '<f4'), ('y', '<f4'), ('z', '<f4', (2, 2))])
    

    如果 fieldname 是空字串 '',則欄位將被賦予預設名稱,格式為 f#,其中 # 是欄位的整數索引,從左側的 0 開始計數

    >>> np.dtype([('x', 'f4'), ('', 'i4'), ('z', 'i8')])
    dtype([('x', '<f4'), ('f1', '<i4'), ('z', '<i8')])
    

    結構內欄位的位元組偏移量和結構總 itemsize 會自動決定。

  2. 逗號分隔的 dtype 規格字串

    在此簡寫表示法中,任何字串 dtype 規格都可以在字串中使用,並以逗號分隔。欄位的 itemsize 和位元組偏移量會自動決定,欄位名稱會被賦予預設名稱 f0f1 等。

    >>> np.dtype('i8, f4, S3')
    dtype([('f0', '<i8'), ('f1', '<f4'), ('f2', 'S3')])
    >>> np.dtype('3int8, float32, (2, 3)float64')
    dtype([('f0', 'i1', (3,)), ('f1', '<f4'), ('f2', '<f8', (2, 3))])
    
  3. 欄位參數陣列的字典

    這是最靈活的規格形式,因為它允許控制欄位的位元組偏移量和結構的 itemsize

    字典有兩個必需的鍵,‘names’ 和 ‘formats’,以及四個可選的鍵,‘offsets’、‘itemsize’、‘aligned’ 和 ‘titles’。 ‘names’ 和 ‘formats’ 的值應分別為欄位名稱列表和 dtype 規格列表,長度相同。可選的 ‘offsets’ 值應為整數位元組偏移量列表,每個欄位在結構內都有一個偏移量。如果未給定 ‘offsets’,則會自動決定偏移量。可選的 ‘itemsize’ 值應為一個整數,描述 dtype 的總大小(以位元組為單位),它必須足夠大以容納所有欄位。

    >>> np.dtype({'names': ['col1', 'col2'], 'formats': ['i4', 'f4']})
    dtype([('col1', '<i4'), ('col2', '<f4')])
    >>> np.dtype({'names': ['col1', 'col2'],
    ...           'formats': ['i4', 'f4'],
    ...           'offsets': [0, 4],
    ...           'itemsize': 12})
    dtype({'names': ['col1', 'col2'], 'formats': ['<i4', '<f4'], 'offsets': [0, 4], 'itemsize': 12})
    

    可以選擇偏移量,使欄位重疊,儘管這意味著賦值給一個欄位可能會損壞任何重疊欄位的資料。作為一個例外,numpy.object_ 型別的欄位不能與其他欄位重疊,因為存在損壞內部物件指標然後對其進行解參考的風險。

    可選的 ‘aligned’ 值可以設定為 True,使自動偏移量計算使用對齊的偏移量(請參閱自動位元組偏移量和對齊),就好像 numpy.dtype 的 ‘align’ 關鍵字引數已設定為 True 一樣。

    可選的 ‘titles’ 值應為標題列表,其長度與 ‘names’ 相同,請參閱下方的欄位標題

  4. 欄位名稱的字典

    字典的鍵是欄位名稱,值是指定型別和偏移量的元組

    >>> np.dtype({'col1': ('i1', 0), 'col2': ('f4', 1)})
    dtype([('col1', 'i1'), ('col2', '<f4')])
    

    不建議使用這種形式,因為 Python 字典在 Python 3.6 之前的 Python 版本中不保留順序。欄位標題可以使用 3 元組指定,請參閱下文。

操作和顯示結構化資料型別#

結構化資料型別的欄位名稱列表可以在 dtype 物件的 names 屬性中找到

>>> d = np.dtype([('x', 'i8'), ('y', 'f4')])
>>> d.names
('x', 'y')

可以使用名稱查找每個個別欄位的 dtype

>>> d['x']
dtype('int64')

欄位名稱可以透過賦值給 names 屬性來修改,使用相同長度的字串序列。

dtype 物件也有一個類似字典的屬性 fields,其鍵是欄位名稱(和欄位標題,請參閱下文),其值是包含每個欄位的 dtype 和位元組偏移量的元組。

>>> d.fields
mappingproxy({'x': (dtype('int64'), 0), 'y': (dtype('float32'), 8)})

對於非結構化陣列,namesfields 屬性都將等於 None。測試 dtype 是否為結構化的建議方法是使用 if dt.names is not None 而不是 if dt.names,以考慮具有 0 個欄位的 dtype。

結構化資料型別的字串表示形式會以「元組列表」形式顯示(如果可能),否則 numpy 會退回到使用更通用的字典形式。

自動位元組偏移量和對齊#

Numpy 使用兩種方法之一來自動決定欄位位元組偏移量和結構化資料型別的總 itemsize,具體取決於是否將 align=True 指定為 numpy.dtype 的關鍵字引數。

預設情況下 (align=False),numpy 會將欄位打包在一起,使每個欄位從前一個欄位結束的位元組偏移量開始,並且欄位在記憶體中是連續的。

>>> def print_offsets(d):
...     print("offsets:", [d.fields[name][1] for name in d.names])
...     print("itemsize:", d.itemsize)
>>> print_offsets(np.dtype('u1, u1, i4, u1, i8, u2'))
offsets: [0, 1, 2, 6, 7, 15]
itemsize: 17

如果設定了 align=True,numpy 將以許多 C 編譯器填充 C 結構的方式填充結構。對齊的結構在某些情況下可以提高效能,但會增加資料型別的大小。填充位元組會插入在欄位之間,使每個欄位的位元組偏移量將是該欄位對齊方式的倍數,對於簡單的資料型別,對齊方式通常等於欄位的大小(以位元組為單位),請參閱 PyArray_Descr.alignment。結構也將新增尾隨填充,使其 itemsize 是最大欄位對齊方式的倍數。

>>> print_offsets(np.dtype('u1, u1, i4, u1, i8, u2', align=True))
offsets: [0, 1, 4, 8, 16, 24]
itemsize: 32

請注意,雖然幾乎所有現代 C 編譯器預設都以這種方式填充,但 C 結構中的填充是 C 實作相關的,因此此記憶體佈局不能保證與 C 程式中對應結構的佈局完全匹配。可能需要在 numpy 端或 C 端進行一些工作,以獲得完全對應。

如果使用基於字典的 dtype 規格中的可選 offsets 鍵指定了偏移量,則設定 align=True 將檢查每個欄位的偏移量是否為其大小的倍數,以及 itemsize 是否為最大欄位大小的倍數,如果不是,則會引發例外。

如果結構化陣列的欄位偏移量和 itemsize 滿足對齊條件,則陣列將設定 ALIGNED 旗標

便利函式 numpy.lib.recfunctions.repack_fields 將對齊的 dtype 或陣列轉換為打包的 dtype 或陣列,反之亦然。它採用 dtype 或結構化 ndarray 作為引數,並傳回重新打包欄位的副本,帶或不帶填充位元組。

欄位標題#

除了欄位名稱之外,欄位也可能具有關聯的標題,即替代名稱,有時用作欄位的額外描述或別名。標題可以用於索引陣列,就像欄位名稱一樣。

若要在使用元組列表形式的 dtype 規格時新增標題,欄位名稱可以指定為兩個字串的元組,而不是單個字串,這將分別是欄位的標題和欄位名稱。例如

>>> np.dtype([(('my title', 'name'), 'f4')])
dtype([(('my title', 'name'), '<f4')])

當使用第一種形式的基於字典的規格時,標題可以作為額外的 'titles' 鍵提供,如上所述。當使用第二種(不建議使用)基於字典的規格時,可以透過提供 3 元素元組 (datatype, offset, title) 而不是通常的 2 元素元組來提供標題

>>> np.dtype({'name': ('i4', 0, 'my title')})
dtype([(('my title', 'name'), '<i4')])

dtype.fields 字典將包含標題作為鍵(如果使用了任何標題)。這實際上意味著具有標題的欄位將在 fields 字典中表示兩次。這些欄位的元組值也將具有第三個元素,即欄位標題。因此,並且因為 names 屬性保留欄位順序,而 fields 屬性可能不保留,因此建議使用 dtype 的 names 屬性來迭代 dtype 的欄位,這不會列出標題,如下所示

>>> for name in d.names:
...     print(d.fields[name][:2])
(dtype('int64'), 0)
(dtype('float32'), 8)

聯集型別#

結構化資料型別在 numpy 中實作為預設具有基本型別 numpy.void,但可以使用資料型別物件中描述的 dtype 規格的 (base_dtype, dtype) 形式,將其他 numpy 型別解譯為結構化型別。在這裡,base_dtype 是所需的底層 dtype,欄位和旗標將從 dtype 複製。此 dtype 類似於 C 中的「聯集」。

結構化陣列的索引和賦值#

賦值資料給結構化陣列#

有許多方法可以將值賦值給結構化陣列:使用 python 元組、使用純量值或使用其他結構化陣列。

從 Python 原生型別(元組)賦值#

將值賦值給結構化陣列的最簡單方法是使用 python 元組。每個賦值的值都應該是一個元組,其長度等於陣列中的欄位數,而不是列表或陣列,因為這些會觸發 numpy 的廣播規則。元組的元素會從左到右賦值給陣列的連續欄位

>>> x = np.array([(1, 2, 3), (4, 5, 6)], dtype='i8, f4, f8')
>>> x[1] = (7, 8, 9)
>>> x
array([(1, 2., 3.), (7, 8., 9.)],
     dtype=[('f0', '<i8'), ('f1', '<f4'), ('f2', '<f8')])

從純量賦值#

賦值給結構化元素的純量將賦值給所有欄位。當純量賦值給結構化陣列,或當非結構化陣列賦值給結構化陣列時,會發生這種情況

>>> x = np.zeros(2, dtype='i8, f4, ?, S1')
>>> x[:] = 3
>>> x
array([(3, 3., True, b'3'), (3, 3., True, b'3')],
      dtype=[('f0', '<i8'), ('f1', '<f4'), ('f2', '?'), ('f3', 'S1')])
>>> x[:] = np.arange(2)
>>> x
array([(0, 0., False, b'0'), (1, 1., True, b'1')],
      dtype=[('f0', '<i8'), ('f1', '<f4'), ('f2', '?'), ('f3', 'S1')])

結構化陣列也可以賦值給非結構化陣列,但前提是結構化資料型別只有一個欄位

>>> twofield = np.zeros(2, dtype=[('A', 'i4'), ('B', 'i4')])
>>> onefield = np.zeros(2, dtype=[('A', 'i4')])
>>> nostruct = np.zeros(2, dtype='i4')
>>> nostruct[:] = twofield
Traceback (most recent call last):
...
TypeError: Cannot cast array data from dtype([('A', '<i4'), ('B', '<i4')]) to dtype('int32') according to the rule 'unsafe'

從其他結構化陣列賦值#

兩個結構化陣列之間的賦值發生時,就好像來源元素已轉換為元組,然後賦值給目的地元素一樣。也就是說,來源陣列的第一個欄位賦值給目的地陣列的第一個欄位,第二個欄位也一樣,依此類推,與欄位名稱無關。欄位數不同的結構化陣列不能相互賦值。目的地結構中未包含在任何欄位中的位元組不受影響。

>>> a = np.zeros(3, dtype=[('a', 'i8'), ('b', 'f4'), ('c', 'S3')])
>>> b = np.ones(3, dtype=[('x', 'f4'), ('y', 'S3'), ('z', 'O')])
>>> b[:] = a
>>> b
array([(0., b'0.0', b''), (0., b'0.0', b''), (0., b'0.0', b'')],
      dtype=[('x', '<f4'), ('y', 'S3'), ('z', 'O')])

涉及子陣列的賦值#

當賦值給作為子陣列的欄位時,賦值的值將首先廣播到子陣列的形狀。

索引結構化陣列#

存取個別欄位#

可以透過使用欄位名稱索引陣列來存取和修改結構化陣列的個別欄位。

>>> x = np.array([(1, 2), (3, 4)], dtype=[('foo', 'i8'), ('bar', 'f4')])
>>> x['foo']
array([1, 3])
>>> x['foo'] = 10
>>> x
array([(10, 2.), (10, 4.)],
      dtype=[('foo', '<i8'), ('bar', '<f4')])

結果陣列是原始陣列的視圖。它共享相同的記憶體位置,寫入視圖將修改原始陣列。

>>> y = x['bar']
>>> y[:] = 11
>>> x
array([(10, 11.), (10, 11.)],
      dtype=[('foo', '<i8'), ('bar', '<f4')])

此視圖具有與索引欄位相同的 dtype 和 itemsize,因此它通常是一個非結構化陣列,巢狀結構的情況除外。

>>> y.dtype, y.shape, y.strides
(dtype('float32'), (2,), (12,))

如果存取的欄位是子陣列,則子陣列的維度會附加到結果的形狀

>>> x = np.zeros((2, 2), dtype=[('a', np.int32), ('b', np.float64, (3, 3))])
>>> x['a'].shape
(2, 2)
>>> x['b'].shape
(2, 2, 3, 3)

存取多個欄位#

可以使用多欄位索引對結構化陣列進行索引和賦值,其中索引是欄位名稱列表。

警告

多欄位索引的行為從 Numpy 1.15 變更為 Numpy 1.16。

使用多欄位索引進行索引的結果是原始陣列的視圖,如下所示

>>> a = np.zeros(3, dtype=[('a', 'i4'), ('b', 'i4'), ('c', 'f4')])
>>> a[['a', 'c']]
array([(0, 0.), (0, 0.), (0, 0.)],
     dtype={'names': ['a', 'c'], 'formats': ['<i4', '<f4'], 'offsets': [0, 8], 'itemsize': 12})

賦值給視圖會修改原始陣列。視圖的欄位將按照它們被索引的順序排列。請注意,與單欄位索引不同,視圖的 dtype 與原始陣列具有相同的 itemsize,並且欄位與原始陣列中的偏移量相同,而未索引的欄位僅僅是遺失了。

警告

在 Numpy 1.15 中,使用多欄位索引索引陣列會傳回上述結果的副本,但欄位在記憶體中打包在一起,就像透過 numpy.lib.recfunctions.repack_fields 傳遞一樣。

從 Numpy 1.16 開始的新行為導致與 1.15 相比,未索引欄位的位置有額外的「填充」位元組。您需要更新任何依賴於資料具有「打包」佈局的程式碼。例如,如下程式碼

>>> a[['a', 'c']].view('i8')  # Fails in Numpy 1.16
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
ValueError: When changing to a smaller dtype, its size must be a divisor of the size of original dtype

將需要變更。此程式碼自 Numpy 1.12 以來已引發 FutureWarning,類似的程式碼自 1.7 以來已引發 FutureWarning

在 1.16 中,numpy.lib.recfunctions 模組中引入了許多函式,以幫助使用者解決此變更。這些函式是 numpy.lib.recfunctions.repack_fieldsnumpy.lib.recfunctions.structured_to_unstructurednumpy.lib.recfunctions.unstructured_to_structurednumpy.lib.recfunctions.apply_along_fieldsnumpy.lib.recfunctions.assign_fields_by_namenumpy.lib.recfunctions.require_fields

函式 numpy.lib.recfunctions.repack_fields 始終可以用於重現舊行為,因為它將傳回結構化陣列的打包副本。例如,上面的程式碼可以用以下程式碼替換

>>> from numpy.lib.recfunctions import repack_fields
>>> repack_fields(a[['a', 'c']]).view('i8')  # supported in 1.16
array([0, 0, 0])

此外,numpy 現在提供了一個新函式 numpy.lib.recfunctions.structured_to_unstructured,對於希望將結構化陣列轉換為非結構化陣列的使用者來說,這是一個更安全、更有效率的替代方案,因為上面的視圖通常旨在做到這一點。此函式允許安全地轉換為考慮填充的非結構化型別,通常避免複製,並且還會根據需要轉換資料型別,這與視圖不同。如下程式碼

>>> b = np.zeros(3, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')])
>>> b[['x', 'z']].view('f4')
array([0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)

可以透過替換為以下程式碼來使其更安全

>>> from numpy.lib.recfunctions import structured_to_unstructured
>>> structured_to_unstructured(b[['x', 'z']])
array([[0., 0.],
       [0., 0.],
       [0., 0.]], dtype=float32)

賦值給具有多欄位索引的陣列會修改原始陣列

>>> a[['a', 'c']] = (2, 3)
>>> a
array([(2, 0, 3.), (2, 0, 3.), (2, 0, 3.)],
      dtype=[('a', '<i4'), ('b', '<i4'), ('c', '<f4')])

這符合上面描述的結構化陣列賦值規則。例如,這意味著可以使用適當的多欄位索引來交換兩個欄位的值

>>> a[['a', 'c']] = a[['c', 'a']]

使用整數索引取得結構化純量#

索引結構化陣列的單個元素(使用整數索引)會傳回結構化純量

>>> x = np.array([(1, 2., 3.)], dtype='i, f, f')
>>> scalar = x[0]
>>> scalar
np.void((1, 2.0, 3.0), dtype=[('f0', '<i4'), ('f1', '<f4'), ('f2', '<f4')])
>>> type(scalar)
<class 'numpy.void'>

與其他 numpy 純量不同,結構化純量是可變的,並且充當原始陣列的視圖,因此修改純量將修改原始陣列。結構化純量也支援依欄位名稱進行存取和賦值

>>> x = np.array([(1, 2), (3, 4)], dtype=[('foo', 'i8'), ('bar', 'f4')])
>>> s = x[0]
>>> s['bar'] = 100
>>> x
array([(1, 100.), (3, 4.)],
      dtype=[('foo', '<i8'), ('bar', '<f4')])

與元組類似,結構化純量也可以使用整數進行索引

>>> scalar = np.array([(1, 2., 3.)], dtype='i, f, f')[0]
>>> scalar[0]
np.int32(1)
>>> scalar[1] = 4

因此,元組可以被認為是 numpy 結構化型別的原生 Python 等效項,很像原生 python 整數是 numpy 整數型別的等效項。結構化純量可以透過呼叫 numpy.ndarray.item 轉換為元組

>>> scalar.item(), type(scalar.item())
((1, 4.0, 3.0), <class 'tuple'>)

檢視包含物件的結構化陣列#

為了防止損壞 object 型別欄位中的物件指標,numpy 目前不允許檢視包含物件的結構化陣列。

結構比較和提升#

如果兩個 void 結構化陣列的 dtype 相等,則測試陣列的相等性將產生一個布林陣列,其維度與原始陣列相同,其中元素設定為 True,表示對應結構的所有欄位都相等

>>> a = np.array([(1, 1), (2, 2)], dtype=[('a', 'i4'), ('b', 'i4')])
>>> b = np.array([(1, 1), (2, 3)], dtype=[('a', 'i4'), ('b', 'i4')])
>>> a == b
array([True, False])

NumPy 將提升個別欄位資料型別以執行比較。因此,以下程式碼也是有效的(請注意 'a' 欄位的 'f4' dtype)

>>> b = np.array([(1.0, 1), (2.5, 2)], dtype=[("a", "f4"), ("b", "i4")])
>>> a == b
array([True, False])

若要比較兩個結構化陣列,必須可以將它們提升為 numpy.result_typenumpy.promote_types 傳回的通用 dtype。這強制執行欄位數、欄位名稱和欄位標題必須完全匹配。當無法進行提升時(例如由於欄位名稱不符),NumPy 將引發錯誤。兩個結構化 dtype 之間的提升會產生一個標準 dtype,以確保所有欄位的原生位元組順序

>>> np.result_type(np.dtype("i,>i"))
dtype([('f0', '<i4'), ('f1', '<i4')])
>>> np.result_type(np.dtype("i,>i"), np.dtype("i,i"))
dtype([('f0', '<i4'), ('f1', '<i4')])

提升產生的 dtype 也保證是打包的,這意味著所有欄位都連續排序,並且移除了任何不必要的填充

>>> dt = np.dtype("i1,V3,i4,V1")[["f0", "f2"]]
>>> dt
dtype({'names': ['f0', 'f2'], 'formats': ['i1', '<i4'], 'offsets': [0, 4], 'itemsize': 9})
>>> np.result_type(dt)
dtype([('f0', 'i1'), ('f2', '<i4')])

請注意,結果列印時沒有 offsetsitemsize,表示沒有額外的填充。如果使用 align=True 建立結構化 dtype,以確保 dtype.isalignedstruct 為 true,則此屬性會被保留

>>> dt = np.dtype("i1,V3,i4,V1", align=True)[["f0", "f2"]]
>>> dt
dtype({'names': ['f0', 'f2'], 'formats': ['i1', '<i4'], 'offsets': [0, 4], 'itemsize': 12}, align=True)

>>> np.result_type(dt)
dtype([('f0', 'i1'), ('f2', '<i4')], align=True)
>>> np.result_type(dt).isalignedstruct
True

當提升多個 dtype 時,如果任何輸入是對齊的,則結果也是對齊的

>>> np.result_type(np.dtype("i,i"), np.dtype("i,i", align=True))
dtype([('f0', '<i4'), ('f1', '<i4')], align=True)

當比較 void 結構化陣列時,<> 運算子始終傳回 False,並且不支援算術和位元運算。

在 1.23 版本中變更:在 NumPy 1.23 之前,當提升為通用 dtype 失敗時,會發出警告並傳回 False。此外,提升的限制性要高得多:它會拒絕上面的混合浮點數/整數比較範例。

記錄陣列#

作為一個可選的便利功能,numpy 提供了一個 ndarray 子類別 numpy.recarray,它允許透過屬性而不是僅透過索引來存取結構化陣列的欄位。記錄陣列使用特殊的資料型別 numpy.record,它允許透過從陣列取得的結構化純量上的屬性來存取欄位。numpy.rec 模組提供了從各種物件建立記錄陣列的函式。在 numpy.lib.recfunctions 中可以找到用於建立和操作結構化陣列的其他輔助函式。

建立記錄陣列的最簡單方法是使用 numpy.rec.array

>>> recordarr = np.rec.array([(1, 2., 'Hello'), (2, 3., "World")],
...                    dtype=[('foo', 'i4'),('bar', 'f4'), ('baz', 'S10')])
>>> recordarr.bar
array([2., 3.], dtype=float32)
>>> recordarr[1:2]
rec.array([(2, 3., b'World')],
      dtype=[('foo', '<i4'), ('bar', '<f4'), ('baz', 'S10')])
>>> recordarr[1:2].foo
array([2], dtype=int32)
>>> recordarr.foo[1:2]
array([2], dtype=int32)
>>> recordarr[1].baz
b'World'

numpy.rec.array 可以將各種引數轉換為記錄陣列,包括結構化陣列

>>> arr = np.array([(1, 2., 'Hello'), (2, 3., "World")],
...             dtype=[('foo', 'i4'), ('bar', 'f4'), ('baz', 'S10')])
>>> recordarr = np.rec.array(arr)

numpy.rec 模組提供了許多其他便利函式來建立記錄陣列,請參閱記錄陣列建立常式

可以使用適當的 view 取得結構化陣列的記錄陣列表示形式

>>> arr = np.array([(1, 2., 'Hello'), (2, 3., "World")],
...                dtype=[('foo', 'i4'),('bar', 'f4'), ('baz', 'S10')])
>>> recordarr = arr.view(dtype=np.dtype((np.record, arr.dtype)),
...                      type=np.recarray)

為了方便起見,將 ndarray 檢視為型別 numpy.recarray 將自動轉換為 numpy.record 資料型別,因此 dtype 可以從視圖中省略

>>> recordarr = arr.view(np.recarray)
>>> recordarr.dtype
dtype((numpy.record, [('foo', '<i4'), ('bar', '<f4'), ('baz', 'S10')]))

若要返回純 ndarray,則必須重設 dtype 和型別。以下視圖執行此操作,同時考慮到 recordarr 不是結構化型別的異常情況

>>> arr2 = recordarr.view(recordarr.dtype.fields or recordarr.dtype, np.ndarray)

依索引或屬性存取的記錄陣列欄位,如果欄位具有結構化型別,則傳回記錄陣列,否則傳回純 ndarray。

>>> recordarr = np.rec.array([('Hello', (1, 2)), ("World", (3, 4))],
...                 dtype=[('foo', 'S6'),('bar', [('A', int), ('B', int)])])
>>> type(recordarr.foo)
<class 'numpy.ndarray'>
>>> type(recordarr.bar)
<class 'numpy.rec.recarray'>

請注意,如果欄位的名稱與 ndarray 屬性的名稱相同,則 ndarray 屬性優先。此類欄位將無法透過屬性存取,但仍然可以透過索引存取。

Recarray 輔助函式#

用於操作結構化陣列的工具集合。

這些函式中的大多數最初是由 John Hunter 為 matplotlib 實作的。為了方便起見,它們已被重寫和擴展。

numpy.lib.recfunctions.append_fields(base, names, data, dtypes=None, fill_value=-1, usemask=True, asrecarray=False)[來源]#

將新欄位新增到現有陣列。

欄位的名稱由 names 引數給定,對應的值由 data 引數給定。如果附加單個欄位,則 namesdatadtypes 不必是列表,而只需是值即可。

參數:
base陣列

要擴展的輸入陣列。

names字串、序列

字串或字串序列,對應於新欄位的名稱。

data陣列或陣列序列

儲存要新增到 base 的欄位的陣列或陣列序列。

dtypes資料型別序列,可選

資料型別或資料型別序列。如果為 None,則資料型別會從 data 估算。

fill_value{float},可選

用於填充較短陣列上遺失資料的填充值。

usemask{False, True},可選

是否傳回遮罩陣列。

asrecarray{False, True},可選

是否傳回 recarray (MaskedRecords)。

numpy.lib.recfunctions.apply_along_fields(func, arr)[來源]#

將函式 ‘func’ 作為結構化陣列欄位之間的縮減應用。

這與 numpy.apply_along_axis 類似,但將結構化陣列的欄位視為額外的軸。這些欄位會先根據 numpy.result_type 應用於欄位 dtype 的型別提升規則,轉換為通用型別。

參數:
func函式 (function)

要應用於「欄位」維度的函式。此函式必須支援 axis 引數,例如 numpy.meannumpy.sum 等。

arrndarray

要應用 func 的結構化陣列。

回傳值:
outndarray

縮減運算的結果

範例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> b = np.array([(1, 2, 5), (4, 5, 7), (7, 8 ,11), (10, 11, 12)],
...              dtype=[('x', 'i4'), ('y', 'f4'), ('z', 'f8')])
>>> rfn.apply_along_fields(np.mean, b)
array([ 2.66666667,  5.33333333,  8.66666667, 11.        ])
>>> rfn.apply_along_fields(np.mean, b[['x', 'z']])
array([ 3. ,  5.5,  9. , 11. ])
numpy.lib.recfunctions.assign_fields_by_name(dst, src, zero_unassigned=True)[source]#

依欄位名稱將值從一個結構化陣列指派到另一個。

在 numpy >= 1.14 中,通常將一個結構化陣列指派到另一個時,會「依位置」複製欄位,這表示 src 的第一個欄位會複製到 dst 的第一個欄位,依此類推,而與欄位名稱無關。

此函式改為「依欄位名稱」複製,使得 dst 中的欄位從 src 中名稱相同的欄位指派值。這會以遞迴方式應用於巢狀結構。這是 numpy >= 1.6 到 <= 1.13 中結構指派的運作方式。

參數:
dstndarray
srcndarray

指派期間的來源和目的地陣列。

zero_unassignedbool,選用

若為 True,則 dst 中在 src 中沒有相符欄位的欄位會以值 0(零)填滿。這是 numpy <= 1.13 的行為。若為 False,則不會修改這些欄位。

numpy.lib.recfunctions.drop_fields(base, drop_names, usemask=True, asrecarray=False)[source]#

傳回一個新陣列,其中已捨棄 drop_names 中的欄位。

支援巢狀欄位。

參數:
base陣列

輸入陣列

drop_names字串或序列

字串或字串序列,對應於要捨棄的欄位名稱。

usemask{False, True},可選

是否傳回遮罩陣列。

asrecarray字串或序列,選用

是否傳回 recarray 或 mrecarray (asrecarray=True),或是具有彈性 dtype 的純 ndarray 或遮罩陣列。預設值為 False。

範例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> a = np.array([(1, (2, 3.0)), (4, (5, 6.0))],
...   dtype=[('a', np.int64), ('b', [('ba', np.double), ('bb', np.int64)])])
>>> rfn.drop_fields(a, 'a')
array([((2., 3),), ((5., 6),)],
      dtype=[('b', [('ba', '<f8'), ('bb', '<i8')])])
>>> rfn.drop_fields(a, 'ba')
array([(1, (3,)), (4, (6,))], dtype=[('a', '<i8'), ('b', [('bb', '<i8')])])
>>> rfn.drop_fields(a, ['ba', 'bb'])
array([(1,), (4,)], dtype=[('a', '<i8')])
numpy.lib.recfunctions.find_duplicates(a, key=None, ignoremask=True, return_index=False)[source]#

沿著給定的鍵 (key) 尋找結構化陣列中的重複項

參數:
a類陣列 (array-like)

輸入陣列

key{字串 (string), None},選用

要沿其檢查重複項的欄位名稱。若為 None,則依記錄執行搜尋

ignoremask{True, False},選用

是否應捨棄遮罩資料,或將其視為重複項。

return_index{False, True},選用

是否傳回重複值的索引。

範例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> ndtype = [('a', int)]
>>> a = np.ma.array([1, 1, 1, 2, 2, 3, 3],
...         mask=[0, 0, 1, 0, 0, 0, 1]).view(ndtype)
>>> rfn.find_duplicates(a, ignoremask=True, return_index=True)
(masked_array(data=[(1,), (1,), (2,), (2,)],
             mask=[(False,), (False,), (False,), (False,)],
       fill_value=(999999,),
            dtype=[('a', '<i8')]), array([0, 1, 3, 4]))
numpy.lib.recfunctions.flatten_descr(ndtype)[source]#

展平結構化資料型別描述。

範例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> ndtype = np.dtype([('a', '<i4'), ('b', [('ba', '<f8'), ('bb', '<i4')])])
>>> rfn.flatten_descr(ndtype)
(('a', dtype('int32')), ('ba', dtype('float64')), ('bb', dtype('int32')))
numpy.lib.recfunctions.get_fieldstructure(adtype, lastname=None, parents=None)[source]#

傳回一個字典,其中欄位會索引其父欄位的清單。

此函式用於簡化對巢狀於其他欄位中的欄位的存取。

參數:
adtypenp.dtype

輸入資料型別

lastname選用

上次處理的欄位名稱(在遞迴期間於內部使用)。

parents字典 (dictionary)

父欄位的字典(在遞迴期間於內部使用)。

範例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> ndtype =  np.dtype([('A', int),
...                     ('B', [('BA', int),
...                            ('BB', [('BBA', int), ('BBB', int)])])])
>>> rfn.get_fieldstructure(ndtype)
... # XXX: possible regression, order of BBA and BBB is swapped
{'A': [], 'B': [], 'BA': ['B'], 'BB': ['B'], 'BBA': ['B', 'BB'], 'BBB': ['B', 'BB']}
numpy.lib.recfunctions.get_names(adtype)[source]#

以元組 (tuple) 形式傳回輸入資料型別的欄位名稱。輸入資料型別必須具有欄位,否則會引發錯誤。

參數:
adtypedtype

輸入資料型別

範例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> rfn.get_names(np.empty((1,), dtype=[('A', int)]).dtype)
('A',)
>>> rfn.get_names(np.empty((1,), dtype=[('A',int), ('B', float)]).dtype)
('A', 'B')
>>> adtype = np.dtype([('a', int), ('b', [('ba', int), ('bb', int)])])
>>> rfn.get_names(adtype)
('a', ('b', ('ba', 'bb')))
numpy.lib.recfunctions.get_names_flat(adtype)[source]#

以元組形式傳回輸入資料型別的欄位名稱。輸入資料型別必須具有欄位,否則會引發錯誤。巢狀結構會事先展平。

參數:
adtypedtype

輸入資料型別

範例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> rfn.get_names_flat(np.empty((1,), dtype=[('A', int)]).dtype) is None
False
>>> rfn.get_names_flat(np.empty((1,), dtype=[('A',int), ('B', str)]).dtype)
('A', 'B')
>>> adtype = np.dtype([('a', int), ('b', [('ba', int), ('bb', int)])])
>>> rfn.get_names_flat(adtype)
('a', 'b', 'ba', 'bb')
numpy.lib.recfunctions.join_by(key, r1, r2, jointype='inner', r1postfix='1', r2postfix='2', defaults=None, usemask=True, asrecarray=False)[source]#

在鍵 key 上聯結陣列 r1r2

鍵應為字串或字串序列,對應於用於聯結陣列的欄位。若在兩個輸入陣列中都找不到 key 欄位,則會引發例外。沿著 keyr1r2 都不應有任何重複項:重複項的存在會使輸出非常不可靠。請注意,演算法不會尋找重複項。

參數:
key{字串 (string), 序列 (sequence)}

字串或字串序列,對應於用於比較的欄位。

r1, r2陣列 (arrays)

結構化陣列。

jointype{‘inner’, ‘outer’, ‘leftouter’},選用

若為 ‘inner’,則傳回 r1 和 r2 共有的元素。若為 ‘outer’,則傳回共有元素,以及 r1 中不在 r2 中的元素,以及不在 r2 中的元素。若為 ‘leftouter’,則傳回共有元素和 r1 中不在 r2 中的元素。

r1postfix字串 (string),選用

附加到 r1 的欄位名稱的字串,這些欄位存在於 r2 中,但不存在於鍵中。

r2postfix字串 (string),選用

附加到 r2 的欄位名稱的字串,這些欄位存在於 r1 中,但不存在於鍵中。

defaults{字典 (dictionary)},選用

將欄位名稱對應到對應預設值的字典。

usemask{True, False},選用

是否傳回 MaskedArray(或若 asrecarray==True 則為 MaskedRecords)或 ndarray。

asrecarray{False, True},可選

是否傳回 recarray(或若 usemask==True 則為 MaskedRecords)或僅為彈性型別 ndarray。

註記

  • 輸出會沿著鍵排序。

  • 會形成一個暫時陣列,方法是捨棄兩個陣列中不在鍵中的欄位,並串連結果。然後會排序此陣列,並選取共有的項目。輸出是透過以選取的項目填滿欄位來建構的。如果有一些重複項,則不會保留相符項…

numpy.lib.recfunctions.merge_arrays(seqarrays, fill_value=-1, flatten=False, usemask=False, asrecarray=False)[source]#

依欄位逐欄位合併陣列。

參數:
seqarraysndarray 序列 (sequence of ndarrays)

陣列序列

fill_value{float},可選

用於填充較短陣列上遺失資料的填充值。

flatten{False, True},選用

是否摺疊巢狀欄位。

usemask{False, True},可選

是否傳回遮罩陣列。

asrecarray{False, True},可選

是否傳回 recarray (MaskedRecords)。

註記

  • 若沒有遮罩,遺失值會以某些值填滿,具體取決於其對應的型別

    • -1 代表整數

    • -1.0 代表浮點數

    • '-' 代表字元

    • '-1' 代表字串

    • True 代表布林值

  • XXX:我只是憑經驗獲得這些值

範例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> rfn.merge_arrays((np.array([1, 2]), np.array([10., 20., 30.])))
array([( 1, 10.), ( 2, 20.), (-1, 30.)],
      dtype=[('f0', '<i8'), ('f1', '<f8')])
>>> rfn.merge_arrays((np.array([1, 2], dtype=np.int64),
...         np.array([10., 20., 30.])), usemask=False)
 array([(1, 10.0), (2, 20.0), (-1, 30.0)],
         dtype=[('f0', '<i8'), ('f1', '<f8')])
>>> rfn.merge_arrays((np.array([1, 2]).view([('a', np.int64)]),
...               np.array([10., 20., 30.])),
...              usemask=False, asrecarray=True)
rec.array([( 1, 10.), ( 2, 20.), (-1, 30.)],
          dtype=[('a', '<i8'), ('f1', '<f8')])
numpy.lib.recfunctions.rec_append_fields(base, names, data, dtypes=None)[source]#

將新欄位新增到現有陣列。

欄位的名稱由 names 引數給定,對應的值由 data 引數給定。如果附加單個欄位,則 namesdatadtypes 不必是列表,而只需是值即可。

參數:
base陣列

要擴展的輸入陣列。

names字串、序列

字串或字串序列,對應於新欄位的名稱。

data陣列或陣列序列

儲存要新增到 base 的欄位的陣列或陣列序列。

dtypes資料型別序列,可選

資料型別或資料型別序列。如果為 None,則資料型別會從 data 估算。

回傳值:
appended_arraynp.recarray

另請參閱

append_fields
numpy.lib.recfunctions.rec_drop_fields(base, drop_names)[source]#

傳回一個新的 numpy.recarray,其中已捨棄 drop_names 中的欄位。

numpy.lib.recfunctions.rec_join(key, r1, r2, jointype='inner', r1postfix='1', r2postfix='2', defaults=None)[source]#

在鍵上聯結陣列 r1r2。join_by 的替代方案,永遠傳回 np.recarray。

另請參閱

join_by

等效函式

numpy.lib.recfunctions.recursive_fill_fields(input, output)[source]#

使用來自輸入的欄位填滿輸出的欄位,並支援巢狀結構。

參數:
inputndarray

輸入陣列。

outputndarray

輸出陣列。

註記

  • output 應至少與 input 大小相同

範例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> a = np.array([(1, 10.), (2, 20.)], dtype=[('A', np.int64), ('B', np.float64)])
>>> b = np.zeros((3,), dtype=a.dtype)
>>> rfn.recursive_fill_fields(a, b)
array([(1, 10.), (2, 20.), (0,  0.)], dtype=[('A', '<i8'), ('B', '<f8')])
numpy.lib.recfunctions.rename_fields(base, namemapper)[source]#

重新命名彈性資料型別 ndarray 或 recarray 中的欄位。

支援巢狀欄位。

參數:
basendarray

必須修改其欄位的輸入陣列。

namemapper字典 (dictionary)

將舊欄位名稱對應到其新版本的字典。

範例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> a = np.array([(1, (2, [3.0, 30.])), (4, (5, [6.0, 60.]))],
...   dtype=[('a', int),('b', [('ba', float), ('bb', (float, 2))])])
>>> rfn.rename_fields(a, {'a':'A', 'bb':'BB'})
array([(1, (2., [ 3., 30.])), (4, (5., [ 6., 60.]))],
      dtype=[('A', '<i8'), ('b', [('ba', '<f8'), ('BB', '<f8', (2,))])])
numpy.lib.recfunctions.repack_fields(a, align=False, recurse=False)[source]#

重新封裝記憶體中結構化陣列或 dtype 的欄位。

結構化資料型別的記憶體配置允許欄位位於任意位元組偏移量。這表示欄位可以被填補位元組分隔,它們的偏移量可以是非單調遞增的,而且它們可以重疊。

此方法會移除任何重疊並重新排序記憶體中的欄位,使其具有遞增的位元組偏移量,並根據 align 選項新增或移除填補位元組,其行為類似於 numpy.dtypealign 選項。

align=False,此方法會產生「封裝」記憶體配置,其中每個欄位都從前一個欄位結束的位元組開始,並移除任何填補位元組。

align=True,此方法會產生「對齊」記憶體配置,其中每個欄位的偏移量都是其對齊方式的倍數,且總項目大小是最大對齊方式的倍數,方法是視需要新增填補位元組。

參數:
andarray 或 dtype

要重新封裝欄位的陣列或 dtype。

align布林值 (boolean)

若為 true,則使用「對齊」記憶體配置,否則使用「封裝」配置。

recurse布林值 (boolean)

若為 True,也會重新封裝巢狀結構。

回傳值:
repackedndarray 或 dtype

重新封裝欄位的 a 副本,或若不需要重新封裝,則為 a 本身。

範例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> def print_offsets(d):
...     print("offsets:", [d.fields[name][1] for name in d.names])
...     print("itemsize:", d.itemsize)
...
>>> dt = np.dtype('u1, <i8, <f8', align=True)
>>> dt
dtype({'names': ['f0', 'f1', 'f2'], 'formats': ['u1', '<i8', '<f8'], 'offsets': [0, 8, 16], 'itemsize': 24}, align=True)
>>> print_offsets(dt)
offsets: [0, 8, 16]
itemsize: 24
>>> packed_dt = rfn.repack_fields(dt)
>>> packed_dt
dtype([('f0', 'u1'), ('f1', '<i8'), ('f2', '<f8')])
>>> print_offsets(packed_dt)
offsets: [0, 1, 9]
itemsize: 17
numpy.lib.recfunctions.require_fields(array, required_dtype)[source]#

使用依欄位名稱指派的方式,將結構化陣列轉換為新的 dtype。

此函式依名稱從舊陣列指派到新陣列,因此輸出陣列中欄位的值是來源陣列中具有相同名稱的欄位的值。這具有建立新 ndarray 的效果,其中僅包含 required_dtype「需要」的欄位。

若 required_dtype 中的欄位名稱在輸入陣列中不存在,則會建立該欄位,並在輸出陣列中設定為 0。

參數:
andarray

要轉換的陣列

required_dtypedtype

輸出陣列的資料型別

回傳值:
outndarray

具有新 dtype 的陣列,其欄位值從輸入陣列中具有相同名稱的欄位複製而來

範例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> a = np.ones(4, dtype=[('a', 'i4'), ('b', 'f8'), ('c', 'u1')])
>>> rfn.require_fields(a, [('b', 'f4'), ('c', 'u1')])
array([(1., 1), (1., 1), (1., 1), (1., 1)],
  dtype=[('b', '<f4'), ('c', 'u1')])
>>> rfn.require_fields(a, [('b', 'f4'), ('newf', 'u1')])
array([(1., 0), (1., 0), (1., 0), (1., 0)],
  dtype=[('b', '<f4'), ('newf', 'u1')])
numpy.lib.recfunctions.stack_arrays(arrays, defaults=None, usemask=True, asrecarray=False, autoconvert=False)[source]#

依欄位逐欄位疊加陣列

參數:
arrays陣列或序列 (array or sequence)

輸入陣列的序列。

defaults字典 (dictionary),選用

將欄位名稱對應到對應預設值的字典。

usemask{True, False},選用

是否傳回 MaskedArray(或若 asrecarray==True 則為 MaskedRecords)或 ndarray。

asrecarray{False, True},可選

是否傳回 recarray(或若 usemask==True 則為 MaskedRecords)或僅為彈性型別 ndarray。

autoconvert{False, True},選用

是否自動將欄位的型別轉換為最大值。

範例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> x = np.array([1, 2,])
>>> rfn.stack_arrays(x) is x
True
>>> z = np.array([('A', 1), ('B', 2)], dtype=[('A', '|S3'), ('B', float)])
>>> zz = np.array([('a', 10., 100.), ('b', 20., 200.), ('c', 30., 300.)],
...   dtype=[('A', '|S3'), ('B', np.double), ('C', np.double)])
>>> test = rfn.stack_arrays((z,zz))
>>> test
masked_array(data=[(b'A', 1.0, --), (b'B', 2.0, --), (b'a', 10.0, 100.0),
                   (b'b', 20.0, 200.0), (b'c', 30.0, 300.0)],
             mask=[(False, False,  True), (False, False,  True),
                   (False, False, False), (False, False, False),
                   (False, False, False)],
       fill_value=(b'N/A', 1e+20, 1e+20),
            dtype=[('A', 'S3'), ('B', '<f8'), ('C', '<f8')])
numpy.lib.recfunctions.structured_to_unstructured(arr, dtype=None, copy=False, casting='unsafe')[source]#

將 n 維結構化陣列轉換為 (n+1) 維非結構化陣列。

新陣列將具有新的最後一個維度,其大小等於輸入陣列的欄位元素數量。若未提供,則輸出資料型別會根據應用於所有欄位資料型別的 numpy 型別提升規則來決定。

巢狀欄位,以及任何子陣列欄位的每個元素,都算作單一欄位元素。

參數:
arrndarray

要轉換的結構化陣列或 dtype。不能包含物件資料型別。

dtypedtype,選用

輸出非結構化陣列的 dtype。

copybool,選用

若為 true,則永遠傳回副本。若為 false,則在 dtype 和欄位的跨距適合,且陣列子型別為 numpy.ndarraynumpy.recarraynumpy.memmap 其中之一時,會傳回檢視。

在 1.25.0 版本中變更:若欄位以統一跨距分隔,現在可以傳回檢視。

casting{‘no’, ‘equiv’, ‘safe’, ‘same_kind’, ‘unsafe’},選用

請參閱 numpy.ndarray.astype 的 casting 引數。控制可能發生的資料型別轉換種類。

回傳值:
unstructuredndarray

維度多一個的非結構化陣列。

範例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> a = np.zeros(4, dtype=[('a', 'i4'), ('b', 'f4,u2'), ('c', 'f4', 2)])
>>> a
array([(0, (0., 0), [0., 0.]), (0, (0., 0), [0., 0.]),
       (0, (0., 0), [0., 0.]), (0, (0., 0), [0., 0.])],
      dtype=[('a', '<i4'), ('b', [('f0', '<f4'), ('f1', '<u2')]), ('c', '<f4', (2,))])
>>> rfn.structured_to_unstructured(a)
array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]])
>>> b = np.array([(1, 2, 5), (4, 5, 7), (7, 8 ,11), (10, 11, 12)],
...              dtype=[('x', 'i4'), ('y', 'f4'), ('z', 'f8')])
>>> np.mean(rfn.structured_to_unstructured(b[['x', 'z']]), axis=-1)
array([ 3. ,  5.5,  9. , 11. ])
numpy.lib.recfunctions.unstructured_to_structured(arr, dtype=None, names=None, align=False, copy=False, casting='unsafe')[source]#

將 n 維非結構化陣列轉換為 (n-1) 維結構化陣列。

輸入陣列的最後一個維度會轉換為結構,其欄位元素數量等於輸入陣列最後一個維度的大小。預設情況下,所有輸出欄位都具有輸入陣列的 dtype,但也可以改為提供具有相等欄位元素數量的輸出結構化 dtype。

巢狀欄位,以及任何子陣列欄位的每個元素,都算作欄位元素數量。

參數:
arrndarray

要轉換的非結構化陣列或 dtype。

dtypedtype,選用

輸出陣列的結構化 dtype

names字串清單 (list of strings),選用

若未提供 dtype,則這會依序指定輸出 dtype 的欄位名稱。欄位 dtype 會與輸入陣列相同。

align布林值 (boolean),選用

是否建立對齊的記憶體配置。

copybool,選用

請參閱 numpy.ndarray.astype 的 copy 引數。若為 true,則永遠傳回副本。若為 false,且符合 dtype 需求,則會傳回檢視。

casting{‘no’, ‘equiv’, ‘safe’, ‘same_kind’, ‘unsafe’},選用

請參閱 numpy.ndarray.astype 的 casting 引數。控制可能發生的資料型別轉換種類。

回傳值:
structuredndarray

維度較少的結構化陣列。

範例

>>> import numpy as np
>>> from numpy.lib import recfunctions as rfn
>>> dt = np.dtype([('a', 'i4'), ('b', 'f4,u2'), ('c', 'f4', 2)])
>>> a = np.arange(20).reshape((4,5))
>>> a
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])
>>> rfn.unstructured_to_structured(a, dt)
array([( 0, ( 1.,  2), [ 3.,  4.]), ( 5, ( 6.,  7), [ 8.,  9.]),
       (10, (11., 12), [13., 14.]), (15, (16., 17), [18., 19.])],
      dtype=[('a', '<i4'), ('b', [('f0', '<f4'), ('f1', '<u2')]), ('c', '<f4', (2,))])