擴展陣列是常規 Arrow Array 物件的包裝器,提供一些自訂的行為和/或儲存方式。擴展類型的一個常見用例是定義 Arrow Array 和 R 物件之間的自訂轉換,當預設轉換速度慢或遺失對陣列中值解釋很重要的 metadata 時。對於大多數類型,內建的 vctrs 擴展類型 可能已足夠。
用法
new_extension_type(
storage_type,
extension_name,
extension_metadata = raw(),
type_class = ExtensionType
)
new_extension_array(storage_array, extension_type)
register_extension_type(extension_type)
reregister_extension_type(extension_type)
unregister_extension_type(extension_name)
參數
- storage_type
底層儲存陣列的 資料類型。
- extension_name
擴展名稱。這應該使用「點」語法進行命名空間劃分(即「some_package.some_type」)。命名空間「arrow」保留給 Apache Arrow 程式庫定義的擴展類型。
- extension_metadata
包含類型序列化版本的
raw()
或character()
向量。字元向量的長度必須為 1,並且在轉換為raw()
之前會先轉換為 UTF-8。- type_class
一個 R6::R6Class,其
$new()
類別方法將用於建構類型的新實例。- storage_array
底層儲存空間的 Array 物件。
- extension_type
一個 ExtensionType 實例。
值
new_extension_type()
根據指定的type_class
傳回 ExtensionType 實例。new_extension_array()
傳回 ExtensionArray,其$type
對應於extension_type
。register_extension_type()
、unregister_extension_type()
和reregister_extension_type()
傳回NULL
,不可見。
詳細資訊
這些函數建立、註冊和取消註冊 ExtensionType 和 ExtensionArray 物件。若要使用擴展類型,您必須
定義一個繼承自 ExtensionType 的 R6::R6Class,並重新實作一個或多個方法(例如,
deserialize_instance()
)。建立一個類型建構子函數(例如,
my_extension_type()
),呼叫new_extension_type()
以建立可用作套件中其他地方 資料類型 的 R6 實例。建立一個陣列建構子函數(例如,
my_extension_array()
),呼叫new_extension_array()
以建立擴展類型的 Array 實例。使用您的建構子函數,使用
register_extension_type()
註冊擴展類型的虛擬實例。
如果在 R 套件中定義擴展類型,您可能會想在該套件的 .onLoad()
hook 中使用 reregister_extension_type()
,因為您的套件在其開發期間可能會在同一個 R 會期中重新載入,並且如果針對相同的 extension_name
呼叫兩次 register_extension_type()
將會出錯。如需使用大多數這些功能的擴展類型範例,請參閱 vctrs_extension_type()
。
範例
# Create the R6 type whose methods control how Array objects are
# converted to R objects, how equality between types is computed,
# and how types are printed.
QuantizedType <- R6::R6Class(
"QuantizedType",
inherit = ExtensionType,
public = list(
# methods to access the custom metadata fields
center = function() private$.center,
scale = function() private$.scale,
# called when an Array of this type is converted to an R vector
as_vector = function(extension_array) {
if (inherits(extension_array, "ExtensionArray")) {
unquantized_arrow <-
(extension_array$storage()$cast(float64()) / private$.scale) +
private$.center
as.vector(unquantized_arrow)
} else {
super$as_vector(extension_array)
}
},
# populate the custom metadata fields from the serialized metadata
deserialize_instance = function() {
vals <- as.numeric(strsplit(self$extension_metadata_utf8(), ";")[[1]])
private$.center <- vals[1]
private$.scale <- vals[2]
}
),
private = list(
.center = NULL,
.scale = NULL
)
)
# Create a helper type constructor that calls new_extension_type()
quantized <- function(center = 0, scale = 1, storage_type = int32()) {
new_extension_type(
storage_type = storage_type,
extension_name = "arrow.example.quantized",
extension_metadata = paste(center, scale, sep = ";"),
type_class = QuantizedType
)
}
# Create a helper array constructor that calls new_extension_array()
quantized_array <- function(x, center = 0, scale = 1,
storage_type = int32()) {
type <- quantized(center, scale, storage_type)
new_extension_array(
Array$create((x - center) * scale, type = storage_type),
type
)
}
# Register the extension type so that Arrow knows what to do when
# it encounters this extension type
reregister_extension_type(quantized())
# Create Array objects and use them!
(vals <- runif(5, min = 19, max = 21))
#> [1] 20.42644 20.32484 20.21635 20.83541 19.04193
(array <- quantized_array(
vals,
center = 20,
scale = 2^15 - 1,
storage_type = int16()
)
)
#> ExtensionArray
#> <QuantizedType <20;32767>>
#> [
#> 13973,
#> 10643,
#> 7089,
#> 27373,
#> -31393
#> ]
array$type$center()
#> [1] 20
array$type$scale()
#> [1] 32767
as.vector(array)
#> [1] 20.42644 20.32481 20.21635 20.83538 19.04193