Cuando se discute el desempeño con colegas, se enseña, se envía un informe de error o se busca orientación en las listas de correo y aquí en Stack Overflow, a menudo se pide un ejemplo reproducible y siempre es útil.
¿Cuáles son tus consejos para crear un excelente ejemplo? ¿Cómo se pegan las estructuras de datos deren formato de texto? ¿Qué otra información debe incluir?
¿Hay otros trucos además de usar dput()
, dump()
o structure()
? ¿Cuándo debe incluir library()
o require()
declaraciones? ¿Qué palabras reservadas debe uno evitar, además c
, df
, data
, etc.?
¿Cómo se puede hacer un gran r ejemplo reproducible?
Respuestas:
Un ejemplo reproducible mínimo consta de los siguientes elementos:
set.seed()
) para la reproducibilidad 1Para ver ejemplos de buenos ejemplos reproducibles mínimos , consulte los archivos de ayuda de la función que está utilizando. En general, todo el código proporcionado cumple los requisitos de un ejemplo reproducible mínimo: se proporcionan datos, se proporciona un código mínimo y todo es ejecutable. También mire las preguntas sobre Stack Overflow con muchos votos a favor.
Produciendo un conjunto de datos mínimo
Para la mayoría de los casos, esto se puede hacer fácilmente simplemente proporcionando un marco de vector / datos con algunos valores. O puede usar uno de los conjuntos de datos integrados, que se proporcionan con la mayoría de los paquetes.
Se puede ver una lista completa de los 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,?mtcars
donde '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 hacerlo.
sample()
puede aleatorizar un vector o dar un vector aleatorio con solo unos pocos valores.letters
es un vector útil que contiene el alfabeto. Esto se puede usar para hacer factores.Algunos ejemplos :
x <- rnorm(10)
para distribución normal,x <- runif(10)
para distribución uniforme, ...x <- sample(1:10)
para el vector 1:10 en orden aleatorio.x <- sample(letters[1:4], 20, replace = TRUE)
Para las matrices, uno puede usar
matrix()
, por ejemplo:Hacer 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 :
Para algunas preguntas, se pueden necesitar formatos específicos. Para estos, uno puede utilizar cualquiera de los previstos
as.someType
funciones:as.factor
,as.Date
,as.xts
, ... Estos en combinación con los trucos de vectores y / o trama de datos.Copia tus 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 usedput()
para darnos algo que se pueda poner en R inmediatamente:Si su marco de datos tiene un factor con muchos niveles, la
dput
salida 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 usar ladroplevels()
función. Observe a continuación cómo las especies son un factor con un solo nivel:Al usar
dput
, es posible que también desee incluir solo columnas relevantes:Otra advertencia para
dput
es que no funcionará paradata.table
objetos con clave o para agrupadostbl_df
(clasegrouped_df
) dedplyr
. En estos casos se puede convertir de nuevo a una trama de datos regular antes de compartirdput(as.data.frame(my_data))
.En el peor de los casos, puede proporcionar una representación de texto que se puede leer utilizando el
text
parámetro deread.table
: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:
Lo que debes hacer es:
library()
)unlink()
)op <- par(mfrow=c(1,2)) ...some code... par(op)
)Dar información extra
En la mayoría de los casos, solo la versión R y el sistema operativo serán suficientes. Cuando surgen conflictos con los paquetes, dar la salida de
sessionInfo()
realmente puede ayudar. Cuando se habla de conexiones a otras aplicaciones (ya sea a través de ODBC o cualquier otra cosa), también se deben proporcionar números de versión para 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, puede proporcionar la versión del paquete dando la salida 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 utilizó 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 laRNGversion()
función -antesset.seed()
(por ejemplo :)RNGversion("3.5.2")
.fuente
dput
si el marco de datos es muy grande y el problema se genera en el medio del marco de datos? ¿Hay alguna manera de usardput
para reproducir la sección media de datos, digamos las filas 60 a 70?tmp <- mydf[50:70,]
seguido dedput(mydf)
. Si el marco de datos es realmente grande, intente aislar el problema y solo envíe las pocas líneas que causan el problema.head
odput
limitar los datos al nivel N de forma recursiva? Estoy tratando de encontrar un ejemplo reproducible y mis datos son una lista de marcos de datos. Entonces,dput(head(myDataObj))
parece que no es suficiente, ya que genera un archivo de salida de 14 MB de tamaño.(Aquí está mi consejo de Cómo escribir un ejemplo reproducible . He tratado de hacerlo breve pero dulce)
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 el código R.
Hay cuatro cosas que debe incluir para que su ejemplo sea reproducible: paquetes necesarios, 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 pregunta de desbordamiento de pila es utilizar
dput()
para generar el código R para recrearlo. Por ejemplo, para recrear elmtcars
conjunto de datos en R, realizaría los siguientes pasos:dput(mtcars)
en rmtcars <-
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 usado espacios y sus nombres de 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 R y facilita la comprobación de si está utilizando un paquete desactualizado.Puede verificar que realmente haya hecho un ejemplo reproducible iniciando una nueva sesión R y pegando su script.
Antes de poner todo su código en un correo electrónico, considere ponerlo en Gistub de Gist . 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.
fuente
reprex
intidyverse
es un buen paquete para producir un ejemplo mínimo y reproducible: github.com/tidyverse/reprexPersonalmente, prefiero los revestimientos "uno". Algo en la línea:
La estructura de datos debe imitar la idea del problema del escritor y no la estructura textual exacta. Realmente aprecio que las variables no sobrescriban mis propias variables o que Dios no lo permita, funciones (como
df
).Alternativamente, uno podría cortar algunas esquinas y señalar un conjunto de datos preexistente, algo como:
No olvide mencionar cualquier paquete especial que pueda estar usando.
Si está intentando demostrar algo en objetos más grandes, puede intentar
Si está trabajando con datos espaciales a través del
raster
paquete, puede generar algunos datos aleatorios. Se pueden encontrar muchos ejemplos en la viñeta del paquete, pero aquí hay una pequeña pepita.Si necesita algún objeto espacial tal como está implementado
sp
, puede obtener algunos conjuntos de datos a través de archivos externos (como el archivo de forma ESRI) en paquetes "espaciales" (consulte la Vista espacial en Vistas de tareas).fuente
sample
orunif
es prudenteset.seed
. Al menos, esta es la sugerencia que he recibido al producir ejemplos que se transmiten en muestreo o generación de números aleatorios.runif
osample
no están confundidos que no pueden obtener los mismos datos.Inspirado en esta misma publicación, ahora uso una función práctica
reproduce(<mydata>)
cuando necesito publicar en StackOverflow.INSTRUCCIONES RÁPIDAS
Si
myData
es el nombre de su objeto para reproducir, ejecute lo siguiente en R:Detalles:
Esta función es un contenedor inteligente
dput
y hace lo siguiente:dput
salidaobjName <- ...
para que se pueda copiar y pegar fácilmente, pero ...La fuente está disponible aquí:
Ejemplo:
DF mide aproximadamente 100 x 102. Quiero muestrear 10 filas y algunas columnas específicas
Da el siguiente resultado:
Observe también que la totalidad de la salida está en una bonita línea larga y no un párrafo alto de líneas cortadas. Esto facilita la lectura en publicaciones de preguntas SO y también es más fácil copiar y pegar.
Actualización de octubre de 2013:
Ahora puede especificar cuántas líneas de salida de texto ocuparán (es decir, qué pegará en StackOverflow). Usa el
lines.out=n
argumento para esto. Ejemplo:reproduce(DF, cols=c(1:3, 17, 23), lines.out=7)
rendimientos:fuente
Aquí hay 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 hacer 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 dónde está el problema usted mismo. 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.fuente
La lista de correo de R-help tiene una guía de publicación que cubre preguntas y respuestas, incluido un ejemplo de generación de datos:
La palabra pequeña es especialmente importante. Debería apuntar a un ejemplo reproducible mínimo , lo que significa que los datos y el código deberían 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. Usa una guía de estilo .
fuente
Desde R.2.14 (supongo) puede alimentar su representación de texto de datos directamente a
read.table
:fuente
A veces, el problema realmente no es reproducible con un dato más pequeño, no importa cuánto lo intente, y no sucede con datos sintéticos (aunque es útil para mostrar cómo produjo conjuntos de datos sintéticos que no reprodujeron el problema, porque descarta algunas hipótesis).
Si no puede hacer ninguno de estos, entonces probablemente necesite contratar a un consultor para resolver su problema ...
editar : Dos preguntas SO útiles para la anonimización / codificación:
fuente
fitdistr
yfitdistrplus
.Las respuestas hasta ahora son obviamente excelentes para la parte de reproducibilidad. Esto es simplemente para aclarar que un ejemplo reproducible no puede y no debe ser el único componente de una pregunta. No olvides explicar cómo quieres que se vea y los contornos de tu problema, no solo cómo has intentado llegar hasta ahora. El código no es suficiente; Necesitas palabras también.
Aquí hay un ejemplo reproducible de qué evitar hacer (extraído de un ejemplo real, nombres cambiados para proteger a los inocentes):
Lo siguiente son datos de muestra y parte de la función con la que tengo problemas.
Cómo puedo conseguir esto ?
fuente
Tengo una manera 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,
Luego puede ingresar sus datos manualmente. Esto es eficiente para ejemplos más pequeños en lugar de grandes.
fuente
dput(mydata)
for (d in data) {...}
.Para crear rápidamente un
dput
de sus datos, puede simplemente copiar (un pedazo de) los datos en su portapapeles y ejecutar lo siguiente en R:para datos en Excel:
para datos en un archivo txt:
Puede cambiar el
sep
en este último si es necesario. Esto solo funcionará si sus datos están en el portapapeles, por supuesto.fuente
Pautas:
Su objetivo principal en la elaboración de sus preguntas debe ser hacer que sea lo más fácil posible para los lectores comprender y reproducir su problema en sus sistemas. Para hacerlo:
Esto requiere algo de trabajo, pero parece una compensación justa ya que le está pidiendo a otros que hagan el trabajo por usted.
Proporcionar datos:
Conjuntos de datos incorporados
La mejor opción , con mucho, es confiar en los conjuntos de datos incorporada. 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 todos lo tienen)Consulte este SO QA para saber cómo encontrar conjuntos de datos adecuados 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 para 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
Ahora, alguien que intenta responder mi pregunta puede copiar / pegar esas dos líneas y comenzar a trabajar en el problema de inmediato.
dput
Como último recurso , puede usar
dput
para transformar un objeto de datos en código R (por ejemplodput(myData)
). Digo como "último recurso" porque la salida dedput
es a menudo bastante difícil de manejar, molesta para copiar y pegar, y oscurece el resto de su pregunta.Proporcionar salida esperada:
Alguien dijo una vez:
Si puede agregar algo como "esperaba obtener este resultado":
a su pregunta, es mucho más probable que las personas entiendan rápidamente lo que está tratando de hacer. Si su resultado esperado es grande y difícil de manejar, entonces probablemente no haya pensado lo suficiente sobre cómo simplificar su problema (ver a continuación).
Explique su problema sucintamente
Lo principal que debe hacer es simplificar su problema tanto como sea posible antes de hacer su pregunta. Reenmarcar el problema para que funcione con los conjuntos de datos integrados ayudará mucho a este respecto. También encontrará a menudo que con solo pasar por el proceso de simplificación responderá su propio problema.
Aquí hay algunos ejemplos de buenas preguntas:
En ambos casos, los problemas del usuario casi con certeza no se deben a los simples ejemplos que proporcionan. 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: usar conjuntos de datos integrados y proporcionar 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 comentarios a preguntas para novatos.
fuente
El código reproducible es clave para obtener ayuda. Sin embargo, hay muchos usuarios que pueden ser escépticos de pegar incluso una parte de sus datos. Por ejemplo, podrían estar trabajando con datos confidenciales o con datos originales recopilados para usar en un trabajo de investigación. Por cualquier motivo, pensé que sería bueno tener una función útil para "deformar" mis datos antes de pegarlos públicamente. La
anonymize
función del paqueteSciencesPo
es muy tonta, pero para mí funciona muy bien con ladput
función.Luego lo anonimizo:
También es posible que desee muestrear algunas variables en lugar de todos los datos antes de aplicar el comando de anonimización y dput.
fuente
A menudo necesita algunos datos como ejemplo, sin embargo, no desea publicar sus datos exactos. Para usar algunos data.frame existentes en una biblioteca establecida, use el comando de datos para importarlo.
p.ej,
y luego hacer el problema
fuente
mtcars
yiris
conjuntos de datos) en realidad no necesitandata
que se use la llamada.Si tiene un conjunto de datos grande que no se puede usar fácilmente en el script
dput()
, publique sus datos en pastebin y cárguelos usandoread.table
:Inspirado por @Henrik .
fuente
Estoy desarrollando el paquete wakefield para abordar esta necesidad de compartir rápidamente datos reproducibles, a veces
dput
funciona bien para conjuntos de datos más pequeños, pero muchos de los problemas con los que nos enfrentamos son mucho mayores, compartir un conjunto de datos tan grande nodput
es práctico.Acerca de:
wakefield permite al usuario compartir código mínimo para reproducir datos. El usuario establece
n
(número de filas) y especifica cualquier número de funciones variables preestablecidas (actualmente hay 70) que imitan datos reales si (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:
Ejemplo:
Aquí hay un ejemplo:
Esto produce:
fuente
Si tiene una o más
factor
variables en sus datos con las que desea hacer reproduciblesdput(head(mydata))
, considere agregarlasdroplevels
, de modo que los niveles de factores que no están presentes en el conjunto de datos minimizado no se incluyan en sudput
salida, para Haz que el ejemplo sea mínimo :fuente
Me pregunto si un enlace http://old.r-fiddle.org/ podría ser una forma muy clara de compartir un problema. Recibe una identificación única como e incluso se podría pensar en incrustarlo en SO.
fuente
No pegue las salidas de su consola de esta manera:
No podemos copiarlo y pegarlo directamente.
Para hacer que las preguntas y respuestas se reproduzcan correctamente, intente eliminar
+
y>
antes de publicarlo y#
obtenga resultados y comentarios como este:Una cosa más, si ha utilizado alguna función de cierto paquete, mencione esa biblioteca.
fuente
>
y agrega el#
manual o hay una forma automática de hacerlo?>
manualmente. Pero, además de#
, uso elCtrl+Shift+C
acceso directo en elRStudio
editor.Puedes hacer esto usando reprex .
Como señaló mt1022 , "... un buen paquete para producir un ejemplo mínimo y reproducible es " reprex " de tidyverse ".
De acuerdo con Tidyverse :
Se da un ejemplo en el sitio web tidyverse .
Creo que esta es la forma más sencilla de crear un ejemplo reproducible.
fuente
Además de todas las respuestas anteriores que encontré muy interesantes, a veces podría ser muy fácil como se discute aquí: - CÓMO HACER UN EJEMPLO REPRODUCIBLE MÍNIMO PARA OBTENER AYUDA CON R
Hay muchas maneras de hacer un vector aleatorio Cree un vector de 100 números con valores aleatorios en R redondeados a 2 decimales o matriz aleatoria en R
Tenga en cuenta que a veces es muy difícil compartir datos dados debido a varias razones, como la dimensión, etc. Sin embargo, todas las respuestas anteriores son geniales y muy importantes para pensar y usar cuando se quiere hacer un ejemplo de datos reproducibles. Pero tenga en cuenta que para que los datos sean tan representativos como el original (en caso de que el OP no pueda compartir los datos originales), es bueno agregar cierta información con el ejemplo de datos como (si llamamos a los datos mydf1)
Además, se debe conocer el tipo, la longitud y los atributos de los datos que pueden ser estructuras de datos.
fuente
Estas son algunas de mis sugerencias:
dput
para que otros puedan ayudarlo más fácilmenteinstall.package()
menos que sea realmente necesario, la gente entenderá si solo usarequire
olibrary
Intenta ser conciso
Todos estos son parte de un ejemplo reproducible.
fuente
dput()
se ha mencionado anteriormente, y gran parte de esto es solo reiterar las pautas estándar de SO.install.package
función incluida en el ejemplo que no es realmente necesaria (en mi opinión). Además, el uso del conjunto de datos R predeterminado facilitaría la reproducción. Las pautas de SO no han mencionado nada sobre estos temas específicamente. Además, estaba destinado a dar mi opinión y estos son los que más me he encontrado.Es una buena idea usar funciones del
testthat
paquete para mostrar lo que espera que ocurra. Por lo tanto, otras personas pueden alterar su código hasta que se ejecute sin error. Esto alivia la carga de aquellos que desean ayudarlo, porque significa que no tienen que decodificar su descripción textual. Por ejemploes más claro que "Creo que x resultaría ser 1.23 para y igual o superior a 10, y 3.21 de lo contrario, pero no obtuve ninguno de los resultados". Incluso en este ejemplo tonto, creo que el código es más claro que las palabras. El uso
testthat
permite que su asistente se concentre en el código, lo que les ahorra tiempo, y les proporciona una forma de saber que han resuelto su problema, antes de publicarlo.fuente