从源码角度看R语言的format函数

2023-10-31

先提一个问题,请问下面最后的两个逻辑语句的判断,结果是什么?


x <- c(1234567.8, 12.12345)
x11 <- format(x, scientific = FALSE)
x12 <- format(x, scientific = TRUE)
x21 <- as.numeric(x11)
x22 <- as.numeric(x12)

x21 == x
x22 == x

大家可以稍作思考。

之所以给出开头的问题,还是因为之前讨论的apply函数。当apply应用到data.frame上时,中间会调用泛型函数as.matrix将数据进行转换,如果发现数据中存在非数值型,会调用format对数值型数据进行格式化。

....
  else if (non.numeric) {
    for (j in pseq) {
      # 如果是字符串,不转换
      if (is.character(X[[j]])) 
        next
      # 如果是逻辑值,调用as.character
      else if (is.logical(xj <- X[[j]])) 
        xj <- as.character(xj)
      else {
        # 如果有NA,先确定位置
        miss <- is.na(xj)
        # 如果是因子,调用as.vector,否则调用format
        xj <- if (length(levels(xj))) 
          as.vector(xj)
        else format(xj)
        # 最后把NA放回
        is.na(xj) <- miss
      }
      X[[j]] <- xj
    }
  }
....

这个format的描述只有一句,‘Format an R object for pretty printing.’即,格式化一个 R 对象用于漂亮的打印,

问题出在这个“漂亮”上,R语言有自己的理解。

比如说同样的 1234567.8在不同的环境下,会出现了不同的情况,

format(c(1234567.8, 12.12345))
# "1.234568e+06" "1.212345e+01"
format(c(1234567.8, 123.12345))
# "1234567.8000" "    123.1235"

一个采取了科学计数法,并保留了7位有效数字,显示为1.234568e+06,一个则保持原状1234567.8000。

为什么会出现这个情况呢?这和scientific参数有关,接受一个逻辑值或者一个整数。如果提供的逻辑值,行为非常简单,就是要么用科学计数法,要么不用科学计数法。

而问题出在它默认值不是逻辑值,而是NA,此时他使用 getOption("scipen") 的结果作为输入,用于决定是以固定,还是以指数符号(科学计数法)打印数字。正值偏向于固定符号,负值则偏向于科学计数法。

具体这个参数会触发R哪一行底代码呢?通过我刨根问底,最终确定源代码中src/mian/format.c 的formatReal函数,一个用于对double类型数据进行格式化的函数。

代码有一段注释,含义是,在满足有效位数的前提下,固定表示使用的空间不超过指数表示时,优先使用固定显示。

    /* F Format: use "F" format WHENEVER we use not more space than 'E'
     *    and still satisfy 'R_print.digits' {but as if nsmall==0 !}
     *
     * E Format has the form   [S]X[.XXX]E+XX[X]
     *
     * This is indicated by setting *e to non-zero (usually 1)
     * If the additional exponent digit is required *e is set to 2
     */
     ...
  *d = mxns - 1;
  *w = neg + (*d > 0) + *d + 4 + *e; /* width for E format */
  if (wF <= *w + R_print.scipen) { /* Fixpoint if it needs less space */
      *e = 0;
      if (nsmall > rgt) {
    rgt = nsmall;
    wF = mxsl + rgt + (rgt != 0);
      }
      *d = rgt;
      *w = wF;
  } /* else : "E" Exponential format -- all done above */
...       

代码中w是指数表示法的宽度, wF是固定表示的宽度,最后w会加上 scipen 得到最终的长度,默认是0,也就是公平决斗。

回到数据c(1234567.8, 12.12345)中,我们来看它在固定表示和指数表示的结果。

> format(c(1234567.8, 12.12345), scientific = TRUE)
[1] "1.234568e+06"
[2] "1.212345e+01"
> format(c(1234567.8, 12.12345), scientific = FALSE)
[1] "1234567.80000"
[2] "     12.12345"

在保证最小数字有7位有效数字的前提下(由digits参数控制),采用指数显示法时结果是12个字符,采取固定显示结果是13个字符。当scipen=0时,指数显示比较窄,因此选择指数显示。

而数据c(1234567.8, 123.12345),在保证最小数字有7位有效数字时,结果都是12个字符,势均力敌的情况下,采取固定显示。

