【发布时间】:2020-04-07 05:50:41
【问题描述】:
似乎tidyjson 在嵌套数组上使用了类似 inner-join 的行为,因此删除了具有空子数组的记录。有没有办法获得类似 left-join 的行为,用NAs 填充?
例如,这些假数据有一条记录,其中包含一个填充的嵌套数组 (middles),还有两条记录,其中middles 为空:
library(tidyjson)
people <- c('{"age": 32, "name": [{"first": "Bob", "last": "Smith", "middles":[{"middle1":"John", "middle2":"Rick"}]}]}',
'{"age": 54, "name": [{"first": "Susan", "last": "Doe", "middles":[]}]}',
'{"age": 18, "name": [{"first": "Ann", "last": "Jones", "middles":[]}]}')
从这些数据中,我希望有一个数据框,其中保留了所有父记录并缺少用NAs(〜左连接)填充的子数组信息:
# A tibble: 3 x 5
age first last middle1 middle2
<dbl> <chr> <chr> <chr> <chr>
1 32 Bob Smith John Rick
2 54 Susan Doe NA NA
3 18 Ann Jones NA NA
但是,提取包含一些空子数组的嵌套数组会导致丢失其父级的信息(~ 内连接):
people %>%
spread_all() %>%
enter_object("name") %>% gather_array() %>%
spread_all() %>% select(-document.id,-array.index) %>%
enter_object("middles") %>% gather_array %>%
spread_all() %>% select(-array.index) %>%
tbl_df()
# A tibble: 1 x 5
age first last middle1 middle2
<dbl> <chr> <chr> <chr> <chr>
1 32 Bob Smith John Rick
有没有办法避免这种情况;即,即使子数组为空,也要保留所有行?
解决方法,但不是解决方案
一种可能的解决方法是从字面上进行左连接,但这意味着复制 JSON 读取,考虑到千兆字节的数据,这并非易事。
wrap_dplyr_verb <- function(dplyr.verb) {
# Creates a tidyjson verb out of a dplyr verb
# https://github.com/colearendt/tidyjson/blob/master/R/tbl_json.R
function(.data, ...) {
# Check if reserved ..JSON name already in data.frame
if ("..JSON" %in% names(.data))
stop("'..JSON' in the column names of tbl_json object being filtered")
# Assign JSON to the data.frame so it is treated as any other column
.data$..JSON <- attr(.data, "JSON")
# Apply the transformation
y <- dplyr.verb(dplyr::as_tibble(.data), ...)
# Reconstruct tbl_json without ..JSON column
tbl_json(dplyr::select(y, -..JSON), y$..JSON)
}
}
left_join_json = wrap_dplyr_verb(left_join)
people %>%
spread_all() %>%
enter_object("name") %>% gather_array() %>%
spread_all() %>% select(-document.id,-array.index) %>%
left_join_json(
people %>%
spread_all() %>%
enter_object("name") %>% gather_array() %>%
spread_all() %>% select(-document.id,-array.index) %>%
enter_object("middles") %>% gather_array %>%
spread_all() %>% select(-array.index)
) %>%
tbl_df()
Joining, by = c("age", "first", "last")
# A tibble: 3 x 5
age first last middle1 middle2
<dbl> <chr> <chr> <chr> <chr>
1 32 Bob Smith John Rick
2 54 Susan Doe NA NA
3 18 Ann Jones NA NA
【问题讨论】: