2468

在与同事讨论性能、教学、发送错误报告或在邮件列表和 Stack Overflow 上搜索指导时,经常会询问可重现的示例,并且总是很有帮助。

你对创建一个优秀的例子有什么建议?如何以文本格式粘贴来自您还应该包括哪些其他信息?

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

如何制作一个很好的可示例?

4

23 回答 23

1865

基本上,一个最小可重现示例 (MRE)应该能够让其他人在他们的机器上准确地重现您的问题。

MRE 由以下项目组成:

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

有关良好 MRE 的示例,请参阅您正在使用的函数的帮助文件底部的“示例”部分。只需在 R 控制台中输入 eghelp(mean)或 short即可。?mean

提供最小数据集

通常,不需要共享庞大的数据集,而且可能会阻止其他人阅读您的问题。因此,最好使用内置数据集或创建一个类似于您的原始数据的小型“玩具”示例,这实际上是最小的意思。如果出于某种原因您确实需要共享您的原始数据,您应该使用一种方法,例如dput(),允许其他人获取您的数据的精确副本。

内置数据集

您可以使用其中一种内置数据集。可以使用 来查看内置数据集的完整列表data()。每个数据集都有一个简短的描述,并且可以获得更多信息,例如?irisR 附带的“iris”数据集。安装的包可能包含其他数据集。

创建示例数据集

初步说明:有时您可能需要特殊格式(即类),例如因子、日期或时间序列。对于这些,请使用以下功能:as.factor, as.Date, as.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()它是 F 分布的密度(即曲线在点的高度)的 R 函数,x您可能会与它发生冲突。

复制原始数据

如果您有特定原因,或者数据很难从中构建示例,您可以提供原始数据的一小部分,最好使用dput.

为什么使用dput()

dput抛出在控制台上准确再现数据所需的所有信息。您可以简单地复制输出并将其粘贴到您的问题中。

如果您在问题中共享它,则调用dat(从上面)产生的输出仍然缺少有关变量类和其他功能的信息。此外,列中的空格type使得它很难做任何事情。即使我们开始使用这些数据,我们也无法正确获取您数据的重要特征。

  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

子集您的数据

Tho 共享子集、使用head()subset()索引iris[1:4, ]。然后把它包装进去dput(),给别人一些可以立即放入 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输出可能会很笨拙,因为它仍会列出所有可能的因子级别,即使它们不存在于您的数据子集中。要解决此问题,您可以使用该droplevels()功能。请注意下面的物种是如何只有一个水平的因素,例如dput(droplevels(iris[1:4, ]))。另一个需要注意的是,dput它不适用于键控data.table对象tbl_dfgrouped_df. tidyverse在这些情况下,您可以在共享之前转换回常规数据框,dput(as.data.frame(my_data)).

生成最少的代码

结合最少的数据(见上文),您的代码应该通过简单地复制和粘贴来准确地在另一台机器上重现问题。

这应该是容易的部分,但通常不是。你不应该做的事情:

  • 显示各种数据转换;确保提供的数据已经采用正确的格式(当然,除非这是问题所在)
  • 复制粘贴在某处出现错误的整个脚本。尝试找出导致错误的确切行。很多时候,你会发现问题出在自己身上。

