如何制作一个伟大的R可重复的例子

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

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

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

如何制作一个伟大的可重复的例子?

418484 次浏览

这是一个很好的指南

最重要的一点是:编写一小段代码,我们可以运行它来查看问题所在。一个有用的函数是dput(),但如果您有非常大的数据,那么您可能希望制作一个小样本数据集或仅使用前10行左右。

编辑:

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

就个人而言,我更喜欢“一个”衬垫。大致如下:

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

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

基本上,最小可重现示例(MRE)应该允许其他人完全在他们的机器上复制您的问题。

请不要发布您的数据、代码或控制台输出的图像!

tl; dr

地雷风险评估包括以下项目:

  • 最小数据集,需要证明问题
  • 重现问题所需的最小可运行代码,可以在给定数据集上运行
  • 所有必要的信息都在使用的library、R版本和运行它的操作系统上,也许是sessionInfo()
  • 在随机进程的情况下,种子(由set.seed()设置)使其他人能够复制与您完全相同的结果

有关良好MRE的示例,请参阅您正在使用的函数的帮助页面底部的“示例”部分。只需在R控制台中键入例如help(mean)或简短的?mean

提供最小数据集

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

内置数据集

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

创建示例数据集

初步说明:有时您可能需要特殊格式(即类),例如因子、日期或时间序列。对于这些,请使用以下函数:as.factoras.Dateas.xts、…示例:

d <- as.Date("2020-12-30")

在哪里

class(d)# [1] "Date"

矢量图

x <- rnorm(10)  ## random vector normal distributedx <- runif(10)  ## random vector uniformly distributedx <- sample(1:100, 10)  ## 10 random draws out of 1, 2, ..., 100x <- 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 reproducibilityn <- 6dat <- 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分布的密度(即曲线在点x的高度)的R函数,您可能会与它发生冲突。

复制原始数据

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

为什么使用dput()

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

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

  id       date group age   type         x1  1 2020-12-26     A  27 type 1 0.03563122  2 2020-12-27     B  19 type 2 1.31495883  3 2020-12-28     A  20 type 3 0.9781675

子集您的数据

要共享一个子集,请使用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(mtcar[1:3, c(2,5,6)])

注意:如果你的数据帧有一个具有许多级别的因子,dput的输出可能会很笨拙,因为它仍然会列出所有可能的因子级别,即使它们不存在于你的数据的子集中。要解决这个问题,你可以使用droplevels()函数。请注意下面的物种是一个只有一个级别的因子,例如dput(droplevels(iris[1:4, ]))dput的另一个警告是,它不适用于data.table键控对象或tidyverse中的分组tbl_df(类grouped_df)。在这些情况下,你可以在共享之前转换回常规数据帧,dput(as.data.frame(my_data))

生成最小代码

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

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

  • 显示所有类型的数据转换;确保提供的数据已经是正确的格式(当然,除非这是问题所在)
  • 复制粘贴一个完整的脚本,在某个地方给出一个错误。试着找出哪些行确切地导致了错误。通常情况下,你会发现问题出在自己身上。

