问题:如何制作出色的R可重现示例

与同事讨论绩效,教学,发送错误报告或在邮件列表上以及在Stack Overflow上搜索指南时,这是一个可复制的示例< / a>经常被问到并且总是有帮助的。

创建出色示例的秘诀是什么?如何从文本中的中粘贴数据结构格式?您还应该包括哪些其他信息?

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

一个人如何使一个很好的的问题例子吗?

标签:r,r-faq

Q: How to make a great R reproducible example

When discussing performance with colleagues, teaching, sending a bug report or searching for guidance on mailing lists and here on StackOverflow, a reproducible example is often asked and always helpful.

What are your tips for creating an excellent example? How do you paste data structures from in a text format? What other information should you include?

Are there other tricks in addition to using dput(), dump() or structure()? When should you include library() or require() statements? Which reserved words should one avoid, in addition to c, df, data, etc.?

How does one make a great reproducible example?

回答1:

最小可复制示例 由以下各项组成:

  • 证明问题最基本的数据集
  • 再现错误所需的最少可运行代码,可以在给定的数据集上运行
  • 有关所用软件包,R版本和运行它的系统的必要信息。
  • 在随机过程的情况下,为可再现性提供种子(由set.seed()设置) 1

有关良好的最小可复制示例的示例,请参见所使用功能的帮助文件。通常,此处给出的所有代码都满足最小可重现示例的要求:提供数据,提供最少的代码并且一切都可运行。还要查看有关堆栈溢出问题的很多支持。

产生最小的数据集

在大多数情况下,只需提供带有某些值的向量/数据帧即可轻松完成此操作。或者,您可以使用大多数软件包随附的内置数据集之一。
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.factoras.Dateas.xts,...这些与矢量和/或数据帧的技巧结合在一起。

复制您的数据

如果您使用这些技巧难以构建某些数据,则始终可以使用head()subset() 或索引。然后使用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")), .Names = c("Sepal.Length", 
"Sepal.Width", "Petal.Length", "Petal.Width", "Species"), row.names = c(NA, 
4L), class = "data.frame")

如果您的数据框具有多个级别的因数,则dput输出可能会很笨拙,因为它仍会列出所有可能的因素级别,即使它们不在您的子集中也是如此数据。要解决此问题,可以使用droplevels()函数。请注意下面的内容,物种是如何只有一个水平的因子:

> dput(droplevels(iris[1: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时,您可能还希望仅包含相关列:

> dput(mtcars[1:3, c(2, 5, 6)]) # first three rows of columns 2, 5, and 6
structure(list(cyl = c(6, 6, 4), drat = c(3.9, 3.9, 3.85), wt = c(2.62, 
2.875, 2.32)), row.names = c("Mazda RX4", "Mazda RX4 Wag", "Datsun 710"
), class = "data.frame")

dput的另一个警告是,它不适用于键控data.table对象或分组的tbl_df(类dplyr中的grouped_df )。在这种情况下,您可以在共享dput(as.data.frame(my_data))之前转换回常规数据帧。

最坏的情况下,您可以使用read.tabletext参数提供可以读取的文本表示形式:

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))...某些代码...par(op))
  • 在一个新的空R会话中测试您的代码,以确保代码可运行。人们应该能够只在控制台中复制粘贴您的数据和代码,并获得与您完全相同的信息。

提供更多信息

在大多数情况下,仅R版本和操作系统就足够了。当软件包出现冲突时,提供sessionInfo()的输出确实可以提供帮助。在谈论与其他应用程序的连接(通过ODBC或其他方式)时,还应提供这些应用程序的版本号,并在可能的情况下还提供有关安装程序的必要信息。

如果您正在使用rstudioapi::versionInfo() R Studio 中运行R,则有助于报告RStudio版本。

如果您对特定软件包有疑问,则可能需要通过提供packageVersion("软件包名称")的输出来提供软件包的版本。