> format(c(1234567.8, 123.12345), scientific = TRUE)
[1] "1.234568e+06"
[2] "1.231235e+02"
> format(c(1234567.8, 123.12345),scientific = FALSE)
[1] "1234567.8000"
[2] "    123.1235"

有效数字的定义是,从第一位非0数字开始到最后一位,一共有多少位数字。例如100是3为有效数字,0.001是1位有效数字,0.00100是3位有效数字。

最后帮助大家梳理下整体逻辑

  1. format函数作用是让打印结果更加美观
  2. 在打印数字时,在保证最小数以一定有效数值展示的前提下,对比固定表示和指数表示两者的字符数目,选择占用字符最少的方法
  3. 最终数值的展示效果会受到digits和scientific的影响
  4. digits和scientific默认值来自于getOption(“digits”)和getOption(“scipen”)
  5. 如果想让结果都以固定显示,可以设置scipen为一个非常大的数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从源码角度看R语言的format函数 的相关文章

  • R data.table fwrite 到 fread 空间分隔符并清空

    我在使用 fread 以 作为分隔符和散布的空白值时遇到问题 例如 这个 dt lt data table 1 5 1 5 1 5 make a simple table dt 3 V2 NA add a blank in the midd
  • 汇总表中各列的字符值比例

    在这种数据框中 df lt data frame w1 c A A B C A w2 c C A A C C w3 c C A B C B 我需要计算所有列中字符值的列内比例 有趣的是 以下代码适用于大型实际数据集 但对上述玩具数据会引发错
  • 如何在 R 中绘制一列与其余列的关系图

    我有一个数据集 其中 1 是时间 接下来的 14 个是幅度 我想在一张图表上散布所有大小与时间的关系 其中每个不同的列都是网格化的 分层在另一个之上 我想使用原始数据来制作这些图表 并单独制作它们 但只想执行此过程一次 数据集A 唯一的自变
  • 如何定义“f_n-chi-square”函数并使用“uniroot”求置信区间?

    I want to get a 95 confidence interval for the following question 我已经写了函数f n在我的 R 代码中 我首先使用 Normal 随机采样 100 个样本 然后定义函数h
  • 如何绘制堆积比例图?

    我有一个数据框 x lt data frame id letters 1 3 val0 1 3 val1 4 6 val2 7 9 id val0 val1 val2 1 a 1 4 7 2 b 2 5 8 3 c 3 6 9 我想绘制一个
  • 计算互相关函数?

    In R 我在用ccf or acf计算成对互相关函数 以便我可以找出哪个移位给我带来最大值 从它的外观来看 R给我一个标准化的值序列 Python 的 scipy 中是否有类似的东西 或者我应该使用fft模块 目前 我正在这样做 xcor
  • 从 R 中的方差分析 (glm) 中提取残余偏差

    我在 R 中安装了一个 glm 模型并采用了方差分析表 我需要提取 残余偏差 列 但它会产生错误 以下是代码 创建数据 counts lt c 18 17 15 20 10 20 25 13 12 outcome lt gl 3 1 9 t
  • 无法部署 ShinyApp:readTableHeader 在“raw”上发现不完整的最后一行(使用默认值:en_US)

    我已经拼命尝试部署我的闪亮应用程序大约一周了 但不幸的是我无法停止收到以下消息 Warning message Error detecting locale Error in read table file file header head
  • 融化R中的下半矩阵

    如何融化下半三角形加对角矩阵 11 NA NA NA NA 12 22 NA NA NA 13 23 33 NA NA 14 24 34 44 NA 15 25 35 45 55 A lt t matrix c 11 NA NA NA NA
  • R 中按时间划分的平均值

    我每秒测量一次化合物浓度 我想求 30 秒和 60 秒的平均值 我一直在阅读这里的帖子 我尝试过lubridate and dplyr 但没有运气 我正在努力完成这项工作 但我一直没能做到 我正在从 SAS 过渡到 R 所以请耐心等待 这是
  • 将第 N 行上的 NA 行插入 data.frames 列表,其中 N 来自列表

    经过几个小时后 我发现自己无法解决以下问题 我有一个数据框列表 我想分别向每个 DF 插入 而不是替换 一行或多行 NA 始终至少一行 要插入的 NA 数量存储在单独的列表中 为了说明这一点 我有以下两个列表 list of datafra
  • 如何在knitr和RStudio中为word和html设置不同的全局选项?

    我正在使用 RStudio 0 98 932 和 knitr 1 6 想要为word和html设置不同的全局knitr选项 例如 想要将word的fig width和fig height设置为6 html的fig width和fig hei
  • 获取函数的命名空间

    我正在开发一个包 我希望在其中向对象添加编辑历史记录 该包允许其他包注册用于编辑对象的函数 我正在寻找一种方法来记录注册用于编辑的函数的包的版本 问题是 给定一个函数 如何从导出的位置获取包 我的想法是调查它的搜索路径 但是search 仅
  • randomForest 包在删除一个预测类时的奇怪行为

    我正在运行一个随机森林模型 它产生的结果从统计角度来看对我来说完全没有意义 因此我确信有些东西mustrandomForest 包的代码出现错误 至少在模型的本次迭代中 预测 左侧变量是具有 3 种可能结果的政党 ID 民主党 独立党 共和
  • 如何对数字进行四舍五入并使其显示零?

    R 中将数字四舍五入到小数点后 2 位的常用代码是 gt a 14 1234 gt round a digits 2 gt a gt 14 12 但是 如果该数字的前两位小数位为零 则 R 会在显示中抑制零 gt a 14 0034 gt
  • R中的字典数据结构

    在 R 中 我有 例如 gt foo lt list a 1 b 2 c 3 如果我输入foo I get a 1 1 b 1 2 c 1 3 我怎样才能看透foo仅获取 键 列表 在这种情况下 a b c R 列表可以具有命名元素 因此可
  • R中的重叠矩阵

    我有以下数据框 id channel 1 a 1 b 1 c 2 a 2 c 3 a 我想创建并重叠矩阵 它基本上是一个方阵 行和列标签为 a b c 表中的每个条目显示每个通道共有多少个 id 例如 在上面的例子中 矩阵看起来像 a b
  • 列出 R 数据文件的内容而不加载

    我有时用print load myDataFile RData 当我加载数据文件时列出它的内容 有没有办法列出内容而不加载数据文件中包含的对象 我认为如果不加载对象就无法做到这一点 解决方案可能是使用包装器将 R 对象保存到save 该函数
  • 在R中循环子文件夹

    我正在 R 环境中包含多个子文件夹的文件夹中工作 我想要循环遍历多个子文件夹 然后在每个子文件夹中调用 R 脚本来执行 我想出了下面的代码 但我的代码似乎添加了 到子文件夹列表 我收到错误 文件中的错误 文件名 r 编码 编码 无效的 描述
  • 如何按时间间隔匹配数据帧?

    这是我从数据记录器导入原始数据时经常出现的问题 温度记录仪设置为每十分钟记录一次温度 单独的气体记录仪设置为记录最后十分钟间隔内使用的气体 我想将这两个记录器的数据合并到一个数据框中进行绘图和分析 但时间并不完全一致 我希望每十分钟的时间段