你应该做什么:

  • 如果您使用任何包,请添加您使用的包(使用library()
  • 在新的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 注意:#0的输出在R>3.6.0和以前的版本之间存在差异。请指定您用于随机过程的R版本,如果在关注旧问题时得到的结果略有不同,请不要感到惊讶。在这种情况下要获得相同的结果,您可以使用#0之前的#1-函数(例如:#3)。

R-help邮件列表有一个投稿指南,它涵盖了提问和回答问题,包括生成数据的示例:

示例:有时它有助于举个小例子可以实际运行。例如:

如果我有一个矩阵x如下:

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

如何将其转换为数据框8行,3列命名`row'、`coll'和`value',它们具有维度名称为'row'和'coll'的值,如下所示:

  > x.dfrow col value1    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")

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

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

(这是我从如何写一个可重复的例子得到的建议。我试着让它简短但甜蜜)。

如何写一个可重复的例子

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

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

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

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

    1. 在R中运行dput(mtcars)
    2. 复制输出
    3. 在我的可复制脚本中,键入mtcars <- 然后粘贴。
  • 花点时间确保你的代码很容易让别人知道阅读:

    • 确保您使用了空格并且变量名称简洁,但是信息

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

    • 尽量去掉一切与问题无关的东西。
      代码越短,越容易理解。

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

您可以通过启动一个新的R会话并粘贴您的脚本来检查您实际上已经制作了一个可重复的示例。

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

有时,无论你多么努力,这个问题都无法用较小的数据来重现,而且合成数据也不会发生(尽管展示你如何生成合成数据集来重现问题是很有用的,因为它排除了一些假设)。

  • 将数据发布到Web某处并提供URL可能是必要的。
  • 如果数据不能向公众发布,但可以共享,那么您可以将其通过电子邮件发送给感兴趣的人(尽管这将减少愿意为此工作的人数)。
  • 我还没有看到这样做,因为那些不能发布数据的人对发布任何形式的数据都很敏感,但在某些情况下,如果数据足够匿名/加扰/以某种方式稍微损坏,人们仍然可以发布数据,这似乎是合理的。

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

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

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

 df <- read.table(header=TRUE,text="Sepal.Length Sepal.Width Petal.Length Petal.Width Species1          5.1         3.5          1.4         0.2  setosa2          4.9         3.0          1.4         0.2  setosa3          4.7         3.2          1.3         0.2  setosa4          4.6         3.1          1.5         0.2  setosa5          5.0         3.6          1.4         0.2  setosa6          5.4         3.9          1.7         0.4  setosa")

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

这是一个可重复的例子,说明应该避免做什么(来自一个真实的例子,改变名字以保护无辜者):


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

codecodecodecodecode (40 or so lines of it)

我怎样才能做到这一点?


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

例如,

data(mtcars)

然后再做题

names(mtcars)your problem demostrated on the mtcars data set

要快速创建数据的dput,您只需将(一段)数据复制到剪贴板并在R中运行以下操作:

对于Excel中的数据:

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

对于. txt文件中的数据:

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

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

受这篇文章的启发,我现在使用一个方便的函数,reproduce(<mydata>)当我需要发布到堆栈溢出时。


快速指令

如果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 dataDF <- 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 Class1    A 266 960   Yes2    A 373 315    No            Notice the selection split3    A 573 208    No           (which can be turned off)4    A 907 850   Yes5    B 202  46   Yes6    B 895 969   Yes   <~~~ 70 % of selection is from the top rows7    B 940 928    No98   Y 371 171   Yes99   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==

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

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

灵感由Henrik

我有一个非常简单有效的方法来制作上面没有提到的R示例。您可以首先定义您的结构。例如,

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

当你执行'修复'命令时,你会得到这个弹出框

然后您可以手动输入数据。这对于较小的示例而不是大的示例是有效的。

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

出于某种原因,我认为在公开粘贴数据之前有一个方便的“变形”函数会很好。包SciencesPo中的anonymize函数非常愚蠢,但对我来说,它与dput函数一起工作得很好。

install.packages("SciencesPo")
dt <- data.frame(Z = sample(LETTERS,10),X = sample(1:10),Y = sample(c("yes", "no"), 10, replace = TRUE))
> dtZ  X   Y1  D  8  no2  T  1 yes3  J  7  no4  K  6  no5  U  2  no6  A 10 yes7  Y  5  no8  M  9 yes9  X  4 yes10 Z  3  no

然后我把它匿名化:

> anonymize(dt)Z    X  Y1   b2  2.5 c12   b6 -4.5 c23   b3  1.5 c14   b4  0.5 c15   b7 -3.5 c16   b1  4.5 c27   b9 -0.5 c18   b5  3.5 c29   b8 -1.5 c210 b10 -2.5 c1

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

    # Sample two variables without replacement> anonymize(sample.df(dt,5,vars=c("Y","X")))
   Y    X1 a1 -0.42 a1  0.63 a2 -2.44 a1 -1.45 a2  3.6

最初的帖子提到了datacamp现已退役的r-fiddle服务。它已被重新命名为datacamp light,并且不像我的回答所指出的那样容易嵌入。

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

如果您的数据中有一个或多个factor变量,您希望使用dput(head(mydata))进行重现,请考虑向其添加droplevels,以便最小化数据集中不存在的因素级别不包含在您的dput输出中,以使示例最小

dput(droplevels(head(mydata)))

指引:


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

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

这确实需要一些工作,但这似乎是一个公平的权衡,因为你要求别人为你做工作。

提供数据:


内置数据集

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

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

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

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

自生成数据

如果您的问题特定于存量数据集中未表示的数据类型,则提供R代码,该代码生成您的问题所体现的最小个可能的数据集

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

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

dput

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

提供预期产出:


有人曾经说过:

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

一个圣人

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

   cyl   mean.hp1:   6 122.285712:   4  82.636363:   8 209.21429

对于你的问题,人们更有可能快速理解你想要做的事情。如果你的预期结果是大而笨重的,那么你可能没有充分考虑如何简化你的问题(见下一步)。

简明扼要地解释你的问题


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

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

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

为什么这个问题还有另一个答案?


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

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

关于:

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

安装:

目前(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  Died1  001 White  33   Male 00:00:00 104     74  TRUE2  002 White  24   Male 00:00:00  78     69 FALSE3  003 Asian  34 Female 00:00:00 113     66  TRUE4  004 White  22   Male 00:00:00 124     73  TRUE5  005 White  25 Female 00:00:00  95     72  TRUE6  006 White  26 Female 00:00:00 104     69  TRUE7  007 Black  30 Female 00:00:00 111     71 FALSE8  008 Black  29 Female 00:00:00 100     64  TRUE9  009 Asian  25   Male 00:30:00 106     70 FALSE10 010 White  27   Male 00:30:00 121     68 FALSE.. ...   ... ...    ...      ... ...    ...   ...

以下是我的一些建议:

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

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

所有这些都是一个可重复的例子的一部分。

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

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

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

需要注意的是,有时由于维度等各种原因,想要共享一个给定的数据是非常困难的。然而上述所有答案都很好,在想要做出可重现的数据示例时,这些答案对于思考和使用都非常重要。但需要注意的是,为了使数据与原始一样具有代表性(万一OP无法共享原始数据),最好是与数据示例一起添加一些信息作为(如果我们调用数据mydf1)

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

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

#found based on the followingtypeof(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 datahead(str(mydf1))

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

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")))> xx yA 1 5B 2 6C 3 7D 4 8>
How can I turn it into a dataframe with 8 rows, and threecolumns named `row`, `col`, and `value`, which have thedimension names as the values of `row` and `col`, like this:> x.dfrow col value1    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")

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

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

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

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

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

mt1022注意到所示,“……用于产生最小的、可重复的示例的好包是"reprex"来自tidyverse”。

根据Tidyverse

“reprex”的目标是将有问题的代码打包成其他人可以运行它并感受到您的痛苦的方式。

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

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

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