再现性 : Failing to rerun code over time

标签 r period binary-reproducibility

我担心将来运行的代码可能会失败。我用 tidyverse 看过这个运行良好但一段时间后返回错误的函数,因为它们已被 Defunct .为了给出一些可重现的例子,试试这段来自 How to make a great R reproducible example 的代码。具有讽刺意味的是,它不再可重现(将 agex 的值与原始帖子进行比较):

set.seed(42)  ## for sake of reproducibility
n <- 6
dat <- data.frame(id=1:n, 
                  date=seq.Date(as.Date("2020-12-26"), as.Date("2020-12-31"), "day"),
                  group=rep(LETTERS[1:2], n/2),
                  age=sample(18:30, n, replace=TRUE),
                  type=factor(paste("type", 1:n)),
                  x=rnorm(n))
dat
  id       date group age   type           x
1  1 2020-12-26     A  29 type 1  0.63286260
2  2 2020-12-27     B  30 type 2  0.40426832
3  3 2020-12-28     A  21 type 3 -0.10612452
4  4 2020-12-29     B  28 type 4  1.51152200
5  5 2020-12-30     A  26 type 5 -0.09465904
6  6 2020-12-31     B  24 type 6  2.01842371

问题

是否在更新后完全相同的代码返回不同的输出?换句话说:包和 R本身通常不会自动更新,所以这是否意味着只要我不手动更新任何东西,我就可以“永远”地重新运行一个函数?有没有异常(exception)?

我为什么要问

我使用 bcrypt 为我的公司加密敏感数据包装在 R .我们需要对数据进行加密删除原始数据。一旦完成,就没有回头路了,也就是说,我真的必须相信代码。我没有使用包,但 bcrypt , shinyshinydashboard .

编辑

我的问题假设代码在同一系统上运行而没有更改全局设置(根据@qdread 的评论进行编辑)并且没有更改 R 版本。

我的详细工作:我处理患者数据。首先,我为每位患者选择一个由字母和数字组成的随机 ID,例如A72CV对于 Max Cooper 1987-05-03 .在下一步中,我使用 bcrypt为每位患者创建盐,然后我使用盐创建 ID 的散列/加密版本(盐 + ID = 加密 ID)。因此每个患者都有姓名+生日、随机字母/数字 ID、盐(使用 salt <- bcrypt::gensalt(log_rounds = 12) 生成)和加密 ID(使用 id_encrypted <- bcrypt::hashpw(id, salt = salt) 生成)。我将数据保存在三个单独的文件中:(i) 患者数据,即姓名和出生日期,以及加密的 ID,(ii) ID 和盐,以及 (iii) 带有 ID 和许多感兴趣变量的实际数据库,例如吸烟者/体重,...这种方法在我工作的环境中被一些机构推荐,它被称为假名化(一种可逆加密)。它确保即使存在数据泄漏,识别变量 name + birthday 与所有感兴趣的变量(吸烟者,...)之间也没有明显的联系。我制作了一个 shinyApp,允许我的同事 (1) 提供 ID 并查找姓名 + 生日,(2) 提供姓名 + 生日并查找 ID,以及 (3) 为新患者生成 ID。这一切都有效,因为具有相同 salt 的相同 ID 会产生相同的加密(散列)ID——至少目前是这样。但是,如果将来由于某些原因相同的输入(例如 ID)不会返回相同的输出(例如姓名 + 生日),我就完蛋了。另一方面,如果随机 ID 的生成会随着时间而改变,这不是什么大问题,因为每个 ID 只创建和保存一次,即这个过程不必是可重现的。所描述的加密方法将应用于我所在机构多年收集的一些数据库。如果我们不能重新创建数据,那么一切都会丢失。这就是代码稳定性对我如此重要的原因。我会在同事的 windows 电脑上安装 shinyApp。他们只会点击 run App里面R然后执行之前描述的选项之一(1 到 3)。

最佳答案

(部分回答。)

sample 的默认行为在 R-3.6.0 中发生了变化。值得注意的是,在 NEWS-3在 R-3.6.0 下,它在 SIGNIFICANT USER-VISIBLE CHANGES 下声明:

The default method for generating from a discrete uniform distribution (used in sample(), for instance) has been changed. This addresses the fact, pointed out by Ottoboni and Stark, that the previous method made sample() noticeably non-uniform on large populations. See PR#17494 for a discussion. The previous method can be requested using RNGkind() or RNGversion() if necessary for reproduction of old results. Thanks to Duncan Murdoch for contributing the patch and Gabe Becker for further assistance.

我们可以通过更改 sample.kind="Rounding" 重新获得 age 随机值,

RNGkind(sample.kind = "Rounding")
# Warning in RNGkind(sample.kind = "Rounding") :
#   non-uniform 'Rounding' sampler used

set.seed(42)  ## for sake of reproducibility
n <- 6
dat <- data.frame(id=1:n, 
                  date=seq.Date(as.Date("2020-12-26"), as.Date("2020-12-31"), "day"),
                  group=rep(LETTERS[1:2], n/2),
                  age=sample(18:30, n, replace=TRUE),
                  type=factor(paste("type", 1:n)),
                  x=rnorm(n))
dat
#   id       date group age   type           x
# 1  1 2020-12-26     A  29 type 1  0.63286260
# 2  2 2020-12-27     B  30 type 2  0.40426832
# 3  3 2020-12-28     A  21 type 3 -0.10612452
# 4  4 2020-12-29     B  28 type 4  1.51152200
# 5  5 2020-12-30     A  26 type 5 -0.09465904
# 6  6 2020-12-31     B  24 type 6  2.01842371

至于更改后的 rnorm 输出,在同一链接中指出

Note: The output of set.seed() differs between R >3.6.0 and previous versions. Specify which R version you used for the random process, and don't be surprised if you get slightly different results when following old questions. To get the same result in such cases, you can use the RNGversion()-function before set.seed() (e.g.: RNGversion("3.5.2")).

不幸的是,我无法重现 x-column 的链接版本。


生产中如何处理?在单元测试中依赖真正的随机数总是粗略的(出于诸如此类的原因),主要原因有两个:您不能总是假设未播种的随机值会达到您想要的极端情况;正如您在此处看到的那样,种子随机值会受到“错误修复”或 PRNG 过程改进的影响。

关于再现性 : Failing to rerun code over time,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71127911/

相关文章:

.net - 确定 .NET 程序集是否是从同一源构建的

可重现的 saveRDS 环境

r - 从 R 中的字符向量中提取数字和下一个字符串

r - 逐部分建立公式

windows - 如何在 HH :29:55 and HH:59:55 in a windows batch file 触发命令

ruby-on-rails - ruby on rails - routes.rb - 当文件名中存在多个句点时匹配文件扩展名

r - 在 R 中将未知长度的序列拆分为一定数量的集合

r - 拆分 vs by + 子集

java - 如何从字符串中提取 3 个数字