Cómo hacer un gran ejemplo reproducible de R

May 11 2011

Cuando se habla de rendimiento con colegas, se enseña, se envía un informe de error o se busca orientación en listas de correo y aquí en Stack Overflow, a menudo se pide un ejemplo reproducible y siempre es útil.

¿Cuáles son sus consejos para crear un ejemplo excelente? ¿Cómo se pegan las estructuras de datos de r en formato de texto? ¿Qué otra información debería incluir?

¿Hay otros trucos además de usar dput(), dump()o structure()? ¿Cuándo debe incluir declaraciones library()o require()? ¿Qué palabras reservadas debe uno evitar, además c, df, data, etc.?

¿Cómo hacer un gran r ejemplo reproducible?

Respuestas

1756 JorisMeys May 11 2011 at 18:40

Un ejemplo mínimo reproducible consta de los siguientes elementos:

  • un conjunto de datos mínimo, necesario para demostrar el problema
  • el código ejecutable mínimo necesario para reproducir el error, que se puede ejecutar en el conjunto de datos dado
  • la información necesaria sobre los paquetes utilizados, la versión R y el sistema en el que se ejecuta.
  • en el caso de procesos aleatorios, una semilla (establecida por set.seed()) para la reproducibilidad 1

Para obtener ejemplos de buenos ejemplos mínimos reproducibles , consulte los archivos de ayuda de la función que está utilizando. En general, todo el código que se proporciona allí cumple los requisitos de un ejemplo mínimo reproducible: se proporcionan datos, se proporciona un código mínimo y todo es ejecutable. También mire las preguntas en Stack Overflow con muchos votos a favor.

Producir un conjunto de datos mínimo

En la mayoría de los casos, esto se puede hacer fácilmente simplemente proporcionando un vector / marco de datos con algunos valores. O puede utilizar uno de los conjuntos de datos integrados, que se proporcionan con la mayoría de los paquetes.
Se puede ver una lista completa de conjuntos de datos integrados library(help = "datasets"). Hay una breve descripción de cada conjunto de datos y se puede obtener más información, por ejemplo, ?mtcarsdonde 'mtcars' es uno de los conjuntos de datos en la lista. Otros paquetes pueden contener conjuntos de datos adicionales.

Hacer un vector es fácil. A veces es necesario agregarle algo de aleatoriedad, y hay una gran cantidad de funciones para hacer eso. sample()puede aleatorizar un vector o dar un vector aleatorio con solo unos pocos valores. letterses un vector útil que contiene el alfabeto. Esto se puede usar para hacer factores.

Algunos ejemplos :

  • valores aleatorios: x <- rnorm(10)para distribución normal, x <- runif(10)para distribución uniforme, ...
  • una permutación de algunos valores: x <- sample(1:10)para el vector 1:10 en orden aleatorio.
  • un factor aleatorio: x <- sample(letters[1:4], 20, replace = TRUE)

Para matrices, se puede utilizar matrix(), por ejemplo:

matrix(1:10, ncol = 2)

La creación de marcos de datos se puede hacer usando data.frame(). Se debe prestar atención a nombrar las entradas en el marco de datos y no hacerlo demasiado complicado.

Un ejemplo :

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

Para algunas preguntas, se pueden necesitar formatos específicos. Para estos, uno puede utilizar cualquiera de los previstos as.someTypefunciones: as.factor, as.Date, as.xts, ... Estos en combinación con los trucos de vectores y / o trama de datos.

Copie sus datos

Si usted tiene algunos datos que serían demasiado difíciles de construir uso de estos consejos, entonces siempre se puede hacer un subconjunto de los datos originales, utilizando head(), subset()o los índices. Luego use dput()para darnos algo que se pueda poner en R inmediatamente:

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

Si su marco de datos tiene un factor con muchos niveles, la dputsalida puede ser difícil de manejar porque aún enumerará todos los niveles de factor posibles incluso si no están presentes en el subconjunto de sus datos. Para resolver este problema, puede utilizar la droplevels()función. Observe a continuación cómo la especie es un factor con un solo nivel:

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

Al usar dput, es posible que también desee incluir solo columnas relevantes:

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

Otra advertencia dputes que no funcionará para data.tableobjetos con clave o agrupados tbl_df(clase grouped_df) desde dplyr. En estos casos se puede convertir de nuevo a una trama de datos regular antes de compartir dput(as.data.frame(my_data)).