随机推荐

  • Spark学习之机器学习包ML

    Spark的ML软件包 其操作是基于DataFrame的 ML包括转换器 Transformer 评估器 Estimator 管道 Pipeline 1 转换器 Transformer 通常是将一个新列附加到DataFrame来转换数据 从
  • React入门

    目录 React简介 官网 介绍描述 React的特点 React高效的原因 React的基本使用 效果 相关js库 创建虚拟DOM的两种方式 虚拟DOM与真实DOM React JSX XML JSON JSX 渲染虚拟DOM 元素 JS
  • 二进制部署Kubernetes

    操作系统 centos7 5 x86 docker 19ce 软件 Kubernetes 1 18 角色 k8s master1 192 168 31 71 组件 kube apiserver kube controller manager
  • C语言atoi函数将字符串类型转换为整型

    atoi 是C标准库中的一个函数 用于将字符串转换为整数 函数原型如下 int atoi const char str 参数 str 是一个指向要转换的字符串的指针 atoi 函数会尝试将字符串中的数字部分转换为整数 并返回转换后的整数值
  • 基于深度学习的验证码自动识别(caffe)

    最近在学习使用caffe 然后就想试着玩玩验证码识别 结果非常非常棒 深度学习确实是非常强大的 废话少说 跟我走进验证码自动识别 caffe安装 此处省略一万字 网上教程千千万 你一定可以找到 接着往下看 剧情描述 之前对京东的某些数据进行
  • 《剑指offer》---22.数值的整数次方

    题目描述 给定一个double类型的浮点数base和int类型的整数exponent 求base的exponent次方 保证base和exponent不同时为0 解题分析 使用快速幂解决 代码 class Solution public d
  • Spring Boot + Vue3前后端分离实战wiki知识库系统<十一>--文档管理功能开发三

    文档内容的显示 在上一次Spring Boot Vue3前后端分离实战wiki知识库系统 十 文档管理功能开发二文档管理模块还差文档的显示木有完成 所以接下来先将这块模块给收尾了 增加单独获取内容的接口 概述 在前端页面文档查询时 只查询了
  • javaMail 使用SMTP邮箱服务器发送邮件

    POP3 SMTP协议 smtp默认端口是 25 接收邮件服务器 pop exmail qq com 使用SSL 端口号995 发送邮件服务器 smtp exmail qq com 使用SSL 端口号465 海外用户可使用以下服务器 接收邮
  • java 用redis如何处理电商平台,秒杀、抢购超卖

    原地址 http blog csdn net u012116196 article details 51782934 一 刚来公司时间不长 看到公司原来的同事写了这样一段代码 下面贴出来 1 这是在一个方法调用下面代码的部分 java vi
  • AutoCAD二次开发_从入门到放弃

    在建筑与设计行业中 CAD有着非常广泛的应用 而其中的很多基本操作无法满足实际需求 容易产生大量的重复性的操作 这种重复性的操作违背了程序设计的思维 因此诞生了入门CAD二次开发的想法 跟大多数程序设计语言一样 在了解CAD二次开发所应用的
  • Kruskal算法&Prim算法的区别

    贪心算法 Kruskal Prim算法的区别 贪心算法是一种对某些求最优解问题的更简单 更迅速的设计技术 贪心算法的特点是一步一步地进行 常以当前情况为基础根据某个优化测度作最优选择 而不考虑各种可能的整体情况 省去了为找最优解要穷尽所有可
  • Linux下搭建Webdav(apache)

    环境 RHEL 5 4 x86 64 创建webdav 1 安装apache yum install httpd y 2 配置webdav vim etc httpd conf httpd conf
  • Ubuntu下用Lean源码编译openwrt及一行命令u盘启动openwrt安装x86硬盘上

    Ubuntu下用Lean源码编译openwrt 源码地址 https github com coolsnowwolf lede 1 首先微软云服务器装好 Ubuntu 64bit 推荐 Ubuntu 20 04 LTS x64 免费一年 i
  • ftell函数的用法(用于获取指针位置)

    ftell函数用于得到文件位置指针当前位置相对于文件首的偏移字节数 下面给出一个简单的例子 cpp view plain copy include
  • 【CKEditor5】CKEditor5相关问题

    问题解决 如图 这个样式没效果 解决方法 因为没有导入css 导入css后 配置style插件就生效了 问 你的css哪来的 答 所有的样式与插件CXEditor5官网都可以找到 配置的css ck ck content font fami
  • 春招Java后端开发面试 2021-10-8

    春招Java后端开发面试 春招Java后端开发面试总结包含了JavaOOP Java集合容器 Java异常 并发编程 Java反射 Java序列化 JVM Redis Spring MVC MyBatis MySQL数据库 消息中间件MQ
  • 常用linux命令记录

    常用linux命令记录 1 常用linux命令基本使用列表 序号 命令 英文 作用 01 ls list 查看当前文件夹的内容 02 pwd print work directory 查看当前所在文件夹 03 cd 目录名 change d
  • 高云FPGA系列教程(5):ARM点灯工程设计

    文章目录 toc 1 ARM核定制 2 ARM核程序设计 3 ARM程序烧写 4 工程下载 本文是高云FPGA系列教程的第5篇文章 前面几篇笔记都是介绍的高云GW1NSR 4C FPGA部分的使用 本篇文章介绍片上ARM Cortex M3
  • MES解决方案 附下载地址

    MES Manufacturing Execution System 即制造企业生产过程执行系统 是一套面向制造企业车间执行层的生产信息化管理系统 是美国AMR公司在90年代初提出的 旨在加强MRP计划的执行功能 把MRP计划同车间作业现场
  • 从源码角度看R语言的format函数

    先提一个问题 请问下面最后的两个逻辑语句的判断 结果是什么 x lt c 1234567 8 12 12345 x11 lt format x scientific FALSE x12 lt format x scientific TRUE