你应该做什么:

  • 如果您使用任何软件包,请添加您使用的软件包(使用library()
  • test 在新的 R 会话中运行您的代码,以确保代码可运行。人们应该能够在控制台中复制粘贴您的数据和代码并获得与您相同的内容。
  • 如果您打开连接或创建文件,请添加一些代码以关闭它们或删除文件(使用unlink()
  • 如果您更改选项,请确保代码包含将它们恢复为原始选项的语句。(例如op <- par(mfrow=c(1,2)) ...some code... par(op)

提供必要的信息

在大多数情况下,只需 R 版本和操作系统就足够了。当与包发生冲突时,提供 的输出sessionInfo()真的很有帮助。在谈论与其他应用程序的连接时(无论是通过 ODBC 还是其他任何方式),还应提供这些应用程序的版本号,如果可能,还应提供有关设置的必要信息。

如果您在R Studio中运行 R ,使用rstudioapi::versionInfo()可以帮助报告您的 RStudio 版本。

如果您对特定包有问题,您可能希望通过提供packageVersion("name of the package").

种子

使用set.seed()您可以指定种子1,即特定状态,R 的随机数生成器是固定的。这使得随机函数(例如sample()、和许多其他函数rnorm()runif()始终返回相同的结果成为可能,例如:

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注意: R >3.6.0 和以前的版本之间的输出不同。指定您用于随机过程的 R 版本,如果您在回答旧问题时得到的结果略有不同,请不要感到惊讶。要在这种情况下获得相同的结果,您可以在之前使用 -function (例如:) set.seed()RNGversion()set.seed()RNGversion("3.5.2")

于 2011-05-11T11:40:18.877 回答
623

(这是我对如何写一个可重现的例子的建议。我试图让它简短但甜蜜)。

如何编写可重现的示例

如果您提供可重现的示例,您最有可能在您的 R 问题上得到很好的帮助。一个可重现的示例允许其他人通过复制和粘贴 R 代码来重现您的问题。

您需要包括四件事以使您的示例可重现:所需的包、数据、代码和 R 环境的描述。

  • 应该在脚本的顶部加载,所以很容易看出示例需要哪些包。

  • 在电子邮件或 Stack Overflow 问题中包含数据dput()的最简单方法是使用生成 R 代码来重新创建它。例如,要mtcars在 R 中重新创建数据集,我将执行以下步骤:

    1. dput(mtcars)在 R 中运行
    2. 复制输出
    3. 在我的可重现脚本中,键入mtcars <- 然后粘贴。
  • 花一点时间确保您的代码易于他人阅读:

    • 确保你使用了空格并且你的变量名简洁,但信息丰富

    • 使用注释指出您的问题所在

    • 尽最大努力删除与问题无关的所有内容。
      你的代码越短,就越容易理解。

  • sessionInfo()在代码中的注释中包含输出。这总结了您的R 环境,并且可以轻松检查您是否使用过时的包。

您可以通过启动一个新的 R 会话并粘贴您的脚本来检查您是否确实制作了一个可重现的示例。

在将所有代码放入电子邮件之前,请考虑将其放在Gist github 上。它将为您的代码提供良好的语法突出显示,您不必担心任何内容会被电子邮件系统破坏。

于 2011-05-11T13:57:51.190 回答
321

就个人而言,我更喜欢“一个”衬里。类似的东西:

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包处理空间数据,您可以生成一些随机数据。可以在包 vignette 中找到很多示例,但这里有一个小块。

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 shapefile)获取一些数据集(请参阅任务视图中的空间视图)。

library(rgdal)
ogrDrivers()
dsn <- system.file("vectors", package = "rgdal")[1]
ogrListLayers(dsn)
ogrInfo(dsn=dsn, layer="cities")
cities <- readOGR(dsn=dsn, layer="cities")
于 2011-05-11T11:22:15.987 回答
296

受这篇文章的启发, reproduce(<mydata>)当我需要发布到 Stack Overflow 时,我现在使用了一个方便的功能。


快速说明

如果myData是要复制的对象的名称,请在 R 中运行以下命令:

install.packages("devtools")
library(devtools)
source_url("https://raw.github.com/rsaporta/pubR/gitbranch/reproduce.R")

reproduce(myData)

细节:

此函数是一个智能包装器,dput并执行以下操作:

  • 自动对大型数据集进行采样(基于大小和类别。可以调整样本大小)
  • 创建dput输出
  • 允许您指定要导出的列
  • 附加到它的前面objName <- ...,以便可以轻松复制+粘贴,但是...
  • 如果在 Mac 上工作,输出会自动复制到剪贴板,这样您就可以简单地运行它,然后将其粘贴到您的问题中。

源代码可在此处获得:


例子:

# sample data
DF <- data.frame(id=rep(LETTERS, each=4)[1:100], replicate(100, sample(1001, 100)), Class=sample(c("Yes", "No"), 100, TRUE))

DF 约为 100 x 102。我想采样 10 行和一些特定列

reproduce(DF, cols=c("id", "X1", "X73", "Class"))  # I could also specify the column number.

给出以下输出:

This is what the sample looks like:

    id  X1 X73 Class
1    A 266 960   Yes
2    A 373 315    No            Notice the selection split
3    A 573 208    No           (which can be turned off)
4    A 907 850   Yes
5    B 202  46   Yes
6    B 895 969   Yes   <~~~ 70 % of selection is from the top rows
7    B 940 928    No
98   Y 371 171   Yes
99   Y 733 364   Yes   <~~~ 30 % of selection is from the bottom rows.
100  Y 546 641    No


    ==X==============================================================X==
         Copy+Paste this part. (If on a Mac, it is already copied!)
    ==X==============================================================X==

 DF <- structure(list(id = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 25L, 25L, 25L), .Label = c("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y"), class = "factor"), X1 = c(266L, 373L, 573L, 907L, 202L, 895L, 940L, 371L, 733L, 546L), X73 = c(960L, 315L, 208L, 850L, 46L, 969L, 928L, 171L, 364L, 641L), Class = structure(c(2L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 2L, 1L), .Label = c("No", "Yes"), class = "factor")), .Names = c("id", "X1", "X73", "Class"), class = "data.frame", row.names = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 98L, 99L, 100L))

    ==X==============================================================X==

