对齐小数位的简单方法

时间:2018-07-02 19:21:23

标签: r

标题是很不言自明的,您知道在报告阶段将小数点与R对齐的简单方法吗?

例如,如果我有一个数值向量:

c(2,120,12.5,100.25,0.1)

我希望显示器看起来像这样:

  2
120
 12.5
100.25
  0.1

第一个人感到惊讶,R中没有用于此的软件包,因为我同意这是一个非常普遍的问题。也许人们能够使用Markdown或其他报告技巧解决此问题?

谢谢

2 个答案:

答案 0 :(得分:0)

好吧,我最终决定为此目的编写一个函数。除示例向量外,它运行得很好,但是我不知道为什么,如果有人可以帮助的话,那会很棒。

AlignDec <- function(df, originalvar, newvar) {

  require(dplyr)

  originalvar <- enquo(originalvar) %>% quo_name()
  newvar <- enquo(newvar) %>% quo_name()

  decimalnumcount <- function(x) {

    out <- ifelse((x %% 1 != 0), nchar(strsplit(sub('.0+$', '', as.character(x)), ".", fixed = TRUE)[[1]][[2]]), 0)
    return(out)
  }

  IntNumCount <- function(x) {
    out <- nchar(as.character(trunc(x)))
    return(out)
  }

  df <- df %>% mutate(n_int = IntNumCount(.data[[originalvar]]), n_dec = decimalnumcount(.data[[originalvar]]), maxnint = max(n_int), maxndec = max(n_dec),
                      intpos = (maxnint - n_int), !!newvar := paste0(strrep(" ",intpos), prettyNum(.data[[originalvar]]))) %>% 
    select(-one_of(c("n_int", "n_dec", "maxnint", "maxndec", "intpos")))

  return(df)

}

如果我在这两个数据帧上进行测试,则它在第一种情况下有效,但在第二种情况下无效,我也不知道为什么!

testok <- data.frame(y = c(12.1, 2, 0, 17, 1000.1, 57))
testnotok <- data.frame(y = c(2,120, 12.5, 100.25, 0.1))

test1 <- AlignDec(testok, y, z)
test2 <- AlignDec(testnotok, y, z)

test2向我返回此错误消息:

Error in mutate_impl(.data, dots) : 
  Evaluation error: subscript out of bounds. 

有什么想法吗?

答案 1 :(得分:0)

这是一种特殊情况,但是下面的函数应该可以执行您想要的操作。我还包括一个“精确”参数,用于指定最大小数位数(必须大于0)。

alignedDigits <- function(df, originalvar, newvar, precision = 2) {
  originalvar <- enquo(originalvar) %>% quo_name()
  newvar <- enquo(newvar) %>% quo_name()

  df[[newvar]] <- round(df[[originalvar]], digits = precision)
  split.digits <- sprintf(paste0('%0.', as.character(precision), 'f'), df[[newvar]])

  split.digits <- strsplit(split.digits, '\\.') %>% 
    as.data.frame() %>% 
    as.matrix %>% 
    t

  split.digits[,2] <- sub('0+$', '', split.digits[,2])
  split.digits[,2] <- ifelse(split.digits[,2] == '', 0, split.digits[,2])

  maxima <- apply(split.digits, 2, function(x) max(nchar(x)))
  split.digits[,1] <- sapply(split.digits[,1], function(x) paste0(paste0(rep(' ', maxima[1] - nchar(x)), collapse = ''), x))
  split.digits[,2] <- sapply(split.digits[,2], function(x) paste0(x, paste0(rep(' ', maxima[2] - nchar(x)), collapse = '')))
  final.digits <- apply(split.digits, 1, function(x) paste(x[1], x[2], sep = '.'))
  df[[newvar]] <- final.digits
  return(df)
}

testok <- data.frame(y = c(12.1, 2, 0, 17, 1000.1, 57))
testnotok <- data.frame(y = c(2,120, 12.5, 100.25, .1))

alignedDigits(testok, y, m)

       y      m
1   12.1   12.1
2    2.0    2.0
3    0.0    0.0
4   17.0   17.0
5 1000.1 1000.1
6   57.0   57.0

alignedDigits(testnotok, y, z)

       y      z
1   2.00   2.0 
2 120.00 120.0 
3  12.50  12.5 
4 100.25 100.25
5   0.10   0.1