ChatGPT解决这个技术问题 Extra ChatGPT

格式化R中的小数位

我有一个数字,例如 1.128347132904321674821,我想在输出到屏幕(或写入文件)时仅显示两位小数。如何做到这一点?

x <- 1.128347132904321674821

编辑:

指某东西的用途:

options(digits=2)

已被建议作为可能的答案。有没有办法在脚本中指定它以供一次性使用?当我将它添加到我的脚本中时,它似乎没有做任何不同的事情,而且我对大量重新输入以格式化每个数字不感兴趣(我正在自动化一个非常大的报告)。

--

答案:round(x, digits=2)

如果使用选项(数字 = 4),那不会将计算限制为 4 位,是吗?在那种情况下,它会使程序的准确性大大降低。它只影响打印时的数字,对吗?
controls the number of digits to print when printing numeric values. It is a suggestion only. Valid values are 1...22 with default 7. See the note in print.default about values greater than 15. 来自 ?options 它只影响输出。
请注意,round(23, digits=2) 将打印 23 而不是 23.00。如果您想要后者,请尝试 stackoverflow.com/a/12135122/180892
@PaulHurleyuk,我认为在编程中尽可能使用最少数量的库是一种很好的做法。为每个琐碎的需求使用不同库的人通常会导致混乱、大文件、可移植性问题等。

J
Jeromy Anglim

背景:此页面上建议的一些答案(例如,signifoptions(digits=...))不保证为任意数字显示一定数量的小数。我认为这是 R 中的一个设计特征,良好的科学实践涉及基于“significant figures”原则显示一定数量的数字。然而,在许多领域(例如,APA style、商业报告)中,格式要求规定要显示一定数量的小数位。这通常是为了一致性和标准化目的,而不是关注重要数字。

解决方案:

下面的代码正好显示了数字 x 的两位小数。

format(round(x, 2), nsmall = 2)

例如:

format(round(1.20, 2), nsmall = 2)
# [1] "1.20"
format(round(1, 2), nsmall = 2)
# [1] "1.00"
format(round(1.1234, 2), nsmall = 2)
# [1] "1.12"

更通用的函数如下,其中 x 是数字,k 是要显示的小数位数。 trimws 删除任何前导空格,如果您有一个数字向量,这可能很有用。

specify_decimal <- function(x, k) trimws(format(round(x, k), nsmall=k))

例如,

specify_decimal(1234, 5)
# [1] "1234.00000"
specify_decimal(0.1234, 5)
# [1] "0.12340"

替代方案的讨论:

formatC answerssprintf answers 运行良好。但在某些情况下,它们会显示负零,这可能是不需要的。 IE,

formatC(c(-0.001), digits = 2, format = "f")
# [1] "-0.00"
sprintf(-0.001, fmt = '%#.2f')
# [1] "-0.00"

一种可能的解决方法如下:

formatC(as.numeric(as.character(round(-.001, 2))), digits = 2, format = "f")
# [1] "0.00" 

+1 唯一对我有用的答案,正确地将 0.0001 打印为 0.00
format()prettyNum() 之类的函数如何将数字转换为字符,这一直困扰着我。你会如何解决这个问题?
@JeromyAnglim我注意到上面的解决方案有一个可能的边缘情况缺点,即固定小数点前的字符数,例如format(c(10, 1), nsmall=1)产生"10.0" " 1.0"(注意1.0前面的前导空格。而{ 3} 函数似乎保证了小数点两边更好的格式,例如 sprintf(c(10,1), fmt = '%#.1f') 摆脱了那个讨厌的前导空格并返回 "10.0" "1.0"
前导空格是用于在列中使用 format 的结果时对齐小数点的功能。
@FengJian 这不是函数的问题。相反,您或许应该避免将数字选项设置得太高。请参阅 print.default help 中的警告。它警告说设置数字 >=16 可能会导致打印问题。
M
MichaelChirico

您可以根据需要格式化一个数字,例如 x,精确到小数位。这里 x 是一个有很多小数位的数字。假设我们希望显示此数字的小数点后 8 位:

x = 1111111234.6547389758965789345
y = formatC(x, digits = 8, format = "f")
# [1] "1111111234.65473890"

这里 format="f" 给出通常小数位的浮点数,例如 xxx.xxx,而 digits 指定位数。相比之下,如果您想获得一个整数来显示,您将使用 format="d"(很像 sprintf)。


虽然我不清楚 OP 到底在问什么,但从评分最高的答案来看,我不禁注意到 formatC 几乎完全是我用于此目的的。我认为这个答案很好,并且根据 OP 的要求以 R 为基础。
你们中的任何人都可以帮助解决这个问题吗? stackoverflow.com/q/53279593/5224236
此答案比所选答案效果更好。 formatC 不受选项(数字)的影响
K
Kun Ren

你可以试试我的包formattable

> # devtools::install_github("renkun-ken/formattable")
> library(formattable)
> x <- formattable(1.128347132904321674821, digits = 2, format = "f")
> x
[1] 1.13

好消息是,x 仍然是一个数字向量,您可以使用相同的格式进行更多计算。

> x + 1
[1] 2.13

更好的是,数字不会丢失,您可以随时重新格式化更多数字:)