1 注意set.seed()的输出在R> 3.6.0和早期版本之间有所不同。请务必指定用于随机过程的R版本,如果在遵循旧问题时得到的结果略有不同,请不要感到惊讶。为了在这种情况下获得相同的结果,可以在set.seed()之前使用RNGversion()-函数(例如:RNGversion("3.5.2"))。

A1:

A minimal reproducible example consists of the following items:

  • a minimal dataset, necessary to demonstrate the problem
  • the minimal runnable code necessary to reproduce the error, which can be run on the given dataset
  • the necessary information on the used packages, R version, and system it is run on.
  • in the case of random processes, a seed (set by set.seed()) for reproducibility1

For examples of good minimal reproducible examples, see the help files of the function you are using. In general, all the code given there fulfills the requirements of a minimal reproducible example: data is provided, minimal code is provided, and everything is runnable. Also look at questions on Stack Overflow with lots of upvotes.

Producing a minimal dataset

For most cases, this can be easily done by just providing a vector/data frame with some values. Or you can use one of the built-in datasets, which are provided with most packages.
A comprehensive list of built-in datasets can be seen with library(help = "datasets"). There is a short description to every dataset and more information can be obtained for example with ?mtcars where 'mtcars' is one of the datasets in the list. Other packages might contain additional datasets.

Making a vector is easy. Sometimes it is necessary to add some randomness to it, and there are a whole number of functions to make that. sample() can randomize a vector, or give a random vector with only a few values. letters is a useful vector containing the alphabet. This can be used for making factors.

A few examples :

  • random values : x <- rnorm(10) for normal distribution, x <- runif(10) for uniform distribution, ...
  • a permutation of some values : x <- sample(1:10) for vector 1:10 in random order.
  • a random factor : x <- sample(letters[1:4], 20, replace = TRUE)

For matrices, one can use matrix(), eg :

matrix(1:10, ncol = 2)

Making data frames can be done using data.frame(). One should pay attention to name the entries in the data frame, and to not make it overly complicated.

An example :

set.seed(1)
Data <- data.frame(
    X = sample(1:10),
    Y = sample(c("yes", "no"), 10, replace = TRUE)
)

For some questions, specific formats can be needed. For these, one can use any of the provided as.someType functions : as.factor, as.Date, as.xts, ... These in combination with the vector and/or data frame tricks.

Copy your data

If you have some data that would be too difficult to construct using these tips, then you can always make a subset of your original data, using head(), subset() or the indices. Then use dput() to give us something that can be put in R immediately :

> 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")), .Names = c("Sepal.Length", 
"Sepal.Width", "Petal.Length", "Petal.Width", "Species"), row.names = c(NA, 
4L), class = "data.frame")

If your data frame has a factor with many levels, the dput output can be unwieldy because it will still list all the possible factor levels even if they aren't present in the the subset of your data. To solve this issue, you can use the droplevels() function. Notice below how species is a factor with only one level:

