Rmarkdown: написание встроенного кода dplyr, если в именах столбцов заданы пробелы
проблема
Мой встроенный код ломается, когда я filter()
или же select()
имя столбца с пробелом, который я обычно определяю с помощью обратных галочек в dplyr.
Пример данных
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(dplyr)
library(knitr)
library(lazyeval)
df <- structure(list(1:3, 2:4), .Names = c("a", "b"), row.names = c(NA, -3L), class = "data.frame")
df <- df %>% select(`a a`=a, `b b`=b)
```
Встроенный блок кода
Я пытаюсь что-то вроде `r df %>% filter(`a a` == 1) %>% select(`a a`) %>% as.numeric()`
, но я получаю следующую ошибку:
Error in base::parse(text = code, keep.source = FALSE) : <text>:2.0: unexpected end of input 1: df %>% filter( ^ Calls: <Anonymous> ... inline_exec -> withVisible -> eval -> parse_only -> <Anonymous>
... по довольно очевидным причинам (обратные черты заканчивают фрагмент кода). Я мог бы переименовать столбцы в фрагменте кода после вычисления intext (я форматирую их для таблицы), но было бы неприятно разбивать их.
дорогой lazyeval
решение
Это решает проблему r df %>% filter_(interp(~ which_column == 1, which_column = as.name("a a"))) %>% select_(as.name("a a")) %>% as.numeric()
, но должен быть лучший способ.
1 ответ
Я не уверен, как вы работаете вещи - здесь я даю ответ относительно knitr
,
Для этого случая не существует простого решения, и обходной путь перемещения некоторого кода внутри чанков (как предлагается в одном из комментариев), вероятно, является подходящим способом.
Для дальнейшего использования и дальнейшего понимания я все же поделюсь основной проблемой и альтернативным решением.
Обратите внимание, что knitr
использует следующий шаблон для inline.code
(если вы используете формат Rmarkdown):
knitr::all_patterns$md$inline.code
[1] "`r[ #]([^`]+)\\s*`"
Теперь функция knitr:::parse_inline
соответствует этому через вызов stringr::str_match_all
, который будет обнаруживать паттерны одного или нескольких не-backticks ([^`]+
), за которым следует ноль или несколько элементов класса пространства (\\s*
), после чего следует галочка.
Так что это закончится на первом бэккеке `r
более или менее несмотря ни на что. Это имеет некоторый смысл, так как строки ввода свернуты в parse_inline
и на самом деле может быть несколько операторов встроенного кода и простой текст, содержащий обратные галочки в результирующей строке.
Однако если вы ограничиваете себя некоторыми соглашениями, вы можете изменить шаблон, чтобы по-разному определять конец фрагментов встроенного кода. Ниже я предполагаю, что я всегда разбиваюсь на новую строку после фрагмента встроенного кода, например, следуя вашему setup
у меня есть только следующее:
Hello there.
`r DF %>% filter(`a a` == 1) %>% select(`a a`) %>% as.numeric()`
This should read 1 above here.
Затем я могу вязать следующим образом, модифицируя шаблон так, чтобы он брал все до обратного удара, за которым следовал разрыв новой строки:
library(knitr)
opts_knit$set('verbose' = TRUE)
knit_patterns$set(all_patterns$md)
inline.code.2 <- "`r[ #](.+)\\s*`\n"
knitr::knit_patterns$set(inline.code = inline.code.2)
knit2html("MyRmarkdownFile.rmd")
browseURL("MyRmarkdownFile.html")
Найти общее правило для этого шаблона, которое работает для всех, кажется невозможным.