我有一堆换行符分隔的 JSON 文件,我想使用
R
包读入 arrow
。
文件中的一个参数是嵌套的。潜在的嵌套值非常大且混乱,我宁愿只选择我实际需要的嵌套参数。
这是我正在使用的数据示例:
# Bring in libraries
suppressMessages(library(arrow))
suppressMessages(library(data.table))
# Make data
tf <- tempfile()
on.exit(unlink(tf))
writeLines('
{ "hello": 3.5, "world": false, "yo":{"param1":"duck1","param2":"duck2"} }
{ "hello": 3.25, "world": null, "yo":{"param1":"duck3","param2":"duck4"} }
{ "hello": 0.0, "world": true, "yo":{"param1":"duck5","param2":"duck6"} }
', tf, useBytes = TRUE)
df <- read_json_arrow(tf)
这是我刚刚读到的结果:
read_json_arrow(tf, col_select = "yo")
我也可以在“哟”栏里看书。结果如下:
但是我无法读取“yo.param1”数据元素:
关于我如何阅读这个嵌套的专栏并避免阅读整个专栏有什么想法吗?
当您使用
read_*
函数读入一个对象时,您正在将它们作为箭头表读入,这些表存储在内存中。 Arrow 是围绕执行零复制操作而设计的,这意味着如果您可以直接操作 Arrow 对象而不是将它们拉入 R,这应该有助于在处理较大的对象时不创建对象的中间副本和破坏您的 R 会话。
我有一个潜在的解决方案,它涉及到使用 Arrow 对象直到将数据拉入 R 的最后一刻,尽管它不是最优雅的。
# Bring in libraries
suppressMessages(library(arrow))
# Make data
tf <- tempfile()
on.exit(unlink(tf))
writeLines('
{ "hello": 3.5, "world": false, "yo":{"param1":"duck1","param2":"duck2"} }
{ "hello": 3.25, "world": null, "yo":{"param1":"duck3","param2":"duck4"} }
{ "hello": 0.0, "world": true, "yo":{"param1":"duck5","param2":"duck6"} }
', tf, useBytes = TRUE)
# read in the JSON table as an Arrow Table
my_tbl <- read_json_arrow(tf, col_select = c("hello", "world"), as_data_frame = FALSE)
complex_cols <- read_json_arrow(tf, col_select = "yo", as_data_frame = FALSE)
# subselect the "yo" column - this is an Arrow ChunkedArray object
# containing a Struct at position 0
yo_col <- complex_cols[["yo"]]
yo_col
#> ChunkedArray
#> <struct<param1: string, param2: string>>
#> [
#> -- is_valid: all not null
#> -- child 0 type: string
#> [
#> "duck1",
#> "duck3",
#> "duck5"
#> ]
#> -- child 1 type: string
#> [
#> "duck2",
#> "duck4",
#> "duck6"
#> ]
#> ]
# extract the Struct by passing in the chunk number
sa <- yo_col$chunk(0)
sa
#> StructArray
#> <struct<param1: string, param2: string>>
#> -- is_valid: all not null
#> -- child 0 type: string
#> [
#> "duck1",
#> "duck3",
#> "duck5"
#> ]
#> -- child 1 type: string
#> [
#> "duck2",
#> "duck4",
#> "duck6"
#> ]
# extract the "param1" column from the Struct
param1_col <- sa[["param1"]]
param1_col
#> Array
#> <string>
#> [
#> "duck1",
#> "duck3",
#> "duck5"
#> ]
# Add the param1 column to the original Table
my_tbl[["param1"]] = param1_col
my_tbl
#> Table
#> 3 rows x 3 columns
#> $hello <double>
#> $world <bool>
#> $param1 <string>
# now pull the table into R
dplyr::collect(my_tbl)
#> # A tibble: 3 × 3
#> hello world param1
#> <dbl> <lgl> <chr>
#> 1 3.5 FALSE duck1
#> 2 3.25 NA duck3
#> 3 0 TRUE duck5
我一直在寻找如何直接在 tidyverse 中完成此操作(我们在 tidyverse 设计之后模拟了很多箭头包设计),但我看到的许多解决方案都涉及在
purrr::map()
中运行 dplyr::select()
,这是一个工作流程目前没有在箭头中实现,我不知道它是否可能。如果您确实想提出功能请求,请随时在回购协议上开票。
最后一点:在上面的示例中,这可能不会对内存占用产生太大影响,但是如果您有很多嵌套项目要拉出并重新组装到一个表中,那么您可能会看到更多好处。