r-faq - 如何让一个R 可重现的例子?

  显示原文与译文双语对照的内容

在讨论性能与同事,教学为指导去,送出 Bug 报表或者搜索邮件列表和这里是这样,持续可以复制示例上往往要求并且总是有帮助的。

创建一个优秀示例的技巧是什么? 如何以文本格式从 粘贴数据结构? 应该包括哪些其他信息?

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

如何使一个伟大的 可以重复示例?

时间:

一个可以重复的示例包含以下项目:

  • 用于重现错误的最小数据集
  • 重现错误所需的最小可以运行的代码,可以在给定的数据集中运行。
  • 在使用的软件包,R 版本和系统上运行所需的信息。
  • 在随机过程中,种子( 由 set.seed() 设置) 用于重现

查看所使用函数的帮助文件中的示例通常很有用。 通常,给定的所有代码都满足了最小可以重复示例的需求: 提供了数据,提供了最少的代码,并且一切都是可以运行的。

生成最小数据集

在大多数情况下,只需提供一个带有一些值的向量/dataframe就可以轻松完成。 或者你可以使用一个内置的数据集,大多数软件包都提供了这些数据集。

生成矢量很容易。 有时有必要给它增加一些随机性,而且有很多函数可以让它。 sample() 可以随机化一个向量,或者给出一个只含有几个值的随机向量。 letters 是一个包含字母表的有用向量。 这可以用于制作因子。

几个例子:

  • 随机值:x <- rnorm(10) 用于正态分布,x <- runif(10) 用于均匀分布,。。
  • 一些值的置换: 在随机order,为向量 1: x <- sample(1:10)
  • 随机因素: x <- sample(letters[1:4], 20, replace = TRUE)

对于矩阵,可以使用 matrix(),例如:


matrix(1:10, ncol = 2)

使dataframes可以使用 data.frame() 完成。 要注意dataframe中的条目,不要让它过于复杂。

一个示例:


Data <- data.frame(
 X = sample(1:10),
 Y = sample(c("yes","no"), 10, replace = TRUE)
)

对于某些问题,需要特定的格式。 对于这些,你可以使用任何提供的as.someType 函数: as.factoras.Dateas.xts,。。 这些结合了矢量和/或者dataframe技巧。

复制数据

如果你有一些使用这些技巧难以构造的数据,那么你可以使用 head()subset() 或者索引组成原始数据的子集。 然后使用 dput() 来给我们一些可以立即放入 R的东西:


> dput(head(iris,4))
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")),. Names = c("Sepal.Length", 
"Sepal.Width","Petal.Length","Petal.Width","Species"), row.names = c(NA, 
4L), class ="data.frame")

使用 text 参数中,更糟糕的情况,你可以给一个文本表示,它可以 read:


zz <-"Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa"

Data <- read.table(text=zz, header = TRUE)

生成最小代码

这应该是简单的部分,但通常不是。 你不应该做的是:

  • 添加各种类型的数据转换。 确保所提供的数据已经是正确的格式( 除非这是当然的问题)
  • copy-paste一个给出错误的整个函数/块。 首先尝试找出哪些行恰好导致错误。 通常你会发现问题是什么。

你应该做的是:

  • 如果使用任何软件包,添加哪些软件包。
  • 如果打开连接或者生成文件,请添加一些代码以关闭或者删除文件( 使用 unlink() )
  • 如果你更改了选项,请确保代码包含一个语句,以便将它们恢复到原来的状态。 ( 如 op <- par(mfrow=c(1,2)).. .some code... par(op) )
  • testrun在一个新的空 R 会话中执行代码,确保代码是可以运行的。 人们应该能够在控制台中copy-paste的数据和代码,并得到完全相同的结果。

提供额外信息

在大多数情况下,仅仅是 R 版本和操作系统就够了。 当软件包出现冲突时,给出 sessionInfo()的输出会很有帮助。 当谈到与其他应用程序的连接时,( 是通过ODBC还是其他任何方式) 也应该提供版本号,如果可能的话,还需要安装的必要信息。

个人而言,我更喜欢"一个"衬垫。 沿着以下线条:


my.df <- data.frame(col1 = sample(c(1,2), 10, replace = TRUE),
 col2 = as.factor(sample(10)), col3 = letters[1:10],
 col4 = sample(c(TRUE, FALSE), 10, replace = TRUE))
my.list <- list(list1 = my.df, list2 = my.df[3], list3 = letters)

数据结构应该模仿作者的问题,而不是确切的逐字结构。 当变量不覆盖我自己的变量或者禁止使用函数( 像 df ) 时,我非常感激。

或者,可以剪切几个角点并指向一个预先存在的数据集,比如:


library(vegan)
data(varespec)
ord <- metaMDS(varespec)