> dput(droplevels(iris[1: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")

When using dput, you may also want to include only relevant columns:

> dput(mtcars[1:3, c(2, 5, 6)]) # first three rows of columns 2, 5, and 6
structure(list(cyl = c(6, 6, 4), drat = c(3.9, 3.9, 3.85), wt = c(2.62, 
2.875, 2.32)), row.names = c("Mazda RX4", "Mazda RX4 Wag", "Datsun 710"
), class = "data.frame")

One other caveat for dput is that it will not work for keyed data.table objects or for grouped tbl_df (class grouped_df) from dplyr. In these cases you can convert back to a regular data frame before sharing, dput(as.data.frame(my_data)).

Worst case scenario, you can give a text representation that can be read in using the text parameter of 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)

Producing minimal code

This should be the easy part but often isn't. What you should not do, is:

  • add all kind of data conversions. Make sure the provided data is already in the correct format (unless that is the problem of course)
  • copy-paste a whole function/chunk of code that gives an error. First, try to locate which lines exactly result in the error. More often than not you'll find out what the problem is yourself.

What you should do, is:

  • add which packages should be used if you use any (using library())
  • if you open connections or create files, add some code to close them or delete the files (using unlink())
  • if you change options, make sure the code contains a statement to revert them back to the original ones. (eg op <- par(mfrow=c(1,2)) ...some code... par(op) )
  • test run your code in a new, empty R session to make sure the code is runnable. People should be able to just copy-paste your data and your code in the console and get exactly the same as you have.

Give extra information

In most cases, just the R version and the operating system will suffice. When conflicts arise with packages, giving the output of sessionInfo() can really help. When talking about connections to other applications (be it through ODBC or anything else), one should also provide version numbers for those, and if possible also the necessary information on the setup.

If you are running R in R Studio using rstudioapi::versionInfo() can be helpful to report your RStudio version.

If you have a problem with a specific package you may want to provide the version of the package by giving the output of packageVersion("name of the package").


1 Note: The output of set.seed() differs between R >3.6.0 and previous versions. Do specify which R version you used for the random process, and don't be surprised if you get slightly different results when following old questions. To get the same result in such cases, you can use the RNGversion()-function before set.seed() (e.g.: RNGversion("3.5.2")).

回答2:

(这是如何编写可复制示例的建议。尝试使它简短但甜美)

如何编写可复制的示例。

如果您提供可复制的示例,则很可能会在R问题上获得良好的帮助。一个可复制的示例允许其他人仅通过复制和粘贴R代码来重新创建您的问题。

要使示例可重现,需要包括四件事:必需的程序包,数据,代码和对R环境的描述。

  • 软件包应该加载到脚本的顶部,这样很容易看到示例需要的软件包。

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

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

    • 确保您使用了空格,并且变量名简洁明了,但内容丰富

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

    • 尽力删除与问题无关的所有内容。
      您的代码越短,则越容易理解。

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

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

在将所有代码放入电子邮件之前,请考虑将其放在要点github 上。它将为您的代码提供醒目的语法突出显示,并且您不必担心电子邮件系统会干扰任何事情。

A2:

(Here's my advice from How to write a reproducible example . I've tried to make it short but sweet)

How to write a reproducible example.

You are most likely to get good help with your R problem if you provide a reproducible example. A reproducible example allows someone else to recreate your problem by just copying and pasting R code.

There are four things you need to include to make your example reproducible: required packages, data, code, and a description of your R environment.

  • Packages should be loaded at the top of the script, so it's easy to see which ones the example needs.

  • The easiest way to include data in an email or Stack Overflow question is to use dput() to generate the R code to recreate it. For example, to recreate the mtcars dataset in R, I'd perform the following steps:

    1. Run dput(mtcars) in R
    2. Copy the output
    3. In my reproducible script, type mtcars <- then paste.
  • Spend a little bit of time ensuring that your code is easy for others to read:

    • make sure you've used spaces and your variable names are concise, but informative

    • use comments to indicate where your problem lies

    • do your best to remove everything that is not related to the problem.
      The shorter your code is, the easier it is to understand.

  • Include the output of sessionInfo() in a comment in your code. This summarises your R environment and makes it easy to check if you're using an out-of-date package.

You can check you have actually made a reproducible example by starting up a fresh R session and pasting your script in.

Before putting all of your code in an email, consider putting it on Gist github . It will give your code nice syntax highlighting, and you don't have to worry about anything getting mangled by the email system.

回答3:

就个人而言,我更喜欢"一个"衬垫。大致情况:

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实现的某些空间对象,则可以通过" spatial"包中的外部文件(例如ESRI shapefile)获得一些数据集(请参阅Task中的Spatial视图)。观看次数)。

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

A3:

Personally, I prefer "one" liners. Something along the lines:

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)

The data structure should mimic the idea of writer's problem and not the exact verbatim structure. I really appreciate it when variables don't overwrite my own variables or god forbid, functions (like df).

Alternatively, one could cut a few corners and point to a pre-existing data set, something like:

