可重复性最小的示例包含以下项目:
- 重现错误所必需的最小数据集
- 最小的 可运行 重现错误所需的代码,可以在给定的数据集上运行。
- 有关所使用的软件包,R版本及其运行的系统的必要信息。
- 在随机过程的情况下,种子(由...设置)
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()
,例如:
matrix(1:10, ncol = 2)
制作数据帧可以使用 data.frame()
。应注意在数据框中命名条目,并且不要使其过于复杂。
一个例子 :
set.seed(1)
Data <- data.frame(
X = sample(1:10),
Y = sample(c("yes", "no"), 10, replace = TRUE)
)
对于某些问题,可能需要特定格式。对于这些,可以使用任何提供的 as.someType
功能 : as.factor
, as.Date
, as.xts
,...这些与矢量和/或数据框架技巧相结合。
复制您的数据
如果你有一些使用这些技巧难以构建的数据,那么你总是可以使用例如原始数据的子集。 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")
如果您的数据框具有多个级别的因子,则 dput
输出可能很难处理,因为它仍会列出所有可能的因子级别,即使它们不存在于数据子集中。要解决此问题,您可以使用 droplevels()
功能。请注意以下物种是如何只有一个水平的因素:
> dput(droplevels(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 = "setosa",
class = "factor")), .Names = c("Sepal.Length", "Sepal.Width",
"Petal.Length", "Petal.Width", "Species"), row.names = c(NA,
4L), class = "data.frame")
另一个警告 dput
是它不适用于键控 data.table
对象或分组 tbl_df
(类 grouped_df
)来自 dplyr
。在这些情况下,您可以在共享之前转换回常规数据框, dput(as.data.frame(my_data))
。
在最坏的情况下,您可以提供可以使用的文本表示 text
的参数 read.table
:
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)
生成最少的代码
这应该是容易的部分,但往往不是。你不应该做的是:
- 添加所有类型的数据转换。确保提供的数据格式正确(除非这是问题)
- 复制粘贴一个产生错误的整个函数/代码块。首先,尝试找出确切导致错误的行。通常情况下,你会发现自己的问题是什么。
你应该做的是:
- 添加使用任何包时应使用哪些包(使用
library()
)
- 如果您打开连接或创建文件,添加一些代码来关闭它们或删除文件(使用
unlink()
)
- 如果更改选项,请确保代码包含一个语句,以将其还原为原始语句。 (例如
op <- par(mfrow=c(1,2)) ...some code... par(op)
)
- 测试在新的空R会话中运行您的代码,以确保代码是可运行的。人们应该能够在控制台中复制粘贴您的数据和代码,并获得与您完全相同的信息。
提供额外信息
在大多数情况下,仅R版本和操作系统就足够了。当包与包含冲突时,给出输出 sessionInfo()
可以真的帮助。在谈论与其他应用程序的连接时(无论是通过ODBC还是其他任何应用程序),还应该为这些应用程序提供版本号,如果可能,还应提供有关设置的必要信息。
如果你正在运行R in R Studio 运用 rstudioapi::versionInfo()
可以帮助您报告您的RStudio版本。
如果您对特定包有问题,可能需要通过提供输出来提供包的版本 packageVersion("name of the package")
。
就个人而言,我更喜欢“一个”衬里。一些事情:
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")
受到这篇文章的启发,我现在使用了一个方便的功能
reproduce(<mydata>)
当我需要发布到StackOverflow。
快速说明
如果 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==
另请注意,输出的整体是一条漂亮的单行,长行,而不是一段很高的切割线。
这样可以更容易阅读SO问题帖子,也更容易复制+粘贴。
2013年10月更新:
您现在可以指定将占用多少行文本输出(即,您将粘贴到StackOverflow中的内容)。使用 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==
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行,有3列命名
'row','col'和'value',它们都有
维度名称为'row'和'col'的值,如下所示:
> 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")
)
这个单词 小 特别重要。你应该瞄准一个 最小 可重现的例子,这意味着数据和代码应尽可能简单地解释问题。
编辑:漂亮的代码比丑陋的代码更容易阅读。用一个 时尚指南。