还要注意,整个输出是一条漂亮的单行长行,而不是一段高高的截断行。这使得阅读 Stack Overflow 问题帖子更容易,也更容易复制+粘贴。


2013 年 10 月更新:

您现在可以指定将占用多少行文本输出(即,您将粘贴到 Stack Overflow 中的内容)。lines.out=n为此使用论据。例子:

reproduce(DF, cols=c(1:3, 17, 23), lines.out=7)产量:

    ==X==============================================================X==
         Copy+Paste this part. (If on a Mac, it is already copied!)
    ==X==============================================================X==

 DF <- structure(list(id = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 25L,25L, 25L), .Label
      = c("A", "B", "C", "D", "E", "F", "G", "H","I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U","V", "W", "X", "Y"), class = "factor"),
      X1 = c(809L, 81L, 862L,747L, 224L, 721L, 310L, 53L, 853L, 642L),
      X2 = c(926L, 409L,825L, 702L, 803L, 63L, 319L, 941L, 598L, 830L),
      X16 = c(447L,164L, 8L, 775L, 471L, 196L, 30L, 420L, 47L, 327L),
      X22 = c(335L,164L, 503L, 407L, 662L, 139L, 111L, 721L, 340L, 178L)), .Names = c("id","X1",
      "X2", "X16", "X22"), class = "data.frame", row.names = c(1L,2L, 3L, 4L, 5L, 6L, 7L, 98L, 99L, 100L))

    ==X==============================================================X==
于 2013-05-13T22:20:34.470 回答
209

这是一个很好的指南

最重要的一点是:做一小段代码,我们可以运行看看是什么问题。一个有用的函数是dput(),但是如果你有非常大的数据,那么你可能想要制作一个小样本数据集或者只使用前 10 行左右。

编辑:

另外,请确保您确定了问题出在哪里。该示例不应是带有“在第 200 行出现错误”的整个 R 脚本。如果您使用 R(我喜欢browser())和 Google 中的调试工具,那么您应该能够真正确定问题出在哪里,并重现一个出现同样问题的简单示例。

于 2011-05-11T11:21:24.100 回答
178

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 行的数据框,三列名为“行”、“列”和“值”,它们的维度名称为“行”和“列”的值,如下所示:

  > 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")

)

这个词尤其重要。您应该瞄准一个最小的可重现示例,这意味着数据和代码应该尽可能简单地解释问题。

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

于 2011-05-11T13:17:38.937 回答
173

从 R.2.14(我猜)开始,您可以将数据文本表示直接提供给read.table

 df <- read.table(header=TRUE, 
  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
") 
于 2012-06-29T08:32:04.220 回答
153

有时,无论您如何努力,问题确实无法用较小的数据重现,并且不会发生在合成数据上(尽管展示您如何生成没有重现问题的合成数据集很有用,因为它排除了一些假设)。

  • 可能需要将数据发布到网络上的某个地方并提供 URL。
  • 如果数据不能向公众公开,但完全可以共享,那么您可以提议通过电子邮件将其发送给感兴趣的各方(尽管这将减少愿意工作的人数)在上面)。
  • 我实际上并没有看到这样做,因为不能发布他们的数据的人对发布任何形式的数据都很敏感,但在某些情况下,如果数据被充分匿名/加扰/稍微损坏,人们仍然可以发布数据似乎是合理的某种程度上来说。