library(vegan)
data(varespec)
ord <- metaMDS(varespec)

Don't forget to mention any special packages you might be using.

If you're trying to demonstrate something on larger objects, you can try

my.df2 <- data.frame(a = sample(10e6), b = sample(letters, 10e6, replace = TRUE))

If you're working with spatial data via the raster package, you can generate some random data. A lot of examples can be found in the package vignette, but here's a small nugget.

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)

If you're in need of some spatial object as implemented in sp, you can get some datasets via external files (like ESRI shapefile) in "spatial" packages (see the Spatial view in Task Views).

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

回答4:

受此文章的启发,当我需要发布到StackOverflow时,我现在使用了方便的函数
reproduce( )


快速说明

如果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 x102。我想对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==

A4:

Inspired by this very post, I now use a handy function
reproduce(<mydata>) when I need to post to StackOverflow.


QUICK INSTRUCTIONS

If myData is the name of your object to reproduce, run the following in R:

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

reproduce(myData)

Details:

This function is an intelligent wrapper to dput and does the following:

  • automatically samples a large data set (based on size and class. Sample size can be adjusted)
  • creates a dput output
  • allows you to specify which columns to export
  • appends to the front of it objName <- ... so that it can be easily copy+pasted, but...
  • If working on a mac, the output is automagically copied to the clipboard, so that you can simply run it and then paste to your question.

The source is available here:


Example:

# 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 is about 100 x 102. I want to sample 10 rows, and a few specific columns

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

Gives the following output:

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==

Notice also that the entirety of the output is in a nice single, long line, not a tall paragraph of chopped up lines. This makes it easier to read on SO questions posts and also easier to copy+paste.


Update Oct 2013:

You can now specify how many lines of text output will take up (ie, what you will paste into StackOverflow). Use the lines.out=n argument for this. Example:

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

    ==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==

回答5:

这是一个很好的指南

最重要的一点是:只需确保您编写一小段代码即可运行以查看问题所在。一个有用的功能是dput(),但是如果您有非常大的数据,则可能要制作一个小的样本数据集或仅使用前10行左右。

编辑:

还要确保您确定问题出在哪里。该示例不应是带有"在线200出现错误"的整个R脚本。如果您使用R(我喜欢browser())和Google中的调试工具,则您应该能够真正确定问题出在哪里,并重现一个简单的例子,说明同样的事情出了问题。

A5:

Here is a good guide.

The most important point is: Just make sure that you make a small piece of code that we can run to see what the problem is. A useful function for this is dput(), but if you have very large data, you might want to make a small sample dataset or only use the first 10 lines or so.

EDIT:

Also make sure that you identified where the problem is yourself. The example should not be an entire R script with "On line 200 there is an error". If you use the debugging tools in R (I love browser()) and Google you should be able to really identify where the problem is and reproduce a trivial example in which the same thing goes wrong.

回答6:

R帮助邮件列表中有一个发布指南,其中涵盖了和回答问题,包括生成数据的示例:

示例:有时它有助于提供一个可以实际运行的小示例。例如:

如果我的矩阵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行,名为" 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")

)

一词特别重要。您应该以一个最小可重现的示例为目标,这意味着数据和代码应尽可能简单以解释问题。

编辑:漂亮的代码比丑陋的代码更易于阅读。使用样式指南

A6:

The R-help mailing list has a posting guide which covers both asking and answering questions, including an example of generating data:

Examples: Sometimes it helps to provide a small example that someone can actually run. For example:

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

)

The word small is especially important. You should be aiming for a minimal reproducible example, which means that the data and the code should be as simple as possible to explain the problem.

EDIT: Pretty code is easier to read than ugly code. Use a style guide.

回答7:

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

A7:

Since R.2.14 (I guess) you can feed your data text representation directly to 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
") 

回答8:

有时即使使用较小的数据也无法重现该问题,无论您如何努力,也不会在合成数据中发生(尽管这对于显示如何生成确实做到了的合成数据集很有用不重现该问题,因为它排除了一些假设)。

  • 可能需要将数据发布到Web上的某个地方并提供URL。
  • 如果无法将数据公开发布,但可以共享,那么您可以通过电子邮件将其发送给感兴趣的各方(尽管这样做可以减少愿意麻烦去做)。
  • 我实际上还没有看到这样做,因为无法发布数据的人对以任何形式发布数据都很敏感,但是在某些情况下,如果数据被充分匿名/加扰,仍然可以发布数据似乎是合理的。 /以某种方式轻微损坏。

如果您不能做任何一个,那么您可能需要聘请顾问来解决您的问题...

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

A8:

Sometimes the problem really isn't reproducible with a smaller piece of data, no matter how hard you try, and doesn't happen with synthetic data (although it's useful to show how you produced synthetic data sets that did not reproduce the problem, because it rules out some hypotheses).

  • Posting the data to the web somewhere and providing a URL may be necessary.
  • If the data can't be released to the public at large but could be shared at all, then you may be able to offer to e-mail it to interested parties (although this will cut down the number of people who will bother to work on it).
  • I haven't actually seen this done, because people who can't release their data are sensitive about releasing it any form, but it would seem plausible that in some cases one could still post data if it were sufficiently anonymized/scrambled/corrupted slightly in some way.

If you can't do either of these then you probably need to hire a consultant to solve your problem ...

edit: Two useful SO questions for anonymization/scrambling:

回答9:

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

以下是可避免发生的事情的可复制示例(从真实示例中得出,为了保护无辜者而更改了名称):


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

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

我该如何实现?


A9:

The answers so far are obviously great for the reproducibility part. This is merely to clarify that a reproducible example cannot and should not be the sole component of a question. Don't forget to explain what you want it to look like and the contours of your problem, not just how you have attempted to get there so far. Code is not enough; you need words also.

Here's a reproducible example of what to avoid doing (drawn from a real example, names changed to protect the innocent):


The following is sample data and part of function I have trouble with.

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

How can I achieve this ?


回答10:

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

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

>fix(mydata)

执行'fix'命令时,您将获得此弹出框

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

A10:

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)

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

回答11:

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

对于Excel中的数据:

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

对于txt文件中的数据:

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

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

A11:

To quickly create a dput of your data you can just copy (a piece of) the data to your clipboard and run the following in R:

for data in Excel:

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

for data in a txt file:

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

You can change the sep in the latter if necessary. This will only work if your data is in the clipboard of course.

回答12:

指南:


制作问题的主要目的应该是使读者尽可能容易地在其系统上理解和再现您的问题。为此:

  1. 提供输入数据
  2. 提供预期输出
  3. 简要说明您的问题
    • 如果您有超过20行的文字和代码,您可能可以回过头来简化
    • 在保留问题/错误的同时尽可能简化代码

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

提供数据:


内置数据集

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

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

请参阅此 SO质量检查 ,了解如何查找适合您问题的数据集。

如果您能够改写问题以使用内置数据集,则更有可能获得良好的答案(并赞成)。

自行生成的数据

如果您的问题非常特定于现有数据集中未表示的一种数据类型,请提供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

对于您的问题,人们更有可能快速了解您正在尝试做的事情。如果您的预期结果很大且难以处理,那么您可能还没有对如何简化问题进行充分的考虑(请参阅下一个)。

简要说明您的问题


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

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

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

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


此答案侧重于我认为的最佳实践:使用内置数据集,并以最小的形式提供您期望的结果。最突出的答案集中在其他方面。我不希望这个答案能引起人们的关注。这仅仅是在这里,以便我可以在对新手问题的评论中链接到它。

A12:

Guidelines:


Your main objective in crafting your questions should be to make it as easy as possible for readers to understand and reproduce your problem on their systems. To do so:

  1. Provide input data
  2. Provide expected output
  3. Explain your problem succinctly
    • if you have over 20 lines of text + code you can probably go back and simplify
    • simplify your code as much as possible while preserving the problem/error

