#r #vega-lite #vega
Вопрос:
Как бы вы взяли дерево вложенных списков R и напечатали их таким образом, чтобы их можно было оценить как код?
Например, представьте, что у нас есть следующий код списка:
spec <- list(
description="An mtcards example",
data = list(),
mark = "point",
encoding = list(
x = list(field = "wt", type="quantitative"),
y = list(field="mpg", type="quantitative"),
color = list(field="cyl", type="nominal")))
Существует ли функция f
(либо в стандартной библиотеке, либо где-нибудь в CRAN), которая f(spec)
выдает строку, более или менее похожую на код, используемый для определения spec
, в идеале с нормальным отступом на основе длины строки? Что-то вроде:
'list(
description="An mtcards example",
data = list(),
mark = "point",
encoding = list(
x = list(field = "wt", type="quantitative"),
y = list(field="mpg", type="quantitative"),
color = list(field="cyl", type="nominal")))'
Это возможно на других языках, таких как JS, Python и Clojure. Обычно структуры данных выводятся в виде литералов, которые могут быть оценены с помощью используемого языка. Существуют также специальные функции для выполнения этого с отступом (мы обычно называем это «pretty printing»). Но я не помню, чтобы когда-либо сталкивался с чем-то подобным в R (хотя прошло много лет с тех пор, как я его широко использовал), и Google оказался бесполезным в поиске чего-либо.
Для контекста прямо сейчас рассматривается возможность автоматического перевода примеров Vega-Lite / Vega на другие языки (что легко для представления данных Clojure EDN), но неясно, как мы будем это делать для спецификаций R data, используемых vegawidget. У кого-нибудь есть представление о том, как мы могли бы это сделать, или есть вдохновение написать код, чтобы сделать это вручную?
Спасибо!
Обновление: было указано, что deparse
(и dput
) приближают нас к этому, но они по-прежнему не выводят отступы, которые вы ожидаете увидеть в реальном коде. В частности, для этого примера я получаю:
> dput(spec)
list(description = "An mtcards example", data = list(), mark = "point",
encoding = list(x = list(field = "wt", type = "quantitative"),
y = list(field = "mpg", type = "quantitative"), color = list(
field = "cyl", type = "nominal")))
В частности, я бы ожидал, что строки не будут прерываться в середине определения списка, если это не необходимо; color = ...
должно быть в отдельной строке здесь. Я не в восторге от того, что некоторые другие записи на верхнем уровне list(...)
находятся в одной строке, а другие — отдельно, но мы, вероятно, могли бы смириться с этим для примеров. Я бы никогда не ожидал увидеть color = ...
список, разбитый по строкам, подобным этому, хотя в code docs, так что это не полностью решает проблему, если у кого-то нет лучшего решения.
Еще раз спасибо!
Комментарии:
1. Вы ищете
dput(spec)
?2. Это (или
deparse
) может быть допустимым, но не совсем соответствует методам отступов, которые я ожидаю увидеть в реальном коде. Собираюсь проголосовать за повторное открытие, чтобы узнать, есть ли лучшее решение для этого.3. Похоже, вы ищете комбинацию
dput
с code prettifier. В R нет средства улучшения собственного кода, но вы можете проверитьformatR
пакет. Тогда функция, которую вы ищете, будет выглядеть примерно такf <- function(x) formatR::tidy_source(text = capture.output(dput(x)), args.newline = TRUE)
4. Выполнено. Если подумать, я мог бы сам начать использовать эту функцию в Stack Overflow, чтобы сделать вопросы и ответы более разборчивыми, так что спасибо за начало этой темы!
Ответ №1:
Функция dput
— это то, что мы будем использовать в качестве стандартного способа преобразования объекта R в строку текста, которая будет воспроизводить этот объект при запуске в консоли R. На самом деле, это очень часто используется при публикации вопросов и ответов в теге R в Stack Overflow. Например:
x <- list(a = 1, b = "2")
dput(x)
#> list(a = 1, b = "2")
Однако dput
это не всегда дает эстетически приятный результат. Похоже, то, что вы ищете, — это комбинация dput
с code prettifier.
В Base R нет средства улучшения кода. Помимо всего прочего, то, что делает код красивым, довольно субъективно, и, как и в случае с большинством языков программирования, авторы R не предписывают расположение юридического кода.
Однако для R доступны пакеты, которые могут улучшать код, и их можно использовать при выводе dput
. Например, мы могли бы написать такую функцию, как эта:
f <- function(x) {
text_con <- textConnection("output", "w")
dput(x, text_con)
close(text_con)
formatR::tidy_source(text = output, args.newline = TRUE, width = 40)
}
Что является своего рода приукрашенным dput
:
f(spec)
#> list(
#> description = "An mtcards example", data = list(),
#> mark = "point", encoding = list(
#> x = list(field = "wt", type = "quantitative"),
#> y = list(field = "mpg", type = "quantitative"),
#> color = list(field = "cyl", type = "nominal")
#> )
#> )