在与同事讨论性能,教学,发送错误报告或在邮件列表上搜索指导时,以及在Stack Overflow上,通常会询问reproducible example并始终提供帮助 .
您有什么建议创建优秀示例的提示?如何以文本格式粘贴r的数据结构?您应该包括哪些其他信息?
除了使用 dput()
, dump()
还是 structure()
之外还有其他技巧吗?什么时候应该包含 library()
或 require()
语句?应该避免哪些保留字,除了 c
, df
, data
等?
如何成为一个伟大的可重复的例子?
23 回答
(这是我对How to write a reproducible example的建议 . 我试图让它变短但很甜)
如何编写可重现的示例 .
如果您提供可重现的示例,您最有可能获得R问题的良好帮助 . 一个可重现的示例允许其他人通过复制和粘贴R代码来重新创建您的问题 .
为了使您的示例可重现,您需要包含四件事:所需的包,数据,代码和R环境的描述 .
Packages 应该加载在脚本的顶部,因此很容易看出示例需要哪些 .
在电子邮件或Stack Overflow问题中包含 data 的最简单方法是使用
dput()
生成R代码以重新创建它 . 例如,要在R中重新创建mtcars
数据集,我将执行以下步骤:在R中运行
dput(mtcars)
复制输出
在我的可重现脚本中,键入
mtcars <-
然后粘贴 .花一点时间确保你的 code 易于他人阅读:
确保您使用了空格,并且您的变量名称简洁,但信息丰富
使用注释来指出问题所在
尽力删除与问题无关的所有内容 .
代码越短,理解起来就越容易 .
在代码中的注释中包含
sessionInfo()
的输出 . 这总结了您的 R environment ,可以轻松检查您是否使用了过时的软件包 .你可以通过启动一个新的R会话并粘贴你的脚本来检查你是否真的做了一个可重现的例子 .
在将所有代码放入电子邮件之前,请考虑将其放在Gist github上 . 它将为您的代码提供良好的语法突出显示,您不必担心电子邮件系统会破坏任何内容 .
受到这篇文章的启发,我现在使用了一个方便的功能
reproduce(<mydata>)
当我需要发布到StackOverflow时 .快速说明
如果
myData
是要重现的对象的名称,请在R中运行以下命令:详情:
此函数是
dput
的智能包装器,并执行以下操作:自动对大型数据集进行采样(基于大小和类别 . 可以调整样本大小)
创建
dput
输出允许您指定要导出的列
附加到它的前面
objName <- ...
,以便它可以轻松复制粘贴,但......如果在mac上工作,输出会自动复制到剪贴板,这样您就可以简单地运行它,然后粘贴到您的问题中 .
来源可在此处获得:
示例:
DF约为100 x 102.我想抽样10行,以及一些特定的列
提供以下输出:
另请注意,输出的整体是一条漂亮的单行,长行,而不是一段很高的切割线 . 这样可以更容易地阅读SO问题帖子,也更容易复制粘贴 .
2013年10月更新:
您现在可以指定将占用多少行文本输出(即,您将粘贴到StackOverflow中的内容) . 为此使用
lines.out=n
参数 . 例:reproduce(DF, cols=c(1:3, 17, 23), lines.out=7)
收益率:这是一个很好的指南:
http://www.r-bloggers.com/three-tips-for-posting-good-questions-to-r-help-and-stack-overflow/
但最重要的是:确保你制作了一小段我们可以运行的代码来查看问题所在 . 一个有用的函数是
dput()
,但是如果你有非常大的数据,你可能想要制作一个小样本数据集或只使用前10行左右 .编辑:
还要确保您确定问题出在哪里 . 该示例不应该是带有"On line 200 there is an error"的整个R脚本 . 如果您使用R中的调试工具(我爱
browser()
)和谷歌,您应该能够真正确定问题所在,并重现一个简单的例子,其中同样的事情出错了 .如果您希望数据中有一个或多个
factor
变量可以使用dput(head(mydata))
重现,请考虑将droplevels
添加到其中,以便最小化数据集中不存在的因子级别不包含在dput
输出中,为了使示例最小化:自从R.2.14(我猜)你可以提供你的数据文本直接表示read.table:
有时这个问题确实不会出现在合成数据中(尽管显示你如何生成合成数据集是很有用的,因为它排除了一些假设).263997_会重现问题 .
可能需要在某处将数据发布到Web并提供URL .
如果数据无法向公众发布但可以共享,那么您可以通过电子邮件将其发送给感兴趣的各方(尽管这会减少需要打扰的人数)在...上下功夫) .
我没有发布他们的数据对于以任何形式发布它们是敏感的,但似乎有理由认为,如果在某种程度上稍微充分匿名化/加扰/损坏,仍然可以发布数据 .
如果您不能做其中任何一项,那么您可能需要聘请一名顾问来解决您的问题......
edit :匿名/加扰的两个有用的SO问题:
How to create example data set from private data (replacing variable names and levels with uninformative place holders)?
Given a set of random numbers drawn from a continuous univariate distribution, find the distribution
可重复性最小的示例包含以下项目:
重现错误所必需的最小数据集
重现错误所需的最小 runnable 代码,可以在给定数据集上运行 .
有关所使用的包,R版本及其运行的系统的必要信息 .
_999_在随机过程的情况下,种子(由
set.seed()
设置)用于再现性查看已使用函数的帮助文件中的示例通常很有帮助 . 一般来说,那里给出的所有代码都满足最小可重复示例的要求:提供数据,提供最少的代码,并且一切都是可运行的 .
生成最小数据集
对于大多数情况,只需提供带有某些值的矢量/数据帧即可轻松完成 . 或者您可以使用大多数软件包提供的内置数据集之一 .
可以使用
library(help = "datasets")
查看内置数据集的完整列表 . 每个数据集都有一个简短的描述,例如,使用?mtcars
可以获得更多信息,其中'mtcars'是列表中的数据集之一 . 其他包可能包含其他数据集 .制作矢量很容易 . 有时需要为它添加一些随机性,并且有许多功能可以实现 .
sample()
可以随机化一个向量,或者给出一个只有几个值的随机向量 .letters
是一个包含字母表的有用矢量 . 这可以用于制作因素 .几个例子:
随机值:
x <- rnorm(10)
表示正态分布,x <- runif(10)
表示均匀分布,...一些值的排列:
x <- sample(1:10)
对于矢量1:10的随机顺序 .随机因素:
x <- sample(letters[1:4], 20, replace = TRUE)
对于矩阵,可以使用
matrix()
,例如:使用
data.frame()
可以完成数据帧 . 应注意在数据框中命名条目,并且不要使其过于复杂 .一个例子 :
对于某些问题,可能需要特定格式 . 对于这些,可以使用任何提供的
as.someType
函数:as.factor
,as.Date
,as.xts
,......这些与矢量和/或数据框技巧结合使用 .复制您的数据
如果您有一些使用这些提示难以构建的数据,那么您始终可以使用例如
head()
,subset()
或索引来创建原始数据的子集 . 然后使用例如 .dput()
给我们一些可以立即放入R的东西:如果您的数据框具有多个级别的因子,则
dput
输出可能不实用,因为它仍会列出所有可能的因子级别,即使它们不存在于您的数据子集中 . 要解决此问题,可以使用droplevels()
函数 . 请注意以下物种是如何只有一个水平的因素:另一个警告
dput
是它不适用于键控data.table
对象或tbl_df
(类grouped_df
)来自dplyr
. 在这些情况下,您可以在共享之前转换回常规数据帧,dput(as.data.frame(my_data))
.在最坏的情况下,您可以使用
read.table
的text
参数提供可以读取的文本表示:生成最少的代码
这应该是容易的部分,但往往不是 . 你不应该做的是:
添加所有类型的数据转换 . 确保提供的数据格式正确(除非这是问题)
复制粘贴一个产生错误的整个函数/代码块 . 首先,尝试找出确切导致错误的行 . 通常情况下,你会发现自己的问题是什么 .
你应该做的是:
如果您使用任何包,请添加(使用
library()
)如果您打开连接或创建文件,添加一些代码来关闭它们或删除文件(使用
unlink()
)如果更改选项,请确保代码包含一个语句,以将其还原为原始语句 . (例如
op <- par(mfrow=c(1,2)) ...some code... par(op)
)test在新的空R会话中运行您的代码,以确保代码可运行 . 人们应该能够在控制台中复制粘贴您的数据和代码,并获得与您完全相同的信息 .
提供额外信息
在大多数情况下,仅R版本和操作系统就足够了 . 当包与包含冲突时,给出
sessionInfo()
的输出确实有帮助 . 在谈论与其他应用程序的连接时(无论是通过ODBC还是其他任何应用程序),还应该为这些应用程序提供版本号,如果可能,还应提供有关设置的必要信息 .如果您使用
rstudioapi::versionInfo()
在R Studio中运行R,则可以帮助报告您的RStudio版本 .如果您对特定包有问题,可能需要通过提供
packageVersion("name of the package")
的输出来提供包的版本 .除了我发现非常有趣的所有上述答案之外,它有时可能非常容易,因为它在这里讨论: - HOW TO MAKE A MINIMAL REPRODUCIBLE EXAMPLE TO GET HELP WITH R
有许多方法可以在R中制作随机向量Create a 100 number vector with random values in R rounded to 2 decimals或随机矩阵
请注意,由于诸如尺寸等各种原因,有时共享给定数据非常困难 . 但是,当想要制作可重现的数据示例时,所有上述答案都很好并且非常重要 . 但请注意,为了使数据具有代表性(如果OP不能共享原始数据),最好用数据示例添加一些信息(如果我们调用数据mydf1)
此外,应该知道数据的类型,长度和属性,可以Data structures
以下是我的一些建议:
尝试使用默认的R数据集
如果您有自己的数据集,请将它们包含在
dput
中,以便其他人可以更轻松地帮助您除非确实有必要,否则不要使用
install.package()
,如果您只是使用require
或library
,人们会理解尽量简洁,
有一些数据集
尝试尽可能简单地描述您需要的输出
在提出问题之前自己动手
上传图片很容易,如果有,请上传图表
还包括您可能遇到的任何错误
所有这些都是可重复的例子的一部分 .
要快速创建
dput
数据,您只需将数据(一段)复制到剪贴板并在R中运行以下命令:对于Excel中的数据:
对于txt文件中的数据:
如有必要,您可以在后者中更改
sep
. 这只适用于您的数据当然在剪贴板中的情况 .我想知道http://old.r-fiddle.org/链接是否是一种非常简洁的方式来分享问题 . 它接收一个唯一的ID,甚至可以考虑将其嵌入到SO中 .
R-help邮件列表有posting guide,其中包括提问和回答问题,包括生成数据的示例:
small 这个词特别重要 . 您应该瞄准一个可重复的示例,这意味着数据和代码应该尽可能简单来解释问题 .
编辑:漂亮的代码比丑陋的代码更容易阅读 . 使用style guide .
通常,您需要一些示例数据,但是,您不希望发布您的确切数据 . 要在已 Build 的库中使用某些现有data.frame,请使用data命令将其导入 .
例如 . ,
然后解决问题
您可以使用reprex执行此操作 .
作为mt1022 noted,“......用于生成最小,可重复的示例的良好包装是 "reprex" 来自tidyverse” .
根据Tidyverse:
在tidyverse网站上给出了一个例子 .
我认为这是 simplest way 创建一个可重复的例子 .
到目前为止,答案对于再现性部分来说显然是很好的 . 这仅仅是为了澄清一个可重复的例子不能也不应该是问题的唯一组成部分 . 不要忘记解释你想要它的样子和问题的轮廓,而不仅仅是你到目前为止试图到达那里的方式 . 代码还不够;你还需要单词 .
这是一个可重复的例子,说明要避免做什么(从一个真实的例子中提取,名称改为保护无辜者):
以下是我遇到问题的示例数据和部分功能 .
我怎样才能做到这一点?
如果您有大型数据集,使用
dput()
无法轻松将其放入脚本,请将数据发布到pastebin并使用read.table
加载它们:灵感来自@Henrik .
就个人而言,我更喜欢“一个”衬里 . 一些事情:
数据结构应该模仿作者's problem and not the exact verbatim structure. I really appreciate it when variables don't覆盖我自己的变量或者上帝禁止的功能(如
df
) .或者,可以剪切几个角并指向预先存在的数据集,例如:
不要忘记提及您可能使用的任何特殊包装 .
如果你想在更大的物体上展示一些东西,你可以试试
如果您通过
raster
包处理空间数据,则可以生成一些随机数据 . 在包装插图中可以找到很多例子,但这里有一个小块 .如果您需要
sp
中实现的某些空间对象,您可以通过"spatial"包中的外部文件(如ESRI shapefile)获取一些数据集(请参阅任务视图中的空间视图) .使用
testthat
包中的函数来显示您期望发生的内容是个好主意 . 因此,其他人可以更改您的代码,直到它运行没有错误 . 这减轻了那些想要帮助你的人的负担,因为这意味着他们不必解码你的文字描述 . 例如比"I think x would come out to be 1.23 for y equal to or exceeding 10, and 3.21 otherwise, but I got neither result"更清楚 . 即使在这个愚蠢的例子中,我认为代码比单词更清晰 . 使用
testthat
可让您的助手专注于代码,从而节省时间,并为他们提供一种方式让他们知道他们已经解决了您的问题,然后再发布我正在开发wakefield package以满足快速共享可重复数据的需求,有时
dput
适用于较小的数据集,但我们处理的许多问题要大得多,通过dput
共享如此大的数据集是不切实际的 .About:
wakefield允许用户共享最少的代码来重现数据 . 用户设置
n
(行数)并指定任何数量的预设变量函数(当前有70个)模拟真实数据(性别,年龄,收入等)Installation:
目前(2015-06-11),wakefield是一个GitHub包,但最终会在编写单元测试后转到CRAN . 要快速安装,请使用:
Example:
这是一个例子:
这会产生:
可重复的代码是获得帮助的关键 . 但是,有许多用户可能会对即使是一大块数据进行粘贴持怀疑态度 . 例如,他们可能正在处理敏感数据或收集用于研究论文的原始数据 . 出于任何原因,我认为在公开粘贴之前为我的数据提供一个方便的功能会很好 . 包
SciencesPo
中的anonymize
函数非常愚蠢,但对我来说它与dput
函数很好地配合 .然后我将它匿名化:
在应用匿名化和dput命令之前,可能还需要对少量变量进行采样而不是整个数据 .
指南:
制定问题的主要目的应该是让读者尽可能轻松地理解并在他们的系统上重现您的问题 . 为此:
提供输入数据
提供预期产出
简洁地解释你的问题
如果您有超过20行文本代码,您可以返回并简化
尽可能简化代码,同时保留问题/错误
这确实需要一些工作但似乎是公平的权衡,因为你要求别人为你工作 .
提供数据:
内置数据集
最好的选择 by far 依赖于内置数据集 . 这使得其他人可以轻松解决您的问题 . 在R提示符下键入
data()
以查看可用的数据 . 一些经典的例子:iris
mtcars
ggplot2::diamonds
(外包装,但几乎每个人都有)有关如何查找适合您的问题的数据集,请参阅此 SO QA .
如果您能够重新解释您的问题以使用内置数据集,则您更有可能获得良好的答案(和upvotes) .
自生成数据
如果您的问题非常特定于现有数据集中未表示的数据类型,则提供生成 smallest 可能数据集的R代码,您的问题将在其中显示 . 例如
现在有人试图回答我的问题,可以复制/粘贴这两行,并立即开始处理问题 .
dput
作为 last resort ,您可以使用
dput
将数据对象转换为R代码(例如dput(myData)
) . 我说是"last resort"因为dput
的输出通常相当笨拙,很难复制粘贴,并且模糊了你的其余问题 .提供预期输出:
有人说过:
如果您可以添加“我希望得到此结果”之类的内容:
对你的问题,人们更有可能快速了解你想要做什么 . 如果您的预期结果很大且难以处理,那么您可能还没有充分考虑如何简化问题(参见下文) .
简洁地解释你的问题
要做的主要是在提出问题之前尽可能简化问题 . 重新构建问题以使用内置数据集将在这方面提供很多帮助 . 您还经常会发现,只需通过简化过程,您就可以回答自己的问题 .
以下是一些好问题的例子:
with built in data set
with user generated data
在这两种情况下,用户的问题几乎肯定不是他们提供的简单示例 . 相反,他们抽象出问题的本质,并将其应用于一个简单的数据集来提出问题 .
为什么还有这个问题的另一个答案?
这个答案侧重于我认为最佳实践:使用内置数据集并以最小的形式提供您期望的结果 . 最突出的答案集中在其他方面 . 我不希望这个答案上升到任何突出的地位;这只是为了让我可以在对新手问题的评论中链接到它 .
我有一个非常简单有效的方法来制作一个上面没有提到的R例子 . 您可以先定义结构 . 例如,
然后您可以手动输入数据 . 这对于较小的示例而不是较大的示例是有效的 .
请不要粘贴您的控制台输出,如下所示:
我们不能直接复制粘贴它 .
要使问题和答案正确重现,请尝试在发布之前删除
+
&>
并将#
用于输出和注释,如下所示:还有一件事,如果您使用了某个包中的任何函数,请提及该库 .