nanoarrow#
nanoarrow 的目标是使用 nanoarrow C 库 为 Arrow C 数据 和 Arrow C 流 接口提供最小的有用绑定。
安装#
您可以从 CRAN 安装 nanoarrow 的发布版本:
install.packages("nanoarrow")
您可以从 GitHub 安装 nanoarrow 的开发版本:
# install.packages("remotes")
remotes::install_github("apache/arrow-nanoarrow/r")
如果您能加载包,那就可以开始了!
library(nanoarrow)
示例#
Arrow C 数据和 Arrow C 流接口由三个结构组成:表示数组数据类型的 ArrowSchema,表示数组值的 ArrowArray,以及表示零个或多个具有公共 ArrowSchema 的 ArrowArray 的 ArrowArrayStream。所有这三个都可以通过 nanoarrow R 包封装成 R 对象。
模式#
使用 infer_nanoarrow_schema() 获取与给定 R 向量类型对应的 ArrowSchema 对象;使用 as_nanoarrow_schema() 将对象从其他数据类型表示(例如,arrow R 包 DataType,如 arrow::int32())转换为 ArrowSchema 对象;或者使用 na_XXX() 函数构造它们。
infer_nanoarrow_schema(1:5)
#> <nanoarrow_schema int32>
#> $ format : chr "i"
#> $ name : chr ""
#> $ metadata : list()
#> $ flags : int 2
#> $ children : list()
#> $ dictionary: NULL
as_nanoarrow_schema(arrow::schema(col1 = arrow::float64()))
#> <nanoarrow_schema struct>
#> $ format : chr "+s"
#> $ name : chr ""
#> $ metadata : list()
#> $ flags : int 0
#> $ children :List of 1
#> ..$ col1:<nanoarrow_schema double>
#> .. ..$ format : chr "g"
#> .. ..$ name : chr "col1"
#> .. ..$ metadata : list()
#> .. ..$ flags : int 2
#> .. ..$ children : list()
#> .. ..$ dictionary: NULL
#> $ dictionary: NULL
na_int64()
#> <nanoarrow_schema int64>
#> $ format : chr "l"
#> $ name : chr ""
#> $ metadata : list()
#> $ flags : int 2
#> $ children : list()
#> $ dictionary: NULL
数组#
使用 as_nanoarrow_array() 将对象转换为 ArrowArray 对象
as_nanoarrow_array(1:5)
#> <nanoarrow_array int32[5]>
#> $ length : int 5
#> $ null_count: int 0
#> $ offset : int 0
#> $ buffers :List of 2
#> ..$ :<nanoarrow_buffer validity<bool>[0][0 b]> ``
#> ..$ :<nanoarrow_buffer data<int32>[5][20 b]> `1 2 3 4 5`
#> $ dictionary: NULL
#> $ children : list()
as_nanoarrow_array(data.frame(col1 = c(1.1, 2.2)))
#> <nanoarrow_array struct[2]>
#> $ length : int 2
#> $ null_count: int 0
#> $ offset : int 0
#> $ buffers :List of 1
#> ..$ :<nanoarrow_buffer validity<bool>[0][0 b]> ``
#> $ children :List of 1
#> ..$ col1:<nanoarrow_array double[2]>
#> .. ..$ length : int 2
#> .. ..$ null_count: int 0
#> .. ..$ offset : int 0
#> .. ..$ buffers :List of 2
#> .. .. ..$ :<nanoarrow_buffer validity<bool>[0][0 b]> ``
#> .. .. ..$ :<nanoarrow_buffer data<double>[2][16 b]> `1.1 2.2`
#> .. ..$ dictionary: NULL
#> .. ..$ children : list()
#> $ dictionary: NULL
您可以使用 as.vector() 或 as.data.frame() 恢复对象的 R 表示
array <- as_nanoarrow_array(data.frame(col1 = c(1.1, 2.2)))
as.data.frame(array)
#> col1
#> 1 1.1
#> 2 2.2
尽管在 C 级别,ArrowArray 与 ArrowSchema 是不同的,但在 R 级别,我们尽可能附加一个模式。您可以使用 infer_nanoarrow_schema() 访问附加的模式
infer_nanoarrow_schema(array)
#> <nanoarrow_schema struct>
#> $ format : chr "+s"
#> $ name : chr ""
#> $ metadata : list()
#> $ flags : int 0
#> $ children :List of 1
#> ..$ col1:<nanoarrow_schema double>
#> .. ..$ format : chr "g"
#> .. ..$ name : chr "col1"
#> .. ..$ metadata : list()
#> .. ..$ flags : int 2
#> .. ..$ children : list()
#> .. ..$ dictionary: NULL
#> $ dictionary: NULL
数组流#
创建 ArrowArrayStream 最简单的方法是使用数组列表或可以使用 as_nanoarrow_array() 转换为数组的对象列表
stream <- basic_array_stream(
list(
data.frame(col1 = c(1.1, 2.2)),
data.frame(col1 = c(3.3, 4.4))
)
)
您可以使用 $get_next() 方法从流中拉取批次。最后一个批次将返回 NULL。
stream$get_next()
#> <nanoarrow_array struct[2]>
#> $ length : int 2
#> $ null_count: int 0
#> $ offset : int 0
#> $ buffers :List of 1
#> ..$ :<nanoarrow_buffer validity<bool>[0][0 b]> ``
#> $ children :List of 1
#> ..$ col1:<nanoarrow_array double[2]>
#> .. ..$ length : int 2
#> .. ..$ null_count: int 0
#> .. ..$ offset : int 0
#> .. ..$ buffers :List of 2
#> .. .. ..$ :<nanoarrow_buffer validity<bool>[0][0 b]> ``
#> .. .. ..$ :<nanoarrow_buffer data<double>[2][16 b]> `1.1 2.2`
#> .. ..$ dictionary: NULL
#> .. ..$ children : list()
#> $ dictionary: NULL
stream$get_next()
#> <nanoarrow_array struct[2]>
#> $ length : int 2
#> $ null_count: int 0
#> $ offset : int 0
#> $ buffers :List of 1
#> ..$ :<nanoarrow_buffer validity<bool>[0][0 b]> ``
#> $ children :List of 1
#> ..$ col1:<nanoarrow_array double[2]>
#> .. ..$ length : int 2
#> .. ..$ null_count: int 0
#> .. ..$ offset : int 0
#> .. ..$ buffers :List of 2
#> .. .. ..$ :<nanoarrow_buffer validity<bool>[0][0 b]> ``
#> .. .. ..$ :<nanoarrow_buffer data<double>[2][16 b]> `3.3 4.4`
#> .. ..$ dictionary: NULL
#> .. ..$ children : list()
#> $ dictionary: NULL
stream$get_next()
#> NULL
您可以通过调用 as.data.frame() 或 as.vector() 将所有批次拉取到 data.frame() 中
stream <- basic_array_stream(
list(
data.frame(col1 = c(1.1, 2.2)),
data.frame(col1 = c(3.3, 4.4))
)
)
as.data.frame(stream)
#> col1
#> 1 1.1
#> 2 2.2
#> 3 3.3
#> 4 4.4
消费完流后,应尽快调用 release 方法。这使得流的实现能够以比等待垃圾回收器清理对象更可预测的方式释放可能持有的任何资源(如打开的文件)。
与 arrow 包的集成#
nanoarrow 包为大多数 arrow 包类型实现了 as_nanoarrow_schema()、as_nanoarrow_array() 和 as_nanoarrow_array_stream()。同样,它为 nanoarrow 对象实现了 arrow::as_arrow_array()、arrow::as_record_batch()、arrow::as_arrow_table()、arrow::as_record_batch_reader()、arrow::infer_type()、arrow::as_data_type() 和 arrow::as_schema(),以便您可以将等效的 nanoarrow 对象传递给许多 arrow 函数,反之亦然。