> formattable(x, digits = 6, format = "f")
[1] 1.128347

这么小的刺痛了我一上午。出于某种原因,R 只会对某些列的显示进行四舍五入。我需要这个修复,因为我还必须对这些列执行计算。这行得通。谢谢 !
我喜欢 formattable 比任何 baseR 函数。最大的优点是将变量保留为数字。
M
Mark Adamson

假设您要保留尾随零,则保留 2 个小数位

sprintf(5.5, fmt = '%#.2f')

这使

[1] "5.50"

正如@mpag 下面提到的那样,R 似乎有时可以通过 this 和 round 方法给出意想不到的值,例如 sprintf(5.5550, fmt='%#.2f') 给出 5.55,而不是 5.56


然而,尽管 sprintf 轮回, sprintf(5.5550, fmt='%#.2f') 给出了一个稍微出乎意料的结果:5.55。 sprintf(5.555000000001, fmt='%#.2f') 给出 5.56。这似乎是 R 中舍入的一般“问题”,因为 round, nsmall 方法给出了相同的结果。
谢谢@mpag,我不知道 R 在边界四舍五入方面遇到了困难,我刚刚用 5.565 进行了四舍五入,而 5.545 向下舍入。我想这是他们处理浮点不精确的方式。我认为我没有在其他语言中看到过这种行为,我猜这意味着它们有内置的解决方法
我认为他们故意将这些值视为精确程度的限制。他们认为 5.555 的值实际上与 5.5554 的“真实”值 5.5546 产生的可能性一样。但是,如果您继续这种舍入游戏,如果您一次执行一位数字,5.444445 可能(未经测试)最终为“6”。但是您可能是对的,这可能是二进制表示略低于或高于 5.55 的问题。
是的,我认为如果这是故意的,它也会在 5.565 和 5.545 之间保持一致。 '随机性'向我表明这是一个浮点表示的东西。
你们中的任何人都可以帮助解决这个问题吗? stackoverflow.com/q/53279593/5224236
A
Andreas

如果您更喜欢有效数字而不是固定数字,那么 signif 命令可能很有用:

> signif(1.12345, digits = 3)
[1] 1.12
> signif(12.12345, digits = 3)
[1] 12.1
> signif(12345.12345, digits = 3)
[1] 12300

谢谢保罗。这两个并不是我想要的,但 signif 让我找到了 round() ,这正是我所需要的。干杯,
Error: could not find function "fixed"
signif 适用于提供的特定数字,但我认为常见的应用问题是当您需要精确显示两位小数但您提前不知道数字是多少时。在这种情况下,signif 将根据实际数字给出不同的小数位数。
固定在任何地方都找不到。请修复它,否则应删除此误导性答案。
@JeromyAnglim 当我们想要 3sf 时我们如何解决这个问题?有时它给我 3sf,有时是 4sf,等等。我们如何解决这个问题?
X
Xavier V.

类似的东西:

options(digits=2)

数字选项的定义:

digits: controls the number of digits to print when printing numeric values.

有没有办法在运行脚本时动态设置它?
这适用于在 R 控制台中输出,但在我的脚本中不起作用(它们仍然带有 .1289273982)
我有一个奇怪的行为,digits 选项似乎没有设置小数点后的位数。例如,当我设置选项(数字 = 2)时,打印 7.25 会导致输出 7.2,1234.25 变为 1234,而 0.25 仍为 0.25。是否有另一种选择与此交互?
如果您只需要一次使用,这是您绝对不应该做的事情。更改选项将影响一切。
i
ilya

