Я работаю с именованными списками с высокой степенью вложенности (после чтения файлов JSON с помощью jsonlite::fromJSON), и мне было очень удобно конвертировать их в то, что я называю «линейным фреймом данных» с помощью unlist %>% tibble::enframe. Это полезно, поскольку позволяет мне выполнять некоторую обработку данных в подмножествах без необходимости использования сложных рекурсивных пользовательских функций.
Однако после того, как я отредактировал данные, я не могу понять, как преобразовать вложенный список из «линейного фрейма данных». Может кто-то помочь мне с этим ?
Вот воспроизводимый фиктивный пример:
lst<-list(
customers=list(
A=1,
B=2,
C=3),
providers=list(
A=1,
D=5),
vehicles=list(
a=NA,
b=NA))
df<-enframe(unlist(lst))
df[grepl(x=df$name,pattern = "vehicles\\.a"),"value"]<-8
#How to reform lst from df ?
lst<-deframe(df) ???





Используя relist
Сначала добавьте необходимые атрибуты с помощью as.relistable.
df <- tibble::enframe(unlist(as.relistable(lst)))
Измените значение в соответствии с вашим условием
df[grepl(x=df$name,pattern = "vehicles\\.a"),"value"] <- 8
Возвращаем список обратно
relist(tibble::deframe(df))
$customers
$customers$A
[1] 1
$customers$B
[1] 2
$customers$C
[1] 3
$providers
$providers$A
[1] 1
$providers$D
[1] 5
$vehicles
$vehicles$a
[1] 8
$vehicles$b
[1] NA
attr(,"class")
[1] "relistable" "list"
Этот ответ работает, если окончательный список должен иметь ту же структуру, что и стартовый список. Теперь у меня есть случай, когда я использую dplyr::filter в фрейме данных для удаления подсписков, а затем я хотел бы преобразовать исходный список без этих подсписков.
Разве это не новый вопрос?
Это зависит от того, что подразумевается под «после того, как я отредактировал данные». В моем случае издание означает не только модификацию, но и подмножество. Если хотите, я могу задать другой вопрос?
Название по-прежнему должно отражать исходную проблему и ответ, но в конечном итоге это ваше решение.
Тогда я открою новый связанный вопрос. Я признаю, что в исходной проблеме явно не упоминалось подмножество.
Может быть, использовать пакет CRAN rjsoncons , чтобы сохранить представление JSON, и использовать JSONPatch для прямого обновления?
## start with `json` rather than `lst`
json = jsonlite::toJSON(lst, auto_unbox = TRUE)
Вот операция исправления
library(rjsoncons)
op = '[{"op": "replace", "path": "/vehicles/a", "value": 8}]'
json_patched = j_patch_apply(json, op)
Это приводит к
> json_patched |> noquote()
[1] {"customers":{"A":1,"B":2,"C":3},"providers":{"A":1,"D":5},"vehicles":{"a":8,"b":null}}
Функция j_patch_op() помогает сформулировать/проверить операцию.
op = j_patch_op("replace", "/vehicles/a", value = 8, auto_unbox = TRUE)
Патчи могут включать в себя несколько преобразований, как описано на j_patch_opстранице справки и в виньетке
Это предложение подходит для нескольких конкретных модификаций. В моем случае я хотел бы удалить некоторые элементы или подсписки, используя фильтр в фрейме данных после удаления %>% enframe.
Несмотря на то, что здесь используется рекурсивный подход, {purrr} , возможно, все же стоит посмотреть. Ваш пример можно решить с помощью
lst |> assign_in(where = c("vehicles", "a"), 8)(см. шпаргалку).