这个问题的答案是 community effort 。编辑现有答案以改进这篇文章。它目前不接受新的答案或互动。








在与同事讨论性能、教学、发送错误报告或在邮件列表和 StackOverflow 上搜索指南时,经常会问到 reproducible example 并且总是很有帮助。

你有什么创建一个优秀例子的技巧?如何以文本格式粘贴 r 中的数据结构?您还应该包含哪些其他信息?

除了使用 dput()dump()structure() 之外,还有其他技巧吗?什么时候应该包含 library()require() 语句?除了 cdfdata 等,还应该避免哪些保留字?

如何制作一个很棒的 r 可重现示例?

最佳答案

基本上 minimal reproducible example (MRE) 应该使其他人能够在他们的机器上准确地重现您的问题。
一个 MRE 由以下项目组成:

  • a 最小数据集 ,演示问题所必需的
  • 最小可运行代码 重现错误所必需的,可以在给定的数据集上运行
  • 全部 必要信息 关于使用的包、R 版本和运行它的操作系统。
  • 在随机过程的情况下,一个 种子 (由 set.seed() 设置)用于可重复性 0x21433

    有关良好 MRE 的示例,请参阅有关您正在使用的函数的帮助文件底部的“示例”部分。只需键入例如help(mean) 或短 ?mean 到您的 R 控制台。
    提供最小数据集
    通常,没有必要共享庞大的数据集,而且可能会阻止其他人阅读您的问题。因此,最好使用内置数据集或创建一个类似于原始数据的小型“玩具”示例,这实际上就是最小化的意思。如果由于某种原因您确实需要共享您的原始数据,您应该使用一种方法,例如 dput() ,它允许其他人获得您数据的精确副本。
    内置数据集
    您可以使用内置数据集之一。内置数据集的完整列表可以通过 data() 看到。每个数据集都有简短的描述,可以获取更多信息,例如使用 ?iris ,对于 R 附带的“虹膜”数据集。安装的包可能包含其他数据集。
    创建示例数据集
    初步说明:有时您可能需要特殊格式(即类),例如因子、日期或时间序列。对于这些,请使用以下函数: as.factoras.Dateas.xts 、... 示例:
    d <- as.Date("2020-12-30")
    
    在哪里
    class(d)
    # [1] "Date"
    
    向量
    x <- rnorm(10)  ## random vector normal distributed
    x <- runif(10)  ## random vector uniformly distributed
    x <- sample(1:100, 10)  ## 10 random draws out of 1, 2, ..., 100
    x <- sample(LETTERS, 10)  ## 10 random draws out of built-in latin alphabet
    
    矩阵
    m <- matrix(1:12, 3, 4, dimnames=list(LETTERS[1:3], LETTERS[1:4]))
    m
    #   A B C  D
    # A 1 4 7 10
    # B 2 5 8 11
    # C 3 6 9 12
    
    数据帧
    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  27 type 1 0.0356312
    # 2  2 2020-12-27     B  19 type 2 1.3149588
    # 3  3 2020-12-28     A  20 type 3 0.9781675
    # 4  4 2020-12-29     B  26 type 4 0.8817912
    # 5  5 2020-12-30     A  26 type 5 0.4822047
    # 6  6 2020-12-31     B  28 type 6 0.9657529
    
    注意: 虽然它被广泛使用,但最好不要将你的数据框命名为 df ,因为 df() 是一个 R 函数,它可能与分布的 Fx1343 的分布高度相冲突,即 18 的分布密度为.
    复制原始数据
    如果您有特定原因,或者数据难以构建示例,您可以提供原始数据的一小部分,最好使用 x
    为什么使用 dputdput() 抛出在控制台上准确重现数据所需的所有信息。您可以简单地复制输出并将其粘贴到您的问题中。
    调用 dput(从上面)产生的输出仍然缺乏关于变量类和其他特征的信息,如果你在你的问题中分享它。此外,dat 列中的空格使其难以执行任何操作。即使我们开始使用这些数据,我们也无法正确获取您数据的重要特征。
      id       date group age   type         x
    1  1 2020-12-26     A  27 type 1 0.0356312
    2  2 2020-12-27     B  19 type 2 1.3149588
    3  3 2020-12-28     A  20 type 3 0.9781675
    
    子集您的数据
    共享一个子集,使用 typehead() 或索引 subset() 。然后把它包装成 iris[1:4, ] 给别人一些可以立即放入 R 的东西。例子
    dput(iris[1:4, ]) # first four rows of the iris data set
    
    控制台输出以分享您的问题:
    structure(list(Sepal.Length = c(5.1, 4.9, 4.7, 4.6), Sepal.Width = c(3.5,
    3, 3.2, 3.1), Petal.Length = c(1.4, 1.4, 1.3, 1.5), Petal.Width = c(0.2,
    0.2, 0.2, 0.2), Species = structure(c(1L, 1L, 1L, 1L), .Label = c("setosa",
    "versicolor", "virginica"), class = "factor")), row.names = c(NA,
    4L), class = "data.frame")
    
    使用 dput() 时,您可能还希望仅包含相关列,例如dput(mtcars[1:3, c(2, 5, 6)])
    注意: 如果您的数据框有一个具有多个级别的因子,则 dput 输出可能会很笨拙,因为它仍然会列出所有可能的因子级别,即使它们不在您的数据子集中。要解决此问题,您可以使用 dput 函数。请注意下面的物种如何是只有一个水平的因素,例如droplevels()dput(droplevels(iris[1:4, ])) 的另一个警告是它不适用于键控 dput 对象或分组 data.table (类 tbl_df 2313 中的 grouped_df 2313 )在这些情况下,您可以在共享之前转换回常规数据帧 tidyverse
    生成最少的代码
    结合最少的数据(见上文),您的代码应该通过简单地复制和粘贴在另一台机器上准确地重现问题。
    这应该是容易的部分,但通常不是。你不应该做的事情:
  • 显示各种数据转换;确保提供的数据格式正确(当然,除非这是问题)
  • 复制粘贴整个脚本,在某处出现错误。尝试找出导致错误的确切行。通常情况下,您会自己找出问题所在。

  • 你应该做什么:
  • 如果您使用任何软件包,请添加您使用的软件包(使用 dput(as.data.frame(my_data)) )
  • 在新的 R session 中测试运行您的代码,以确保代码可运行。人们应该能够在控制台中复制粘贴您的数据和代码,并获得与您相同的结果。
  • 如果您打开连接或创建文件,请添加一些代码来关闭它们或删除文件(使用 library() )
  • 如果您更改选项,请确保代码包含将它们恢复为原始选项的语句。 (例如 unlink() )

  • 提供必要信息
    在大多数情况下,只需 R 版本和操作系统就足够了。当包发生冲突时,给出 op <- par(mfrow=c(1,2)) ...some code... par(op) 的输出真的很有帮助。在谈论与其他应用程序的连接时(无论是通过 ODBC 还是其他任何方式),还应提供这些应用程序的版本号,如果可能,还应提供有关设置的必要信息。
    如果您在 R Studio 中运行 R,使用 sessionInfo() 可以帮助报告您的 RStudio 版本。
    如果您对特定包有问题,您可能希望通过提供 rstudioapi::versionInfo() 的输出来提供包版本。
    种子
    使用 packageVersion("name of the package") 可以指定一个种子 1,即特定状态,R 的随机数生成器是固定的。这使得随机函数(例如 set.seed()sample()rnorm() 和许多其他函数)始终返回相同的结果成为可能,例如:
    set.seed(42)
    rnorm(3)
    # [1]  1.3709584 -0.5646982  0.3631284
    
    set.seed(42)
    rnorm(3)
    # [1]  1.3709584 -0.5646982  0.3631284
    
    1 注: runif() 的输出在R>3.6.0和之前的版本不同。指定用于随机过程的 R 版本,如果在回答旧问题时得到略有不同的结果,请不要感到惊讶。要在这种情况下获得相同的结果,您可以在 set.seed() 之前使用 RNGversion() 函数(例如: set.seed() )。

    关于r - 如何制作出色的 R 可重现示例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5963269/

    10-12 19:22