检查函数 prettyNum、格式

要试用零(例如 123.1240),请使用 sprintf(x, fmt='%#.4g')


@42 我提倡学习sprintf,它基本上是一个格式化框架
@jangorecki 我不确定你的观点。我所做的(5 年多前)只是建议进行拼写更正。
@42 我很难对 fmt arg 进行投诉,抱歉!
我认为 OP 在固定小数位之后而不是固定数字之后。您的答案中的 g 似乎是固定数字,使用 f 效果更好。
C
Chernoff

函数 formatC() 可用于将数字格式化为两位小数。即使结果值包括尾随零,此函数也会给出两位小数。


E
Eldar Agalarov

我正在使用这个变体来强制打印 K 个小数位:

# format numeric value to K decimal places
formatDecimal <- function(x, k) format(round(x, k), trim=T, nsmall=k)

n
nullglob

请注意,R 中的数字对象与 double precision 一起存储,这为您提供(大约)16 位十进制数字的精度 - 其余的将是噪音。我承认上面显示的数字可能只是一个示例,但它是 22 位长。


已确认,仅作为示例。我把键盘捣碎了。
J
Jeromy Anglim

在我看来,会是这样的

library(tutoR)
format(1.128347132904321674821, 2)

每一点online help


我找到了这个,但它需要一个包,我正在基础包中寻找一些东西。
@brandon, format() 是基础的一部分。打开 R 并输入 ?format ... 不需要任何包。
嗯,你看看这个输出什么? [1] "1.128347" 否则,你对它在基本包中是完全正确的,我的错。
根据提供的链接,也许尝试 format.default(x, digits = 2) 只是在黑暗中拍摄。该信息是我通常阅读的文档中缺少的一些信息,我希望也能看到打印输出。
刚刚注意到您的链接指向 tutoR 文档,这不是基础的一部分。
j
jared

如果您只想对数字或列表进行四舍五入,只需使用

round(data, 2)

然后,数据将四舍五入到小数点后 2 位。


C
Captain Tyler

这是我从单位到数百万的方法。数字参数让我调整有效值的最小数量(整数+小数)。您可以先在内部调整小数舍入。

number <-function(number){
  result <- if_else(
    abs(number) < 1000000,
    format(
      number, digits = 3,
      big.mark = ".",
      decimal.mark = ","
    ),
    paste0(
      format(
        number/1000000,
        digits = 3,
        drop0trailing = TRUE,
        big.mark = ".",
        decimal.mark = ","
      ),
      "MM"
    )
  )
  # result <- paste0("$", result)
  return(result)
}

F
Frederich

我编写了这个可以改进的函数,但看起来在极端情况下效果很好。例如,在 0.9995 的情况下,投票正确答案给我们 1.00,这是不正确的。在数字没有小数的情况下,我使用该解决方案。

round_correct <- function(x, digits, chars = TRUE) {
  if(grepl(x = x, pattern = "\\.")) {
    y <- as.character(x)
    pos <- grep(unlist(strsplit(x = y, split = "")), pattern = "\\.", value = FALSE)
    if(chars) {
      return(substr(x = x, start = 1, stop = pos + digits))
    }
    return(
      as.numeric(substr(x = x, start = 1, stop = pos + digits))
    )
  } else {
    return(
      format(round(x, 2), nsmall = 2)
    )
  }
}

例子:

round_correct(10.59648, digits = 2)
[1] "10.59"
round_correct(0.9995, digits = 2)
[1] "0.99"
round_correct(10, digits = 2)
[1] "10.00"

r
rodrigo franco
library(dplyr)
# round the numbers
df <- df %>%
  mutate(across(where(is.numeric), .fns = function(x) {format(round(x, 2), nsmall = 2)}))

在这里,我将所有数值更改为只有 2 位小数。如果您需要将其更改为更多小数位

# round the numbers for k decimal places
df <- df %>%
  mutate(across(where(is.numeric), .fns = function(x) {format(round(x, k), nsmall = k)}))

将 k 替换为所需的小数位数