Заменить символы в R объектах класса 'expression' - PullRequest
2 голосов
/ 07 октября 2019

Я пытаюсь заменить символы в выражении R (не в строке), но кажется, что обычные функции для замены символов в этом случае не будут работать. Например, с учетом следующего:

exp <- expression(italic(N[T]))
class(exp) # "expression"

И string::str_replace, и base::gsub не смогут преобразовать символы в этом объекте выражения. Первый возвращает предупреждающее сообщение, а в обоих случаях возвращает объект класса «символ»: объект выражения теряется .

exp %>% stringr::str_replace(pattern = "T", replacement = "i")

[1] "курсив (N [i]) "

Предупреждающее сообщение: в stri_replace_first_regex (строка, шаблон, fix_replacement (замена),: аргумент не является атомным вектором; приведение

exp %>% base::gsub(pattern = "T", replacement = "i")

[1] "курсив (N [i])"

Можно ли преобразовывать символы в выражениях без потери типа класса?

A трюк как следующее не будет работать:

exp %>% base::gsub(pattern = "N", replacement = "i") %>% base::gsub(pattern = "^", replacement ="expression(") %>% base::gsub(pattern = "$", replacement = ")")

Ответы [ 2 ]

3 голосов
/ 07 октября 2019

1) заменить Преобразовать в объект вызова, использовать substitute для этого и затем преобразовать обратно (или, возможно, объекта вызова достаточно для ваших нужд, и вам не нужно преобразовывать обратно в выражение). Это работает полностью на уровне языка R. В отличие от манипуляции со строками.

as.expression(do.call("substitute", list(exp[[1]], list(T = as.name("I")))))
## expression(italic(N[I]))

2) recurse Альтернативой является рекурсивный обход объекта вызова и замена T на I. Обратите внимание, чтоэто вводит и выводит объект вызова, поэтому необходимо преобразовать выражение из объекта вызова и из объекта вызова в выражение, если вам нужно работать с объектами выражения, а не с объектами вызова.

T2I <- function(e) {
  if (identical(e, as.name("T"))) e <- as.name("I")
  else if (length(e) > 1) for(i in 1:length(e)) e[[i]] <- Recall(e[[i]])
  e
}

as.expression(T2I(exp[[1]]))
## expression(italic(N[I]))

3) назначение Если вам известна структура exp, то это назначение будет работать:

exp.orig <- exp # in case you need to save the original

exp[[1]][[2]][[3]] <- as.name("I")
exp
## expression(italic(N[I]))

4) манипулирование строками Это преобразование в строку символов, выполнение замены и обратное преобразование. Это похоже на другой ответ, но не совсем то же самое:

parse(text = gsub("\\bT\\b", "I", format(exp[[1]])))
## expression(italic(N[I]))
2 голосов
/ 07 октября 2019
str2expression(gsub("N[T]", "N[i]", exp, fixed = TRUE))
#OR
parse(text = gsub("N[T]", "N[i]", exp, fixed = TRUE))
#expression(italic(N[i]))
...