在与同事讨论绩效、教学、发送错误报告或搜索邮件列表和Stack Overflow上的指导时,经常会询问一个可重复的示例,并且总是很有用。
你有什么建议来创建一个优秀的例子?如何以文本格式粘贴r中的数据结构?您还应包括哪些其他信息?
除了使用dput()、dump()或structure()之外,还有其他技巧吗?什么时候应该包含library()或require()语句?除了c、df、data等之外,应该避免哪些保留字。?
如何做出一个伟大的、可重复的例子?
在与同事讨论绩效、教学、发送错误报告或搜索邮件列表和Stack Overflow上的指导时,经常会询问一个可重复的示例,并且总是很有用。
你有什么建议来创建一个优秀的例子?如何以文本格式粘贴r中的数据结构?您还应包括哪些其他信息?
除了使用dput()、dump()或structure()之外,还有其他技巧吗?什么时候应该包含library()或require()语句?除了c、df、data等之外,应该避免哪些保留字。?
如何做出一个伟大的、可重复的例子?
当前回答
请不要像这样粘贴控制台输出:
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")
还有一件事,如果您使用了某个包中的任何函数,请提及该库。
其他回答
(这是我如何写一个可复制的例子的建议。我试图让它简短而甜蜜)。
如何编写可复制的示例
如果你提供了一个可重复的例子,你最有可能在R问题上得到很好的帮助。一个可复制的示例允许其他人通过复制和粘贴R代码来重新创建您的问题。
为了使示例具有可复制性,您需要包括四个方面:所需的包、数据、代码和R环境的描述。
包应该在脚本的顶部加载,因此很容易看看示例需要哪些。在电子邮件或堆栈溢出问题中包含数据的最简单方法是使用dput()生成R代码以重新创建它。例如,要在R中重新创建mtcars数据集,我将执行以下步骤:在R中运行dput(mtcars)复制输出在我的可复制脚本中,键入mtcars<-然后粘贴。花一点时间确保您的代码易于其他人使用内容如下:确保使用了空格,变量名称简洁,但是提供有用信息的使用注释指出问题所在尽最大努力删除与问题无关的所有内容。代码越短,越容易理解。在代码的注释中包含sessionInfo()的输出。这总结了您的R环境,并使其易于检查您是否使用了过时的包裹
您可以通过启动一个新的R会话并粘贴脚本来检查是否确实制作了一个可复制的示例。
在将所有代码放入电子邮件之前,请考虑将其放在Gistgithub上。它会给你的代码提供很好的语法高亮显示,你不必担心任何东西会被电子邮件系统破坏。
以下是我的一些建议:
尝试使用默认的R数据集如果您有自己的数据集,请将其包含在dput中,这样其他人可以更轻松地帮助您除非确有必要,否则不要使用install.package(),人们会理解您是否只使用require或library尽量简明扼要,有一些数据集尽量简单地描述您需要的输出问问题之前自己做上传图片很容易,所以如果你有还包括您可能遇到的任何错误
所有这些都是可复制示例的一部分。
受到这篇文章的启发,我现在使用了一个方便的功能,当我需要发布到堆栈溢出时,repeat(<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上工作,输出会自动复制到剪贴板,这样您就可以简单地运行它,然后将其粘贴到问题中。
可在以下位置获得来源:
GitHub-pubR/repeat.R
例子:
# 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月更新:
现在,您可以指定将占用多少行文本输出(即,将粘贴到堆栈溢出中的内容)。为此,请使用lines.out=n参数。例子:
复制(DF,列=c(1:3,17,23),行.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==
指南:
你提出问题的主要目的应该是让读者尽可能容易地理解并在他们的系统上重现你的问题。为此:
提供输入数据提供预期输出简洁地解释您的问题如果您有超过20行的文本+代码,您可能可以回去简化尽可能简化代码,同时保留问题/错误
这确实需要一些工作,但这似乎是一种公平的权衡,因为你要求别人为你做工作。
提供数据:
内置数据集
到目前为止,最好的选择是依赖内置数据集。这使得其他人很容易解决您的问题。在R提示符下键入data()以查看您可以使用的数据。一些经典的例子:
虹膜地铁车厢ggplot2::钻石(外包装,但几乎每个人都有)
检查内置数据集以找到适合您问题的数据集。
如果你能用内置的数据集重新表述你的问题,你就更有可能得到好的答案(和支持)。
自行生成的数据
如果您的问题是特定于现有数据集中未表示的数据类型,请提供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
最后,您可以使用dput将数据对象转换为R代码(例如dput(myData))。我说这是“最后的手段”,因为dput的输出通常相当笨拙,复制粘贴很烦人,并掩盖了您的其余问题。
提供预期输出:
有人曾经说过:
一张预期产出的图片值1000字--智者
如果您可以添加类似“我希望得到这个结果”的内容:
cyl mean.hp
1: 6 122.28571
2: 4 82.63636
3: 8 209.21429
对于你的问题,人们更容易理解你想快速做什么。如果您的预期结果很大且难以处理,那么您可能还没有充分考虑如何简化您的问题(见下一页)。
简洁地解释您的问题
主要要做的是在提问之前尽可能简化问题。在这方面,重新构建问题框架以使用内置数据集将有很大帮助。你也会经常发现,仅仅通过简化的过程,你就能回答自己的问题。
以下是一些好问题的示例:
内置数据集使用用户生成的数据
在这两种情况下,用户的问题几乎肯定与他们提供的简单示例无关。相反,他们抽象了问题的本质,并将其应用于一个简单的数据集,以提出问题。
为什么这个问题还有另一个答案?
这个答案侧重于我认为的最佳实践:使用内置数据集,并以最小的形式提供您期望的结果。最突出的答案侧重于其他方面。我不指望这个答案会上升到任何突出的位置;这只是为了让我可以在新手问题的评论中链接到它。
这是一个很好的指南。
最重要的一点是:制作一小段代码,我们可以运行它来了解问题所在。一个有用的函数是dput(),但是如果您有非常大的数据,那么您可能需要制作一个小样本数据集,或者只使用前10行左右。
编辑:
此外,确保您确定了问题所在。示例不应该是一个完整的R脚本,其中包含“在第200行出现错误”。如果您使用R(我爱浏览器())和Google中的调试工具,那么您应该能够真正确定问题所在,并重现一个同样错误的小例子。