This does take some work but seems like a fair trade-off since you are asking others to do work for you.

Providing Data:


Built-in Data Sets

The best option by far is to rely on built-in datasets. This makes it very easy for others to work on your problem. Type data() at the R prompt to see what data is available to you. Some classic examples:

  • iris
  • mtcars
  • ggplot2::diamonds (external package, but almost everyone has it)

See this SO QA for how to find data sets suitable for your problem.

If you are able to rephrase your problem to use the built-in datasets you are much more likely to get good answers (and upvotes).

Self Generated Data

If your problem is very specific to a type of data that is not represented in the existing data sets, then provide the R code that generates the smallest possible dataset that your problem manifests itself on. For example

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

Now someone trying to answer my question can copy/paste those two lines and start working on the problem immediately.

dput

As a last resort, you can use dput to transform a data object to R code (e.g. dput(myData)). I say as a "last resort" because the output of dput is often fairly unwieldy, annoying to copy-paste, and obscures the rest of your question.

Provide Expected Output:


Someone once said:

A picture of expected output is worth 1000 words

-- a very wise person

If you can add something like "I expected to get this result":

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

to your question, people are much more likely to quickly understand what you are trying to do. If your expected result is large and unwieldy, then you probably haven't thought enough about how to simplify your problem (see next).

Explain Your Problem Succinctly


The main thing to do is to simplify your problem as much as possible before you ask your question. Re-framing the problem to work with the built-in datasets will help a lot in this regard. You will also often find that just by going through the process of simplification you will answer your own problem.

Here are some examples of good questions:

In both cases, the user's problems are almost certainly not with the simple examples they provide. Rather they abstracted the nature of their problem and applied it to a simple data set to ask their question.

Why Yet Another Answer To This Question?


This answer focuses on what I think is the best practice: use built-in data sets and provide what you expect as a result in a minimal form. The most prominent answers focus on other aspects. I don't expect this answer to rising to any prominence; this is here solely so that I can link to it in comments to newbie questions.

回答13:

可复制的代码是获得帮助的关键。但是,许多用户可能甚至对粘贴他们的大部分数据都持怀疑态度。例如,他们可能正在使用敏感数据或收集的原始数据以供研究论文使用。出于任何原因,我认为最好有一个方便的功能来在公开粘贴之前"变形"我的数据。软件包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)
)

> 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

A13:

Reproducible code is key to get help. However, there are many users that might be skeptical of pasting even a chunk of their data. For instance, they could be working with sensitive data or on an original data collected to use in a research paper. For any reason, I thought it would be nice to have a handy function for "deforming" my data before pasting it publicly. The anonymize function from the package SciencesPo is very silly, but for me it works nicely with dput function.

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

Then I anonymize it:

> 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

One may also want to sample few variables instead of the whole data before apply anonymization and dput command.

    # 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

回答14:

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

例如

data(mtcars)

然后解决问题

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

A14:

Often you need some data for an example, however, you don't want to post your exact data. To use some existing data.frame in established library, use data command to import it.

e.g.,

data(mtcars)

and then do the problem

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

回答15:

如果您有无法使用dput()轻松放入脚本的大型数据集,请将数据发布到 pastebin 并使用read.table

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

@Henrik 的启发。

A15:

If you have large dataset which cannot be easily put to the script using dput(), post your data to pastebin and load them using read.table:

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

Inspired by @Henrik.

回答16:

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

关于

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

安装:

