gsub и pad внутри круглых скобок

У меня есть такой вектор:

x <- c("20(0.23)", "15(0.2)", "16(0.09)")

и я не хочу связываться с числами на внешней стороне круглых скобок, но хочу удалить начальный ноль на числах внутри и сделать так, чтобы все имело 2 цифры. Вывод будет выглядеть так:

"20(.23)", "15(.20)", "16(.09)"

Полезная информация:

Я могу удалить ведущий ноль и сохранить 2 цифры, используя функцию, взятую из:ССЫЛКА

numformat <- function(val) { sub("^(-?)0.", "\\1.", sprintf("%.2f", val)) }

numformat(c(0.2, 0.26))
#[1] ".20" ".26"

я знаюgsub можно использовать, но я не знаю как. Я предоставлюstrsplit ответ, но это в лучшем случае хакерский.

Ответы на вопрос(4)

pad.fix<-function(x){
y<-gsub('\\.(\\d)\\)','\\.\\10\\)',x)
gsub('0\\.','\\.',y)
}

если необходимо, второй gsub удаляет ведущий ноль.

неgsub ответ это в лучшем случае некрасиво.

x <- c("20(0.23)", "15(0.2)", "16(0.09)")

numformat <- function(val) { sub("^(-?)0.", "\\1.", sprintf("%.2f", val)) }
z <- do.call(rbind, strsplit(gsub("\\)", "", x), "\\("))
z[, 2] <- numformat(as.numeric(z[, 2]))
paste0(z[, 1], "(", z[, 2], ")")
Решение Вопроса

жением функцией, примененной к сопоставлению. Таким образом, мы могли бы использовать то, что у вас есть с вашимnumformat функция

library(gsubfn)
# Note that I added as.numeric in because what will be passed in
# is a character string
numformat <- function(val){sub("^(-?)0.", "\\1.", sprintf("%.2f", as.numeric(val)))}
gsubfn("0\\.\\d+", numformat, x)
#[1] "20(.23)" "15(.20)" "16(.09)"
 Dason14 окт. 2012 г., 00:07
Честно говоря, это первый раз, когда я использовалgsubfn так что, вероятно, это можно сделать еще чище, чем это. Но я смутно вспомнил, что gsubfn позволяет вам заменить вещи на функции, действующие на них, так что это казалось идеальной причиной, чтобы попробовать это.
 Tyler Rinker14 окт. 2012 г., 00:06
Вау, это было довольно красиво сделано. Это просто убедило меня изучитьgsubfn пакет.

который кажется сложным только ради осложнений :)

Итак, поехали:

R> x <- c("20(0.23)", "15(0.2)", "16(0.09)")
R> sapply(strsplit(gsub("^(\\d+)\\((.*)\\)$", "\\1 \\2", x), " "), 
+         function(x) sprintf("%2d(.%02d)", 
+                              as.numeric(x[1]), 
+                              as.numeric(x[2])*100))
[1] "20(.23)" "15(.20)" "16(.09)"
R> 

Мы делаем несколько вещей здесь:

gsub() выбирает две цифры: сначала одну перед паренами, затем одну внутри паренов. [Оглядываясь назад, должен был выбрать после десятичной дроби, см. Ниже.]Это распечатывает их только с пробелами, например"20 0.23" для первого.Затем мы используем стандартstrsplit() на этом.Затем мы используемsapply обработать список, который мы получаем отstrsplitМы печатаем первое число в виде двузначного числа int.Второй более хитрый -(s)printf() семьяне можешь подавить ведущий ноль, поэтому мы печатаем десятичную дробь и выводим две цифры целого числа - и соответственно конвертируем второе число.

Это все сжато и в одну строчку, но было бы яснее вычеркнуто.

Редактировать: Я не часто предоставляю быстрые решения, но когда я делаю, по крайней мере, я могу злорадствовать:

R> dason <- function(x) { numformat <- function(val){sub("^(-?)0.", "\\1.", sprintf("%.2f", as.numeric(val)))}; gsubfn("0\\.\\d+", numformat, x) }
R> dirk <- function(x) { sapply(strsplit(gsub("^(\\d+)\\((.*)\\)$", "\\1 \\2", x), " "), function(x) sprintf("%2d(.%02d)", as.numeric(x[1]), as.numeric(x[2])*100)) }
R> 
R> dason(x)
[1] "20(.23)" "15(.20)" "16(.09)"
R> dirk(x)
[1] "20(.23)" "15(.20)" "16(.09)"
R> 
R> res <- benchmark(dason(x), dirk(x), replications=1000, order="relative")
R> res
      test replications elapsed relative user.self sys.self user.child sys.child
2  dirk(x)         1000   0.133    1.000     0.132    0.000          0         0
1 dason(x)         1000   2.026   15.233     1.960    0.064          0         0
R> 

Так что это примерно на 15 раз быстрее. Не то чтобы это имеет значение вэто контекст, но скорость никогда не повредит никому в долгосрочной перспективе.

 Tyler Rinker14 окт. 2012 г., 00:03
О, Дирк, ты любишь усложнение, это делает жизнь веселой :) +1
 Dirk Eddelbuettel14 окт. 2012 г., 00:12
Мое решение вращается вокруг Дейсона. Редактировать приход.
 Dirk Eddelbuettel14 окт. 2012 г., 00:07
Конечно, особенно когда мы можем решить проблемы старой школы только с базой R и без какого-либо из этих новомодных пакетов. :)

Ваш ответ на вопрос