别忘了提及你可能正在使用的任何特殊软件包。

如果你试图在较大的对象上演示某些东西,你可以尝试


my.df2 <- data.frame(a = sample(10e6), b = sample(letters, 10e6, replace = TRUE))

如果你使用 raster 包处理空间数据,你可以生成一些随机数据。 大量的例子可以在包中找到小插图,但这里是一个小熔核。


library(raster)
r1 <- r2 <- r3 <- raster(nrow=10, ncol=10)
values(r1) <- runif(ncell(r1))
values(r2) <- runif(ncell(r2))
values(r3) <- runif(ncell(r3))
s <- stack(r1, r2, r3)

如果是在需要一些空间对象在 sp 中实现时,你可以得到一些数据集的可以通过外部( 像ESRI形状文件) ( 在任务视图中查看空间视图)"空间空间"软件包中的文件。


library(rgdal)
ogrDrivers()
dsn <- system.file("vectors", package ="rgdal")[1]
ogrListLayers(dsn)
ogrInfo(dsn=dsn, layer="cities")
cities <- readOGR(dsn=dsn, layer="cities")

这是一个很好的指南:

http://www.r-bloggers.com/three-tips-for-posting-good-questions-to-r-help-and-stack-overflow/

但最重要的是: 请确保你制作了一小段代码,我们可以运行它来查看问题是什么。 一个有用的函数是 dput(),但是如果你有非常大的数据,你可能需要制作一个小样本数据集,或者只使用前 10行。

编辑:

同时确保你确定了问题所在。 该示例不应该是一个整体 R 集剧本 如果你在 R ( 我爱 browser() ) 和google中使用调试工具,你应该能够真正识别出问题所在,并重现一个简单的例子,其中出现了错误。

R-help邮件列表包含张贴指南,它涵盖了询问和回答问题,包括生成数据的示例:

示例:有时提供一个小示例,这样某人实际上可以运行。 例如:

如果我有一个矩阵x,如下所示:


> x <- matrix(1:8, nrow=4, ncol=2,
 dimnames=list(c("A","B","C","D"), c("x","y"))
> x
 x y
 A 1 5
 B 2 6
 C 3 7
 D 4 8
> 

我怎么能把它变成一个与 8 dataframe行。三列命名'行','上校',和'值',含义,它的维度名称为'行'和'上校'的值,像这样:


> x.df
 row col value
 1 A x 1


( 答案可能是:


> x.df <- reshape(data.frame(row=rownames(x), x), direction="long",
 varying=list(colnames(x)), times=colnames(x),
 v.names="value", timevar="col", idvar="row")

)

is特别重要。 你应该瞄准一个最小可以再现的例子,这意味着数据和代码应该尽量简单来解释你的问题。

编辑:漂亮的代码比丑陋的代码更容易阅读。 使用样式指南

由于 R.2.14 ( 我觉得),你可以直接将数据文本表示形式馈送给 read.table:


df <- read.table(header=T, text="Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
") 

有时,问题真的是不可再生的和一个较小的数据 Fragment,无论你如何努力尝试,并是并不是用人造数据( 虽然它非常有用,以显示你是如何产生合成数据集,而且做了不是重现该问题,因为它排除了一定的假设前提下) 发生。

  • 将数据发送到站点并提供URL可能是必要的。
  • 如果数据不能在很大程度上公开给公众,但可以共享的话,那么你可以提供给 E-mail的相关各方。
  • 我还没有看到这样做,因为那些不能释放数据的人对释放数据很敏感,但是在某些情况下,如果有足够的anonymized/scrambled/corrupted,仍然可以发布数据。

如果你不能做到这一点,那么你可能需要聘请一个顾问来解决你的问题。

编辑: 两个有用的问题,用于匿名/置乱:

目前为止的答案对于重复性部分来说很明显。 这只是为了阐明一个可以重复的例子不能并且不应是问题的唯一组件。 不要忘了解释你想要它看起来像什么和你的问题轮廓,而不仅仅是你是如何尝试到目前为止的。 代码不够;你需要单词。

下面是一个可以重现的示例,可以避免执行( 从一个真实的例子中得出,改名为保护无辜):


以下是示例数据和函数的一部分,但我有问题。


code
code
code
code
code (40 or so lines of it)

我如何实现这个?


在你的数据你可以简单的拷贝的来快速创建 dput ( 一块) 将数据复制到剪贴板中并运行 following:

对于Excel中的数据:


dput(read.table("clipboard",sep="t",header=TRUE))

用于 txt file: 中的数据


dput(read.table("clipboard",sep="",header=TRUE))

如果需要,你可以在后者中更改 sep 。 只有当你的数据在剪贴板中时,才会工作。

...