如果你不能做这些,那么你可能需要聘请顾问来解决你的问题......

编辑:匿名化/加扰的两个有用的 SO 问题:

于 2011-07-14T19:49:15.733 回答
142

到目前为止的答案对于可重复性部分来说显然是很好的。这只是为了澄清可重现的示例不能也不应该是问题的唯一组成部分。不要忘记解释您希望它看起来像什么以及问题的轮廓,而不仅仅是您到目前为止是如何尝试到达那里的。代码不够;你也需要文字。

这是一个可重复的示例,说明应避免做什么(取自真实示例,更改名称以保护无辜者):


以下是我遇到问题的示例数据和部分功能。

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

我怎样才能做到这一点?


于 2012-07-09T15:41:13.287 回答
131

I have a very easy and efficient way to make a R example that has not been mentioned above. You can define your structure firstly. For example,

mydata <- data.frame(a=character(0), b=numeric(0),  c=numeric(0), d=numeric(0))

>fix(mydata)

When you execute 'fix' command, you will get this pop-up box

Then you can input your data manually. This is efficient for smaller examples rather than big ones.

于 2014-02-20T09:11:37.990 回答
128

要快速创建dput数据,您只需将数据复制(一部分)到剪贴板并在 R 中运行以下命令:

对于 Excel 中的数据:

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

对于.txt文件中的数据:

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

sep如有必要,您可以更改后者。当然,这只有在您的数据在剪贴板中时才有效。

于 2013-04-10T14:51:08.993 回答
128

指导方针:


您设计问题的主要目标应该是让读者尽可能容易地理解并在他们的系统上重现您的问题。为此:

  1. 提供输入数据
  2. 提供预期的输出
  3. 简明扼要地解释你的问题
    • 如果您有超过 20 行文本 + 代码,您可能可以返回并简化
    • 尽可能简化代码,同时保留问题/错误

这确实需要一些工作,但由于您要求其他人为您工作,这似乎是一个公平的权衡。

提供数据:


内置数据集

到目前为止,最好的选择是依赖内置数据集。这使得其他人很容易解决您的问题。在 R 提示符下键入data()以查看您可以使用哪些数据。一些经典的例子:

  • iris
  • mtcars
  • ggplot2::diamonds(外包装,但几乎人人都有)

检查内置数据集以找到适合您问题的数据集。

如果您可以重新表述您的问题以使用内置数据集,那么您更有可能获得好的答案(和赞成票)。

自生成数据

如果您的问题特定于现有数据集中未表示的一种数据类型,请提供 R 代码,该代码生成您的问题在其上表现出来的最小可能数据集。例如

set.seed(1)  # important to make random data reproducible
myData <- data.frame(a=sample(letters[1:5], 20, rep=T), b=runif(20))

试图回答我的问题的人可以复制/粘贴这两行并立即开始解决问题。

输入

作为最后的手段,您可以使用dput将数据对象转换为 R 代码(例如dput(myData))。我说是“最后的手段”,因为输出dput通常相当笨拙,复制粘贴很烦人,并且掩盖了您的其余问题。

提供预期输出:


曾经有人说过:

一张预期输出的图片值 1000 字

——贤者

如果您可以添加类似“我希望得到这个结果”之类的内容:

   cyl   mean.hp
1:   6 122.28571
2:   4  82.63636
3:   8 209.21429

对于您的问题,人们更有可能理解您要快速做的事情。如果您的预期结果很大且难以处理,那么您可能还没有充分考虑如何简化您的问题(见下文)。

简洁地解释你的问题


要做的主要事情是在您提出问题之前尽可能简化您的问题。重新构建问题以使用内置数据集将在这方面有很大帮助。你也会经常发现,只要通过简化的过程,你就会回答你自己的问题。

以下是一些好问题的例子:

在这两种情况下,用户的问题几乎肯定不在于他们提供的简单示例。相反,他们将问题的性质抽象出来,并将其应用于一个简单的数据集来提出他们的问题。

为什么还要回答这个问题?


这个答案侧重于我认为的最佳实践:使用内置数据集并以最小的形式提供您期望的结果。最突出的答案集中在其他方面。我不希望这个答案上升到任何突出地位。这只是为了让我可以在对新手问题的评论中链接到它。

