Скажем, у меня есть текст:

myF <- "lag.variable.1+1"

Я бы хотел получить для всех подобных выражений следующий результат: lag.variable.2 (то есть замена 1 + 1 на фактическую сумму

Следующее, похоже, не работает, похоже, что обратная ссылка не проходит в eval (бит parse ()):

myF<-gsub("(\\.\\w+)\\.([0-9]+\\+[0-9]+)", 
            paste0( "\\1." ,eval(parse(text ="\\2"))) ,
            myF )

Есть какие-нибудь советы, как добиться желаемого результата? Благодарность!

2
satellite42 5 Дек 2020 в 21:24

2 ответа

Лучший ответ

Вот как вы можете использовать текущий шаблон с gsubfn:

library(gsubfn)
x <- " lag.variable0.3 * lag.variable1.1+1 + 9892"
p <- "(\\.\\w+)\\.([0-9]+\\+[0-9]+)"
gsubfn(p, function(n,m) paste0(n, ".", eval(parse(text = m))), x)
# => [1] " lag.variable0.3 * lag.variable1.2 + 9892"

Обратите внимание, что совпадение передается вызываемому объекту в этом случае, когда Группа 1 назначается переменной n, а Группа 2 назначается m. Результатом является конкатенация содержимого Группы 1, . и eval ed Группы 2.

Обратите внимание, что вы можете упростить вызываемую часть с помощью регулярного выражения PCRE (добавить аргумент perl=TRUE) \K, оператора сброса соответствия, который отбрасывает весь текст, сопоставленный на данный момент:

p <- "\\.\\w+\\.\\K(\\d+\\+\\d+)"
gsubfn(p, ~ eval(parse(text = z)), x, perl=TRUE)
[1] " lag.variable0.3 * lag.variable1.2 + 9892"

Вы можете дополнительно улучшить шаблон для поддержки других операндов, заменив \\+ на [-+/*], а если вам нужно поддерживать числа с дробными частями, замените [0-9]+ на \\d*\\.?\\d+:

p <- "(\\.\\w+)\\.(\\d*\\.?\\d+[-+/*]\\d*\\.?\\d+)"
## or a PCRE regex:
p <- "\\.\\w+\\.\\K(\\d*\\.?\\d+[-+/*]\\d*\\.?\\d+)"
1
Wiktor Stribiżew 5 Дек 2020 в 19:40

Мы можем использовать gsubfn

library(gsubfn)
gsubfn("(\\d+\\+\\d+)", ~ eval(parse(text = x)), myF)
#[1] "lag.variable.2"

 gsubfn("\\.([0-9]+\\+[0-9]+)", ~ paste0(".", eval(parse(text = x))), myF2)
#[1] "lag.variable0.3 * lag.variable1.2 + 9892"

Или с str_replace

library(stringr)
str_replace(myF, "(\\d+\\+\\d+)", function(x) eval(parse(text = x)))
#[1] "lag.variable.2"

Или вариант с strsplit и paste

v1 <- strsplit(myF, "\\.(?=\\d)", perl = TRUE)[[1]]
paste(v1[1], eval(parse(text = v1[2])), sep=".")
#[1] "lag.variable.2"

Данные

myF <- "lag.variable.1+1"
myF2 <- "lag.variable0.3 * lag.variable1.1+1 + 9892"
1
akrun 5 Дек 2020 в 18:53