从源码角度看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函数 的相关文章

  • par(mfrow=c(1,2)) 不显示并排密度图[重复]

    这个问题在这里已经有答案了 par mfrow c 1 2 plot 1 12 log y plot 1 2 xaxs i 然而 当我尝试做并排密度图时 图会单独输出 load the stud recs dataset library U
  • 基于服务器中的条件逻辑呈现闪亮的用户输入

    我正在尝试设置一个闪亮的导航栏面板页面 其中用户控制我根据一组单选按钮中所做的初始选择来显示更改 我直接在 ui 中渲染单选按钮 然后在 Server r 中的 观察到的 逻辑控制结构内构建条件控件 弹出错误是因为我的初始 if 语句计算结
  • R::bigmemory - 如何创建角色big.matrix?

    我尝试使用bigmemory封装在R我一开始就陷入困境 我愿意 temp lt matrix paste a 1 10 5 2 并得到一个字符矩阵 没关系 但后来我尝试 x lt as big matrix temp type char 我
  • 返回数据帧 R 中的下一行

    我有一个看起来像这样的数据框 kind datetime book 2016 04 23 04 23 00 pen 2016 04 23 04 30 00 toy 2016 04 23 06 45 00 我想为数据集中的每一行返回下一行的日
  • ggplot2可以在一个图例中分别控制点大小和线大小(线宽)吗?

    一个使用的例子ggplot2绘制数据点组和连接每组均值的线 并使用相同的映射aes for shape并为linetype p lt ggplot mtcars aes gear mpg shape factor cyl linetype
  • 基于另一个数据集获取数据集的子集

    假设我有一个数据集 即 dat1 ID block plot SPID TotHeight 1 1 1 4 44 5 2 1 1 4 51 3 1 1 4 28 7 4 1 1 4 24 5 5 1 1 4 27 3 6 1 1 4 20
  • 使用 pracma::findpeaks 识别持续峰值

    我的语法有问题peakpat内的选项findpeaks内的函数pramcaR 包 v 2 1 1 我使用的是 R 3 4 3 x64 Windows 我希望该函数能够识别可能有两个重复值的峰值 并且我相信该选项peakpat这就是我能做到的
  • 多功能测试仪替代 system.time

    我已经看到 我认为是这样 使用了类似于 system time 的函数 它可以同时评估多个函数的时间并输出一个输出 我不记得它是什么 并且用我正在使用的术语进行互联网搜索并没有得到我想要的响应 有人知道我正在谈论的功能的名称 位置吗 你想要
  • 如何使用 R 计算成为列表中中位数的概率?

    假设我有以下数据集 其中显示了假设实验的每个状态的三个观察结果的列表 state lt c Iowa Minnesota Illinois outcome lt list c 5 11 11 c 3 12 8 c 9 14 2 dat lt
  • kernlab 中 SVM 训练之外的核矩阵计算

    我正在开发一种新算法 该算法可以生成修改后的核矩阵以用于 SVM 训练 但遇到了一个奇怪的问题 出于测试目的 我比较了使用 kernelMatrix 接口和普通内核接口学习的 SVM 模型 例如 Model with kernelMatri
  • 在 R 中绘制 Likert 变量的堆积条形图

    假设我有一个如下所示的数据框 P Q1 Q2 1 1 4 1 2 2 3 4 3 1 1 4 其中的列告诉我哪个人相应地回答了问题 q1 q2 中的哪一个 这些问题需要按照 4 分李克特量表进行回答 例如 批准 表示 1 稍微批准 表示 2
  • twitterR 和 ROAuth R 软件包安装

    我在安装 CRAN 上的 twitteR 和 RAOuth 软件包时遇到一些问题 我尝试了几种不同的方法 在 Windows 下使用源代码 在 Ubuntu 下使用 RStudio 我尝试了以下命令 sudo apt get install
  • R 中的列乘以子字符串

    假设我有一个数据框 其中包含多个组件及其在多个列中列出的属性 并且我想对这些列运行多个函数 我的方法是尝试将其基于每个列标题中的子字符串 但我无法弄清楚如何做到这一点 下面是数据框的示例 Basket F Type 1 F Qty 1 F
  • 将每列的值乘以 R 中另一个 data.frame 中的权重

    我有两个data frames df and weights 代码如下 df看起来像这样 id a b d EE f 1 this 0 23421153 0 02324956 0 5457353 0 73068586 0 5642554 2
  • r 中训练和测试数据的最小最大缩放/归一化

    我正在创建一个函数 它将训练集和测试集作为其参数 最小 最大缩放 标准化并返回训练集并使用这些same最小值和最小 最大范围的值 标准化并返回测试集 到目前为止 这是我想出的功能 min max scaling lt function tr
  • 朴素贝叶斯分类器仅基于先验概率做出决策

    我试图根据推文的情绪将推文分为三类 买入 持有 卖出 我正在使用 R 和包 e1071 我有两个数据框 一个训练集和一组需要预测情绪的新推文 训练集数据框 text sentiment this stock is a good buy Bu
  • 将数据框中重叠的范围合并到唯一的组中

    我有一个 n 行 3 的数据框 df lt data frame start c 178 400 983 1932 33653 end c 5025 5025 5535 6918 38197 group c 1 1 2 2 3 df sta
  • 将阴影区域添加到五分位数之间的直方图中

    All 我有一个包含 2 个直方图的图表 其中我还绘制了代表第 20 40 60 和 80 个百分位数的线条 下面的代码使用虚拟数据重现了类似的图表 data lt rbind data frame x rnorm 1000 0 1 g o
  • 在 r 中的 group_by 之后建模后取消列表列的嵌套

    我想对所有组进行线性回归group by 将模型系数保存在列表列中 然后使用 unnest 扩展列表列 这里我用的是mtcars以数据集为例 注 我想用do here becausebroom tidy 不适用于所有型号 mtcars gt
  • 文本挖掘 pdf 文件/词频问题

    我正在尝试挖掘一篇具有丰富 pdf 编码和图表的文章的 pdf 我注意到 当我挖掘一些 pdf 文档时 我得到的高频词是 phi taeoe toe sigma gamma 等 它与某些 pdf 文档配合良好 但与其他文档配合使用时却得到这

随机推荐

  • 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