En el peor de los casos, puede dar una representación de texto que se pueda leer usando el textparámetro de 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)

Produciendo código mínimo

Esta debería ser la parte fácil, pero a menudo no lo es. Lo que no debes hacer es:

  • agregue todo tipo de conversiones de datos. Asegúrese de que los datos proporcionados ya estén en el formato correcto (a menos que ese sea el problema, por supuesto)
  • copiar y pegar una función / fragmento de código completo que da un error. Primero, intente localizar qué líneas dan exactamente como resultado el error. La mayoría de las veces, usted mismo descubrirá cuál es el problema.

Lo que debes hacer es:

  • agregue qué paquetes deben usarse si usa alguno (usando library())
  • si abre conexiones o crea archivos, agregue algún código para cerrarlos o eliminar los archivos (usando unlink())
  • si cambia las opciones, asegúrese de que el código contenga una declaración para revertirlas a las originales. (por ejemplo op <- par(mfrow=c(1,2)) ...some code... par(op))
  • pruebe, ejecute su código en una nueva sesión de R vacía para asegurarse de que el código sea ejecutable. La gente debería poder simplemente copiar y pegar sus datos y su código en la consola y obtener exactamente lo mismo que usted.

Dar información extra

En la mayoría de los casos, bastará con la versión R y el sistema operativo. Cuando surgen conflictos con los paquetes, dar el resultado de sessionInfo()puede ser de gran ayuda. Cuando se habla de conexiones a otras aplicaciones (ya sea a través de ODBC o cualquier otra cosa), también se deben proporcionar los números de versión de esas y, si es posible, también la información necesaria sobre la configuración.

Si está ejecutando R en R Studio usando rstudioapi::versionInfo()puede ser útil para reportar su versión rstudio.

Si tiene un problema con un paquete específico, es posible que desee proporcionar la versión del paquete dando el resultado de packageVersion("name of the package").


1 Nota: La salida de set.seed()difiere entre R> 3.6.0 y versiones anteriores. Especifique qué versión de R usó para el proceso aleatorio y no se sorprenda si obtiene resultados ligeramente diferentes al seguir preguntas anteriores. Para obtener el mismo resultado en tales casos, puede usar la RNGversion()función-antes set.seed()(por ejemplo :) RNGversion("3.5.2").

595 hadley May 11 2011 at 20:57

(Aquí está mi consejo de Cómo escribir un ejemplo reproducible . He intentado que sea breve pero agradable)

Cómo escribir un ejemplo reproducible.

Es más probable que obtenga una buena ayuda con su problema de R si proporciona un ejemplo reproducible. Un ejemplo reproducible le permite a otra persona recrear su problema simplemente copiando y pegando código R.

Hay cuatro cosas que debe incluir para que su ejemplo sea reproducible: paquetes requeridos, datos, código y una descripción de su entorno R.

  • Los paquetes deben cargarse en la parte superior del script, por lo que es fácil ver cuáles necesita el ejemplo.

  • La forma más fácil de incluir datos en un correo electrónico o una pregunta de desbordamiento de pila es usar dput()para generar el código R para recrearlo. Por ejemplo, para recrear el mtcarsconjunto de datos en R, realizaría los siguientes pasos:

    1. Ejecutar dput(mtcars)en R
    2. Copiar la salida
    3. En mi secuencia de comandos reproducible, escriba y mtcars <-luego pegue.
  • Dedique un poco de tiempo a asegurarse de que su código sea ​​fácil de leer para otros:

    • asegúrese de haber utilizado espacios y que los nombres de las variables sean concisos, pero informativos

    • use comentarios para indicar dónde radica su problema

    • haga todo lo posible para eliminar todo lo que no esté relacionado con el problema.
      Cuanto más corto sea su código, más fácil será de entender.

  • Incluya la salida de sessionInfo()en un comentario en su código. Esto resume su entorno de R y facilita la verificación si está utilizando un paquete desactualizado.

Puede comprobar que ha creado un ejemplo reproducible iniciando una nueva sesión de R y pegando su script en formato.

Antes de poner todo su código en un correo electrónico, considere ponerlo en Gist github . Le dará a su código un buen resaltado de sintaxis, y no tiene que preocuparse de que el sistema de correo electrónico estropee nada.

307 RomanLuštrik May 11 2011 at 18:22

Personalmente, prefiero los revestimientos "uno". Algo parecido a esto:

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)