于 2015-02-12T15:24:00.503 回答
124

可重现的代码是获得帮助的关键。然而,有许多用户可能对粘贴他们的一大块数据持怀疑态度。例如,他们可能正在处理敏感数据或收集用于研究论文的原始数据。

出于任何原因,我认为在公开粘贴之前有一个方便的功能来“变形”我的数据会很好。anonymize包中的功能SciencesPo非常愚蠢,但对我来说,它与该功能很好地配合使用dput

install.packages("SciencesPo")

dt <- data.frame(
    Z = sample(LETTERS,10),
    X = sample(1:10),
    Y = sample(c("yes", "no"), 10, replace = TRUE)
)
> dt
   Z  X   Y
1  D  8  no
2  T  1 yes
3  J  7  no
4  K  6  no
5  U  2  no
6  A 10 yes
7  Y  5  no
8  M  9 yes
9  X  4 yes
10 Z  3  no

然后我将其匿名化:

> anonymize(dt)
     Z    X  Y
1   b2  2.5 c1
2   b6 -4.5 c2
3   b3  1.5 c1
4   b4  0.5 c1
5   b7 -3.5 c1
6   b1  4.5 c2
7   b9 -0.5 c1
8   b5  3.5 c2
9   b8 -1.5 c2
10 b10 -2.5 c1

在应用匿名化和 dput 命令之前,可能还需要对一些变量而不是整个数据进行采样。

    # Sample two variables without replacement
> anonymize(sample.df(dt,5,vars=c("Y","X")))
   Y    X
1 a1 -0.4
2 a1  0.6
3 a2 -2.4
4 a1 -1.4
5 a2  3.6
于 2014-11-27T02:02:02.237 回答
107

通常您需要一些数据作为示例,但是,您不想发布您的确切数据。要使用已建立库中的一些现有 data.frame,请使用 data 命令导入它。

例如,

data(mtcars)

然后做问题

names(mtcars)
your problem demostrated on the mtcars data set
于 2013-02-22T15:29:33.070 回答
100

如果您有一个无法轻松放入脚本的大型数据集,dput()请将您的数据发布到pastebin并使用以下方法加载它们read.table

d <- read.table("http://pastebin.com/raw.php?i=m1ZJuKLH")

灵感来自亨利克

于 2014-01-03T19:07:03.950 回答
94

我正在开发wakefield来解决快速共享可重现数据的需求,有时它dput适用于较小的数据集,但我们处理的许多问题要大得多,通过共享如此大的数据集dput是不切实际的。

关于:

wakefield允许用户共享最少的代码来重现数据。用户设置n(行数)并指定任意数量的预设变量函数(目前有 70 个)模拟真实的数据(如性别、年龄、收入等)

安装:

目前(2015-06-11),wakefield是一个 GitHub 包,但在编写单元测试后最终会转到 CRAN。要快速安装,请使用:

if (!require("pacman")) install.packages("pacman")
pacman::p_load_gh("trinker/wakefield")

例子:

这是一个例子:

r_data_frame(
    n = 500,
    id,
    race,
    age,
    sex,
    hour,
    iq,
    height,
    died
)

这会产生:

    ID  Race Age    Sex     Hour  IQ Height  Died
1  001 White  33   Male 00:00:00 104     74  TRUE
2  002 White  24   Male 00:00:00  78     69 FALSE
3  003 Asian  34 Female 00:00:00 113     66  TRUE
4  004 White  22   Male 00:00:00 124     73  TRUE
5  005 White  25 Female 00:00:00  95     72  TRUE
6  006 White  26 Female 00:00:00 104     69  TRUE
7  007 Black  30 Female 00:00:00 111     71 FALSE
8  008 Black  29 Female 00:00:00 100     64  TRUE
9  009 Asian  25   Male 00:30:00 106     70 FALSE
10 010 White  27   Male 00:30:00 121     68 FALSE
.. ...   ... ...    ...      ... ...    ...   ...
于 2015-06-11T13:57:38.023 回答
77

如果您factor的数据中有一个或多个变量要使其可重现,请dput(head(mydata))考虑添加droplevels它,以便最小化数据集中不存在的因子水平不包含在您的dput输出中,以便使示例最小化

dput(droplevels(head(mydata)))
于 2015-01-09T15:09:51.513 回答
70

