我想用\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
)会更好。
答案 0 :(得分:3)
这可以解决问题吗?显示所需的输出(在测试表达式时确保输出)会很好。感谢DWin的建议(见评论)。
sub("^([ ]+)", "\\\\phantom{\\1}", y)
(
和)
捕获匹配模式(从字符串的开头开始是一串连续的空格),并且可以使用\\1
插入此捕获的组。如果您有多个括号,则可以插入每个捕获的组,并从\ 1到\ 9进行反向引用。