La estructura de datos debe imitar la idea del problema del escritor y no la estructura literal exacta. Realmente aprecio cuando las variables no sobrescriben mis propias variables o Dios no lo quiera, funciones (como df).

Alternativamente, uno podría cortar algunas esquinas y apuntar a un conjunto de datos preexistente, algo como:

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

No olvide mencionar los paquetes especiales que pueda estar utilizando.

Si está intentando demostrar algo en objetos más grandes, puede intentar

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

Si está trabajando con datos espaciales a través del rasterpaquete, puede generar algunos datos aleatorios. Se pueden encontrar muchos ejemplos en la viñeta del paquete, pero aquí hay una pequeña pepita.

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)

Si necesita algún objeto espacial implementado en sp, puede obtener algunos conjuntos de datos a través de archivos externos (como el shapefile ESRI) en paquetes "espaciales" (consulte la Vista espacial en Vistas de tareas).

library(rgdal)
ogrDrivers()
dsn <- system.file("vectors", package = "rgdal")[1]
ogrListLayers(dsn)
ogrInfo(dsn=dsn, layer="cities")
cities <- readOGR(dsn=dsn, layer="cities")
281 RicardoSaporta May 14 2013 at 05:20

Inspirado por esta misma publicación, ahora uso una función útil
reproduce(<mydata>)cuando necesito publicar en StackOverflow.


INSTRUCCIONES RÁPIDAS

Si myDataes el nombre de su objeto para reproducir, ejecute lo siguiente en R:

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

reproduce(myData)

Detalles:

Esta función es una envoltura inteligente dputy hace lo siguiente:

  • muestrea automáticamente un gran conjunto de datos (según el tamaño y la clase. El tamaño de la muestra se puede ajustar)
  • crea una dputsalida
  • le permite especificar qué columnas exportar
  • se agrega al frente objName <- ...para que se pueda copiar y pegar fácilmente, pero ...
  • Si trabaja en una Mac, la salida se copia automáticamente en el portapapeles, de modo que simplemente puede ejecutarla y luego pegarla en su pregunta.

La fuente está disponible aquí:

  • Github - pubR / reproduce.R

Ejemplo:

# 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 es de aproximadamente 100 x 102. Quiero muestrear 10 filas y algunas columnas específicas

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

Da el siguiente resultado:

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

Tenga en cuenta también que la totalidad de la salida está en una bonita línea única y larga, no en un párrafo alto de líneas cortadas. Esto hace que sea más fácil de leer en las publicaciones de preguntas SO y también más fácil de copiar y pegar.


Actualización de octubre de 2013:

Ahora puede especificar cuántas líneas de salida de texto ocupará (es decir, qué pegará en StackOverflow). Usa el lines.out=nargumento para esto. Ejemplo:

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

    ==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==
198 SachaEpskamp May 11 2011 at 18:21

He aquí una buena guía .

El punto más importante es: solo asegúrese de hacer un pequeño fragmento de código que podamos ejecutar para ver cuál es el problema . Una función útil para esto es dput(), pero si tiene datos muy grandes, es posible que desee crear un pequeño conjunto de datos de muestra o solo usar las primeras 10 líneas más o menos.

EDITAR:

También asegúrese de identificar usted mismo dónde está el problema. El ejemplo no debe ser un script R completo con "En la línea 200 hay un error". Si usa las herramientas de depuración en R (me encanta browser()) y Google, debería poder identificar realmente dónde está el problema y reproducir un ejemplo trivial en el que lo mismo sale mal.

167 RichieCotton May 11 2011 at 20:17

La lista de correo de R-help tiene una guía de publicación que cubre tanto la realización de preguntas como la respuesta, incluido un ejemplo de generación de datos:

Ejemplos: a veces es útil proporcionar un pequeño ejemplo de que alguien realmente puede ejecutar. Por ejemplo:

Si tengo una matriz x de la siguiente manera:

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

¿Cómo puedo convertirlo en un marco de datos con 8 filas y tres columnas llamadas 'fila', 'col' y 'valor', que tienen los nombres de dimensión como los valores de 'fila' y 'col', así:

  > x.df
     row col value
  1    A   x      1

...
(A lo que la respuesta podría ser:

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

)

La palabra pequeño es especialmente importante. Debe apuntar a un ejemplo mínimo reproducible, lo que significa que los datos y el código deben ser lo más simples posible para explicar el problema.