当前(2015年6月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
.. ...   ... ...    ...      ... ...    ...   ...

A16:

I am developing the wakefield package to address this need to quickly share reproducible data, sometimes dput works fine for smaller data sets but many of the problems we deal with are much larger, sharing such a large data set via dput is impractical.

About:

wakefield allows the user to share minimal code to reproduce data. The user sets n (number of rows) and specifies any number of preset variable functions (there are currently 70) that mimic real if data (things like gender, age, income etc.)

Installation:

Currently (2015-06-11), wakefield is a GitHub package but will go to CRAN eventually after unit tests are written. To install quickly, use:

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

Example:

Here is an example:

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

This produces:

    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
.. ...   ... ...    ...      ... ...    ...   ...

回答17:

如果您的数据中有一个或多个要使用dput(head(my(data))可重现的factor变量,请考虑添加 droplevels ,以便使 minimum 的示例在dput输出中不包括最小化数据集中不存在的因子水平。 em>:

dput(droplevels(head(mydata)))

A17:

If you have one or more factor variable(s) in your data that you want to make reproducible with dput(head(mydata)), consider adding droplevels to it, so that levels of factors that are not present in the minimized data set are not included in your dput output, in order to make the example minimal:

dput(droplevels(head(mydata)))

回答18:

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

A18:

I wonder if an http://old.r-fiddle.org/ link could be a very neat way of sharing a problem. It receives a unique ID like and one could even think about embedding it in SO.

回答19:

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

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

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

A19:

Please do not paste your console outputs like this:

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

We can not copy-paste it directly.

To make questions and answers properly reproducible, try to remove + & > before posting it and put # for outputs and comments like this:

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

One more thing, if you have used any function from certain package, mention that library.

回答20:

您可以使用 reprex 来实现。

mt1022所述," ...产生最小限度,可复制示例的好方法是 tidyverse " reprex"

根据 Tidyverse

" reprex"的目标是打包您有问题的代码,以使其他人可以运行它并感到您的痛苦。

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

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

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

A20:

You can do this using reprex.

As mt1022 noted, "... good package for producing minimal, reproducible example is "reprex" from tidyverse".

According to Tidyverse:

The goal of "reprex" is to package your problematic code in such a way that other people can run it and feel your pain.

An example is given on tidyverse web site.

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

I think this is the simplest way to create a reproducible example.

回答21:

除了上述所有我认为非常有趣的答案外,有时在这里讨论它也很容易:-如何制作一个最小的可复制示例以使用R进行帮助

有许多方法可以生成随机向量使用R中的随机值四舍五入到2个小数位或R中的随机矩阵

创建一个100号向量
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))

A21:

Apart of all above answers which I found very interesting, it could sometimes be very easy as it is discussed here :- HOW TO MAKE A MINIMAL REPRODUCIBLE EXAMPLE TO GET HELP WITH R

There are many ways to make a random vector Create a 100 number vector with random values in R rounded to 2 decimals or random matrix in R

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

Note that sometimes it is very difficult to share a given data because of various reasons such as dimension etc. However, all above answers are great and very important to think and use when one wants to make a reproducible data example. But note that in order to make a data as representative as the original (in case the OP cannot share the original data), it is good to add some information with the data example as (if we call the data mydf1)

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

Moreover, one should know the type, length and attributes of a data which can be Data structures

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

回答22:

以下是我的一些建议:

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

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

所有这些都是可复制示例的一部分。

A22:

Here are some of my suggestions:

  • Try to use default R datasets
  • If you have your own dataset, include them with dput, so others can help you more easily
  • Do not use install.package() unless it is really necessary, people will understand if you just use require or library
  • Try to be concise,

    • Have some dataset
    • Try to describe the output you need as simply as possible
    • Do it yourself before you ask the question
  • It is easy to upload an image, so upload plots if you have
  • Also include any errors you may have

All these are part of a reproducible example.

回答23:

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

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

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

A23:

It's a good idea to use functions from the testthat package to show what you expect to occur. Thus, other people can alter your code until it runs without error. This eases the burden of those who would like to help you, because it means they don't have to decode your textual description. For example

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

is clearer than "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". Even in this silly example, I think the code is clearer than the words. Using testthat lets your helper focus on the code, which saves time, and it provides a way for them to know they have solved your problem, before they post it

回到顶部