我想将格式化数字字符串中的前导空格替换为 \phantom{...}
命令,其中 ...
与前导空格的长度相同。我能做的是:
x <- c(1, 1., 0.230, 10.1, 1000, 10000.12)
y <- format(round(x, 2), nsmall=2, big.mark="\\\\,", big.interval=3L)
gsub(" ", "\\\\phantom{ }", y)
但是,我更想要一个 \phantom{}
适当长度的(例如 \phantom{ }
然后几个 \phantom{ }
。
更新
基于Arun的解决方案,我构建了这个函数来格式化R
中的数字在 LaTeX 表格中对齐:
tabAlign <- function(x, nsmall=0L, digits=NULL,
flag.before="\\\\phantom{", flag.after="}", embrace="$",
big.mark="\\\\,", big.interval=3L, ...)
{
x <- if(!is.null(digits)) round(x, digits=digits) else x
x <- format(x, nsmall=nsmall, big.mark=big.mark, big.interval=big.interval, ...)
x <- sub("^([ ]+)", paste0(flag.before, "\\1", flag.after), x)
paste0(embrace, x, embrace)
}
现在,让我们用它做一些有用的事情。 tabAlign(x)
给出:
[1] "$\\phantom{ }1.00$" "$\\phantom{ }1.00$"
[3] "$\\phantom{ }0.23$" "$\\phantom{ }10.10$"
[5] "$\\phantom{ }1\\,000.00$" "$10\\,000.12$"
将其复制并粘贴到 LaTeX 文件中会发现对齐不正确。原因是big.mark
。本预留nchar(big.mark)=3
空格(在 R
字符串中)。然而,在 LaTeX 中,这占用的空间要少得多,因此数字不再完美对齐。理想情况下,sub()
因此命令必须采用 nchar(big.mark)
考虑在内(对于任何给定的 big.mark
)。
更新2
这是另一个更新,现在考虑了 DWin 的提示。
tabAlign <- function(x, nsmall=0L, digits=NULL,
flag="\\\\phantom{\\1}", embrace="$",
big.mark="\\\\,", big.interval=3L, ...)
{
## round (if digits is not NULL)
x <- if(!is.null(digits)) round(x, digits=digits) else x
## determine those with/without big.mark (idea from prettyNum())
y <- format(x, nsmall=nsmall, trim=TRUE)
y.sp <- strsplit(y, ".", fixed=TRUE)
B <- sapply(y.sp, `[`, 1L)
ind.w.big.mark <- grep(paste0("[0-9]{", big.interval+1L, ",}"), B)
ind.wo.big.mark <- setdiff(1:length(y), ind.w.big.mark)
## format the numbers
x <- format(x, nsmall=nsmall, big.mark=big.mark, big.interval=big.interval, ...)
## substitute spaces
z <- character(l <- length(x))
n <- nchar(big.mark)
for(i in seq_len(l)){
z[i] <- if(i %in% ind.wo.big.mark) sub("^([ ]+)", paste0(flag, big.mark), x[i])
else sub("^([ ]+)", flag, x[i])
}
## embrace
paste0(embrace, z, embrace)
}
唯一缺少的部分是替换 \phantom
中的所有空格。在 if()
部分,但只有空格数 - n
,其中n <- nchar(big.mark)
。这如何在 sub()
中指定?
更新3
这是一个解决方案(但不太优雅......见下文):
tabAlign <- function(x, nsmall=0L, digits=NULL,
flag="\\\\phantom{\\1}", embrace="$",
big.mark="\\\\,", big.mark2="\\,", big.interval=3L, ...)
{
## round (if digits is not NULL)
x <- if(!is.null(digits)) round(x, digits=digits) else x
## determine those with/without big.mark (idea from prettyNum())
y <- format(x, trim=TRUE)
y.sp <- strsplit(y, ".", fixed=TRUE)
B <- sapply(y.sp, `[`, 1L)
w.big.mark <- grep(paste0("[0-9]{", big.interval+1L, ",}"), B)
wo.big.mark <- setdiff(1:length(y), w.big.mark)
## format the numbers
x. <- if(length(wo.big.mark) > 0 && length(w.big.mark) > 0) {
## format but trim
y <- format(x, trim=TRUE, nsmall=nsmall, big.mark=big.mark, big.interval=big.interval, ...)
## paste big.mark to all numbers without big.mark
y[wo.big.mark] <- paste0(big.mark2, y[wo.big.mark])
format(y, justify="right")
} else { # either all numbers have big.mark or not
format(x, nsmall=nsmall, big.mark=big.mark, big.interval=big.interval, ...)
}
z <- sub("^([ ]+)", flag, x.)
## embrace
paste0(embrace, z, embrace)
}
x <- c(1, 1., 0.230, 10.1, 1000, 10000.12)
tabAlign(x)
tabAlign(x[1:4])
tabAlign(x[5:6])
如果我们只能指定 big.mark
那就更好了(也不是big.mark2
)。
最佳答案
这能解决问题吗?最好显示所需的输出(以在测试表达式时确定输出)。感谢 DWin 的建议(见评论)。
sub("^([ ]+)", "\\\\phantom{\\1}", y)
(
和)
捕获匹配模式(这是从字符串开头开始的一堆连续空格),并且可以使用 \\1
插入此捕获的组。如果您有多个括号,则可以使用从\1 到\9 的反向引用插入每个捕获的组。
关于regex - 替换格式化数字中的前导空格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14077014/