EDITAR: El código bonito es más fácil de leer que el código feo. Utilice una guía de estilo .

164 Paolo Jun 29 2012 at 15:32

Desde R.2.14 (supongo) puede alimentar su representación de texto de datos directamente a 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
") 
146 BenBolker Jul 15 2011 at 02:49

A veces, el problema realmente no se puede reproducir con un fragmento de datos más pequeño, sin importar cuánto lo intente, y no ocurre con datos sintéticos (aunque es útil mostrar cómo produjo conjuntos de datos sintéticos que no reprodujeron el problema, porque descarta algunas hipótesis).

  • Puede ser necesario publicar los datos en la web en algún lugar y proporcionar una URL.
  • Si los datos no se pueden divulgar al público en general, pero podrían compartirse, entonces puede ofrecer enviarlos por correo electrónico a las partes interesadas (aunque esto reducirá la cantidad de personas que se molestarán en trabajar en eso).
  • En realidad, no he visto esto hecho, porque las personas que no pueden divulgar sus datos son sensibles a la hora de publicarlos de cualquier forma, pero parecería plausible que en algunos casos uno podría publicar datos si estuvieran lo suficientemente anonimizados / codificados / corrompidos levemente. de alguna manera.

Si no puede hacer ninguno de estos, probablemente necesite contratar a un consultor para resolver su problema ...

editar : Dos preguntas SO útiles para anonimizar / codificar:

  • ¿Cómo crear un conjunto de datos de ejemplo a partir de datos privados (reemplazando los nombres y niveles de las variables con marcadores de posición no informativos)?
  • Dado un conjunto de números aleatorios extraídos de una distribución univariante continua, encuentre la distribución
136 AriB.Friedman Jul 09 2012 at 22:41

Las respuestas hasta ahora son obviamente excelentes para la parte de reproducibilidad. Esto es simplemente para aclarar que un ejemplo reproducible no puede ni debe ser el único componente de una pregunta. No olvide explicar cómo quiere que se vea y los contornos de su problema, no solo cómo ha intentado llegar hasta ahora. El código no es suficiente; también necesitas palabras.

Aquí hay un ejemplo reproducible de lo que se debe evitar hacer (extraído de un ejemplo real, los nombres cambiados para proteger a los inocentes):


Los siguientes son datos de muestra y parte de la función con la que tengo problemas.

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

Cómo puedo conseguir esto ?


124 jasmine_007 Feb 20 2014 at 16:11

Tengo una forma muy fácil y eficiente de hacer un ejemplo de R que no se ha mencionado anteriormente. Puede definir su estructura en primer lugar. Por ejemplo,

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

>fix(mydata)

Luego, puede ingresar sus datos manualmente. Esto es eficaz para ejemplos más pequeños que para grandes.

119 JT85 Apr 10 2013 at 21:51

Para crear rápidamente una parte dputde sus datos, simplemente puede copiar (una parte de) los datos en su portapapeles y ejecutar lo siguiente en R:

para datos en Excel:

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

para datos en un archivo txt:

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

Puede cambiar el sepen este último si es necesario. Esto solo funcionará si sus datos están en el portapapeles, por supuesto.

118 BrodieG Feb 12 2015 at 22:24

Pautas:


Su principal objetivo al elaborar sus preguntas debe ser facilitar que los lectores comprendan y reproduzcan su problema en sus sistemas. Para hacerlo:

  1. Proporcionar datos de entrada
  2. Proporcionar el resultado esperado
  3. Explica tu problema de manera sucinta
    • si tiene más de 20 líneas de texto + código, probablemente pueda volver atrás y simplificar
    • simplifique su código tanto como sea posible mientras preserva el problema / error

Esto requiere algo de trabajo, pero parece una compensación justa, ya que está pidiendo a otros que trabajen por usted.

Proporcionar datos:


Conjuntos de datos integrados

La mejor opción, con mucho, es confiar en conjuntos de datos integrados. Esto hace que sea muy fácil para otros trabajar en su problema. Escriba data()en el indicador R para ver qué datos están disponibles para usted. Algunos ejemplos clásicos:

  • iris
  • mtcars
  • ggplot2::diamonds (paquete externo, pero casi todo el mundo lo tiene)

Inspeccione los conjuntos de datos integrados para encontrar uno adecuado para su problema.

Si puede reformular su problema para utilizar los conjuntos de datos integrados, es mucho más probable que obtenga buenas respuestas (y votos a favor).