我想知道http://old.r-fiddle.org/链接是否是一种非常巧妙的分享问题的方式。它收到一个唯一的 ID,甚至可以考虑将其嵌入 SO。

于 2015-01-09T13:11:48.777 回答
51

请不要像这样粘贴您的控制台输出:

If I have a matrix x as follows:
> 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
>

How can I turn it into a dataframe with 8 rows, and three
columns named `row`, `col`, and `value`, which have the
dimension names as the values of `row` and `col`, like this:
> x.df
    row col value
1    A   x      1
...
(To which the answer might be:
> 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")
)

我们不能直接复制粘贴。

为了使问题和答案可正确重现,请尝试在发布之前删除+&并放入如下输出和评论:>#

#If I have a matrix x as follows:
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

# How can I turn it into a dataframe with 8 rows, and three
# columns named `row`, `col`, and `value`, which have the
# dimension names as the values of `row` and `col`, like this:

#x.df
#    row col value
#1    A   x      1
#...
#To which the answer might be:

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")

还有一件事,如果您使用了某个包中的任何功能,请提及该库。

于 2016-07-22T10:01:36.653 回答
41

您可以使用reprex执行此操作。

正如mt1022 所指出的,“......用于生成最小、可重现示例的好包是来自tidyverse 的reprex ”。

根据Tidyverse

“reprex”的目标是打包有问题的代码,以便其他人可以运行它并感受到你的痛苦。

tidyverse网站上给出了一个示例。

library(reprex)
y <- 1:4
mean(y)
reprex() 

我认为这是创建可重现示例的最简单方法。

于 2017-08-18T19:02:43.107 回答
37

除了我发现非常有趣的所有上述答案之外,有时它可能很容易,因为它在这里讨论:如何制作一个最小的可重现示例来获得 R 的帮助

有很多方法可以制作随机向量创建一个 100 数字向量,其中 R 中的随机值四舍五入到 2 位小数或 R 中的随机矩阵:

mydf1<- matrix(rnorm(20),nrow=20,ncol=5)

请注意,有时由于维度等各种原因,很难共享给定的数据。但是,以上所有答案都很棒,并且在想要制作可重现的数据示例时考虑和使用它们非常重要. 但是注意,为了让数据和原始数据一样具有代表性(以防OP无法共享原始数据),最好在数据示例中添加一些信息(如果我们将数据称为mydf1)

class(mydf1)
# this shows the type of the data you have
dim(mydf1)
# this shows the dimension of your data

此外,应该知道数据的类型、长度和属性,可以是数据结构

#found based on the following
typeof(mydf1), what it is.
length(mydf1), how many elements it contains.
attributes(mydf1), additional arbitrary metadata.

#If you cannot share your original data, you can str it and give an idea about the structure of your data
head(str(mydf1))
于 2016-04-20T10:50:39.527 回答
30

以下是我的一些建议:

  • 尝试使用默认的 R 数据集
  • 如果您有自己的数据集,请将它们包含在 中dput,以便其他人可以更轻松地帮助您
  • install.package()除非真的必要,否则不要使用,如果您只是使用require或使用,人们会理解的library
  • 尽量简洁,

    • 有一些数据集
    • 尝试尽可能简单地描述您需要的输出
    • 在你问问题之前自己做
  • 上传图片很容易,所以如果有的话,请上传图
  • 还包括您可能遇到的任何错误

所有这些都是可重现示例的一部分。

于 2016-04-09T18:15:19.467 回答
21

使用testthat包中的函数来显示您期望发生的事情是个好主意。因此,其他人可以更改您的代码,直到它运行没有错误。这减轻了那些想帮助你的人的负担,因为这意味着他们不必解码你的文字描述。例如

library(testthat)
# code defining x and y
if (y >= 10) {
    expect_equal(x, 1.23)
} else {
    expect_equal(x, 3.21)
}

比“我认为当 y 等于或超过 10 时 x 为 1.23,否则为 3.21,但我没有得到任何结果”更清楚。即使在这个愚蠢的例子中,我认为代码比文字更清晰。使用testthat可以让您的助手专注于代码,从而节省时间,并为他们提供了一种在发布之前知道他们已经解决了您的问题的方法

于 2017-04-04T21:08:35.587 回答