Извлечение информации в скобках формулы - PullRequest
2 голосов
/ 25 сентября 2019

Я пишу пакет R, в котором пользователи пишут формулы, которые выглядят следующим образом:

outcome ~ var1 + var2 + mm(id, mmc(var3, var4), mmw(pupils^exp(teacher*b)))

Правая часть содержит имена переменных и элемент mm (), который сам содержит имя переменной(id) и элементы mmc () и mmw ().

Я хотел бы разделить mm (), mmc (), mmw (), то есть получить переменные

mm  = id, mmc(var3, var4), mmw(pupils^exp(teacher*b))
mmc = var3, var4
mmw = pupils^exp(teacher*b)

Является ли моя единственная возможность анализировать формулу как символы и затем использовать регулярные выражения для разделения элементов, или есть способы обработать это более элегантно, поскольку это формула?

Я пробовал

all.vars
all.names

, но они слишком сильно разбивают mmw (), поскольку mmw () обычно содержит нелинейные функциональные отношения

1 Ответ

3 голосов
/ 26 сентября 2019

1) Используя getTerms из Слагаемые суммы в выражении R мы можем напрямую анализировать формулу без использования регулярных выражений.Сначала мы получаем термины tt, а затем формируем mm, то есть термин, имеющий более одного элемента.Из этого извлекают остальные.Пакеты не используются.

fo <- outcome ~ var1 + var2 + mm(id, mmc(var3, var4), mmw(pupils^exp(teacher * b)))

tt <- getTerms(fo[[3]])
mm <- as.list(tt[lengths(tt) > 1][[1]])[-1]
mmc <- as.list(mm[[2]][-1])
mmw <- as.list(mm[[3]][-1])

, что дает:

> mm
[[1]]
id

[[2]]
mmc(var3, var4)

[[3]]
mmw(pupils^exp(teacher * b))

> mmc
[[1]]
var3

[[2]]
var4

> mmw
[[1]]
pupils^exp(teacher * b)

2) В качестве альтернативы мы можем включить обработку прямо в getTerms, давая getMs следующим образом:

getMs <- function(e, x = list()) {
  if (length(e) == 1) x
  else if (identical(e[[1]], as.name("+")))
    c( Recall(e[[2]], x), Recall(e[[3]], x) )
  else if (as.character(e[[1]]) %in% c("mm", "mmw", "mmc")) {
      for(i in 2:length(e)) x <- Recall(e[[i]], x)
      c(setNames(list(as.list(e[-1])), as.character(e[[1]])), x)
  } else x
}
res <- getMs(fo[[3]])
str(res)

дача:

List of 3
 $ mm :List of 3
  ..$ : symbol id
  ..$ : language mmc(var3, var4)
  ..$ : language mmw(pupils^exp(teacher * b))
 $ mmw:List of 1
  ..$ : language pupils^exp(teacher * b)
 $ mmc:List of 2
  ..$ : symbol var3
  ..$ : symbol var4
...