Datos autogenerados

Si su problema es muy específico de un tipo de datos que no está representado en los conjuntos de datos existentes, proporcione el código R que genera el conjunto de datos más pequeño posible en el que se manifiesta su problema. Por ejemplo

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

Ahora, alguien que intente responder mi pregunta puede copiar / pegar esas dos líneas y comenzar a trabajar en el problema de inmediato.

dput

Como último recurso , puede utilizar dputpara transformar un objeto de datos en código R (por ejemplo dput(myData)). Digo como "último recurso" porque la salida de a dputmenudo es bastante difícil de manejar, molesta de copiar y pegar y oscurece el resto de su pregunta.

Proporcione el resultado esperado:


Alguien dijo una vez:

Una imagen del resultado esperado vale 1000 palabras

- una persona muy sabia

Si puede agregar algo como "Esperaba obtener este resultado":

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

a su pregunta, es mucho más probable que las personas comprendan rápidamente lo que está tratando de hacer. Si el resultado esperado es grande y difícil de manejar, probablemente no haya pensado lo suficiente en cómo simplificar su problema (ver a continuación).

Explique su problema de manera sucinta


Lo principal que debe hacer es simplificar su problema tanto como sea posible antes de hacer su pregunta. Reencuadrar el problema para trabajar con los conjuntos de datos integrados ayudará mucho en este sentido. También encontrará a menudo que con solo pasar por el proceso de simplificación, resolverá su propio problema.

A continuación, se muestran algunos ejemplos de buenas preguntas:

  • con conjunto de datos incorporado
  • con datos generados por el usuario

En ambos casos, es casi seguro que los problemas del usuario no sean con los ejemplos simples que brindan. Más bien, abstrajeron la naturaleza de su problema y lo aplicaron a un conjunto de datos simple para hacer su pregunta.

¿Por qué otra respuesta a esta pregunta?


Esta respuesta se centra en lo que creo que es la mejor práctica: use conjuntos de datos integrados y proporcione lo que espera como resultado en una forma mínima. Las respuestas más destacadas se centran en otros aspectos. No espero que esta respuesta se destaque; esto está aquí únicamente para que pueda vincularlo en los comentarios a las preguntas de los novatos.

113 daniel Nov 27 2014 at 09:02

El código reproducible es clave para obtener ayuda. Sin embargo, hay muchos usuarios que podrían mostrarse escépticos a la hora de pegar incluso una parte de sus datos. Por ejemplo, podrían estar trabajando con datos confidenciales o en datos originales recopilados para usar en un trabajo de investigación. Por alguna razón, pensé que sería bueno tener una función útil para "deformar" mis datos antes de pegarlos públicamente. La anonymizefunción del paquete SciencesPoes muy tonta, pero para mí funciona bien con la dputfunción.

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

Luego lo anonimizo:

> 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

También es posible que desee muestrear algunas variables en lugar de todos los datos antes de aplicar la anonimización y el comando 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
102 userJT Feb 22 2013 at 22:29

A menudo, necesita algunos datos para un ejemplo, sin embargo, no desea publicar sus datos exactos. Para usar algún data.frame existente en la biblioteca establecida, use el comando de datos para importarlo.

p.ej,

data(mtcars)

y luego haz el problema

names(mtcars)
your problem demostrated on the mtcars data set
92 TMS Jan 04 2014 at 02:07

Si tiene un conjunto de datos grande que no se puede poner fácilmente en el script usando dput(), publique sus datos en pastebin y cárguelos usando read.table:

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

Inspirado por @Henrik .

90 TylerRinker Jun 11 2015 at 20:57

Estoy desarrollando el paquete de wakefield para abordar esta necesidad de compartir rápidamente datos reproducibles, a veces dputfunciona bien para conjuntos de datos más pequeños, pero muchos de los problemas con los que nos enfrentamos son mucho más grandes, compartir un conjunto de datos tan grande a través de no dputes práctico.

Sobre:

wakefield permite al usuario compartir código mínimo para reproducir datos. El usuario establecen(número de filas) y especifica cualquier número de funciones variables preestablecidas (actualmente hay 70) que imitan datos reales (cosas como género, edad, ingresos, etc.)

Instalación:

Actualmente (2015-06-11), wakefield es un paquete de GitHub, pero eventualmente irá a CRAN después de que se escriban las pruebas unitarias. Para instalar rápidamente, use:

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

Ejemplo:

Aquí hay un ejemplo:

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

Esto produce:

    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
.. ...   ... ...    ...      ... ...    ...   ...
73 docendodiscimus Jan 09 2015 at 22:09

Si tiene una o más factorvariables en sus datos con las que desea que sean reproducibles dput(head(mydata)), considere agregarlas droplevels, de modo que los niveles de factores que no están presentes en el conjunto de datos minimizados no se incluyan en su dputsalida, para hacer que el ejemplo sea mínimo :

dput(droplevels(head(mydata)))
66 CMichael Jan 09 2015 at 20:11

Me pregunto si un http://old.r-fiddle.org/El enlace podría ser una forma muy ordenada de compartir un problema. Recibe una identificación única como e incluso se podría pensar en incrustarla en SO.

49 user2100721 Jul 22 2016 at 17:01

No pegue las salidas de su consola de esta manera:

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

No podemos copiarlo y pegarlo directamente.

Para que las preguntas y respuestas sean reproducibles correctamente, intente eliminar +& >antes de publicarlo y coloque #resultados y comentarios como este:

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

Una cosa más, si ha usado alguna función de cierto paquete, mencione esa biblioteca.

34 andrii Aug 19 2017 at 02:02

Puedes hacer esto usando reprex .

Como señaló mt1022 , "... un buen paquete para producir un ejemplo mínimo y reproducible es " reprex " de tidyverse ".

Según Tidyverse :

El objetivo de "reprex" es empaquetar su código problemático de tal manera que otras personas puedan ejecutarlo y sentir su dolor.

Se ofrece un ejemplo en el sitio web de tidyverse .

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

Creo que esta es la forma más sencilla de crear un ejemplo reproducible.

33 5revs,2users84%user5947301 Apr 20 2016 at 17:50

Aparte de todas las respuestas anteriores que me parecieron muy interesantes, a veces podría ser muy fácil como se comenta aquí: - CÓMO HACER UN EJEMPLO DE REPRODUCIBLE MÍNIMO PARA OBTENER AYUDA CON R

Hay muchas formas de hacer un vector aleatorio Cree un vector numérico de 100 con valores aleatorios en R redondeados a 2 decimales o una matriz aleatoria en R

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

Tenga en cuenta que a veces es muy difícil compartir un dato dado debido a varias razones, como la dimensión, etc. Sin embargo, todas las respuestas anteriores son excelentes y muy importantes para pensar y usar cuando se quiere hacer un ejemplo de datos reproducible. Pero tenga en cuenta que para hacer un dato tan representativo como el original (en caso de que el OP no pueda compartir los datos originales), es bueno agregar alguna información con el ejemplo de datos como (si llamamos al dato mydf1)

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

Además, se debe conocer el tipo, la longitud y los atributos de un dato que pueden ser estructuras de datos.

#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))
28 TheRimalaya Apr 10 2016 at 01:15

Estas son algunas de mis sugerencias:

  • Intente usar conjuntos de datos R predeterminados
  • Si tiene su propio conjunto de datos, inclúyalos con dput, para que otros puedan ayudarlo más fácilmente
  • No lo use a install.package()menos que sea realmente necesario, la gente lo entenderá si solo usa requireolibrary
  • Trate de ser conciso

    • Tener un conjunto de datos
    • Intente describir la salida que necesita de la manera más simple posible
    • Hágalo usted mismo antes de hacer la pregunta
  • Es fácil cargar una imagen, así que cargue parcelas si tiene
  • También incluya cualquier error que pueda tener

Todos estos son parte de un ejemplo reproducible.

18 dank Apr 05 2017 at 04:08

Es una buena idea usar funciones del testthatpaquete para mostrar lo que espera que ocurra. Por lo tanto, otras personas pueden modificar su código hasta que se ejecute sin errores. Esto alivia la carga de quienes quisieran ayudarlo, porque significa que no tienen que decodificar su descripción textual. Por ejemplo

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

es más claro que "Creo que x resultaría ser 1,23 para y igual o superior a 10, y 3,21 en caso contrario, pero no obtuve ningún resultado". Incluso en este ejemplo tonto, creo que el código es más claro que las palabras. El uso le testthatpermite a su ayudante concentrarse en el código, lo que le ahorra tiempo y le brinda una forma de saber que ha resuelto su problema antes de publicarlo.