Lorsque vous discutez de performances avec des collègues, enseignez, envoyez un rapport de bogue ou recherchez des conseils sur les listes de diffusion et ici sur Stack Overflow, un exemple reproductible est souvent demandé et toujours utile.
Quels sont vos conseils pour créer un excellent exemple? Comment collez-vous des structures de données à partir derau format texte? Quelles autres informations devez-vous inclure?
Y a-t-il d'autres astuces en plus d'utiliser dput()
, dump()
ou structure()
? Quand devez-vous inclure library()
ou des require()
déclarations? Ce qui a des mots réservés doit - on éviter, en plus c
, df
, data
, etc.?
Comment fait-on un grand r exemple reproductible?
Réponses:
Un exemple reproductible minimal comprend les éléments suivants:
set.seed()
) pour la reproductibilité 1Pour des exemples de bons exemples reproductibles minimes , consultez les fichiers d'aide de la fonction que vous utilisez. En général, tout le code qui y est fourni répond aux exigences d'un exemple reproductible minimal: les données sont fournies, le code minimal est fourni et tout est exécutable. Consultez également les questions sur Stack Overflow avec beaucoup de votes positifs.
Produire un ensemble de données minimal
Pour la plupart des cas, cela peut être fait facilement en fournissant simplement un cadre vectoriel / de données avec quelques valeurs. Ou vous pouvez utiliser l'un des jeux de données intégrés, fournis avec la plupart des packages.
Une liste complète des jeux de données intégrés peut être consultée avec
library(help = "datasets")
. Il y a une brève description de chaque ensemble de données et plus d'informations peuvent être obtenues, par exemple avec?mtcars
où «mtcars» est l'un des ensembles de données dans la liste. D'autres packages peuvent contenir des jeux de données supplémentaires.Faire un vecteur est facile. Parfois, il est nécessaire d'y ajouter un caractère aléatoire, et il existe un certain nombre de fonctions pour le faire.
sample()
peut randomiser un vecteur ou donner un vecteur aléatoire avec seulement quelques valeurs.letters
est un vecteur utile contenant l'alphabet. Cela peut être utilisé pour créer des facteurs.Quelques exemples:
x <- rnorm(10)
pour une distribution normale,x <- runif(10)
pour une distribution uniforme, ...x <- sample(1:10)
pour le vecteur 1:10 dans un ordre aléatoire.x <- sample(letters[1:4], 20, replace = TRUE)
Pour les matrices, on peut utiliser
matrix()
, par exemple:La création de trames de données peut être effectuée à l'aide de
data.frame()
. Il faut faire attention à nommer les entrées dans le bloc de données et à ne pas le rendre trop compliqué.Un exemple :
Pour certaines questions, des formats spécifiques peuvent être nécessaires. Pour ceux - ci, on peut utiliser les fournis
as.someType
fonctions:as.factor
,as.Date
,as.xts
, ... Ces en combinaison avec le vecteur et / ou astuces trame de données.Copiez vos données
Si vous avez des données qui seraient trop difficiles à construire en utilisant ces conseils, vous pouvez toujours faire un sous - ensemble de vos données d' origine, en utilisant
head()
,subset()
ou les indices. Ensuite, utilisezdput()
pour nous donner quelque chose qui peut être mis en R immédiatement:Si votre trame de données a un facteur à plusieurs niveaux, la
dput
sortie peut être lourde car elle répertoriera toujours tous les niveaux de facteurs possibles même s'ils ne sont pas présents dans le sous-ensemble de vos données. Pour résoudre ce problème, vous pouvez utiliser ladroplevels()
fonction. Notez ci-dessous comment l'espèce est un facteur avec un seul niveau:Lors de l'utilisation
dput
, vous pouvez également vouloir inclure uniquement les colonnes pertinentes:Une autre mise en garde
dput
est que cela ne fonctionnera pas pour lesdata.table
objets à clés ou pour les groupestbl_df
(classesgrouped_df
) dedplyr
. Dans ces cas , vous pouvez reconvertir en une trame de données régulière avant le partage,dput(as.data.frame(my_data))
.Dans le pire des cas, vous pouvez donner une représentation textuelle qui peut être lue en utilisant le
text
paramètre deread.table
:Produire un code minimal
Cela devrait être la partie facile, mais ce n'est souvent pas le cas. Ce que vous ne devez pas faire, c'est:
Ce que vous devez faire, c'est:
library()
)unlink()
)op <- par(mfrow=c(1,2)) ...some code... par(op)
)Donner des informations supplémentaires
Dans la plupart des cas, seule la version R et le système d'exploitation suffiront. Lorsque des conflits surviennent avec des packages, donner la sortie de
sessionInfo()
peut vraiment aider. Lorsque vous parlez de connexions à d'autres applications (que ce soit via ODBC ou autre), il convient également de fournir des numéros de version pour celles-ci et, si possible, les informations nécessaires sur la configuration.Si vous utilisez R dans R studio en utilisant
rstudioapi::versionInfo()
peut être utile de signaler votre version rstudio.Si vous rencontrez un problème avec un package spécifique, vous souhaiterez peut-être fournir la version du package en indiquant la sortie de
packageVersion("name of the package")
.1 Remarque: La sortie de
set.seed()
diffère entre R> 3.6.0 et les versions précédentes. Précisez la version R que vous avez utilisée pour le processus aléatoire et ne soyez pas surpris si vous obtenez des résultats légèrement différents lorsque vous suivez d'anciennes questions. Pour obtenir le même résultat dans de tels cas, vous pouvez utiliser laRNGversion()
fonction-avantset.seed()
(par exemple :)RNGversion("3.5.2")
.la source
dput
si la trame de données est très grande et que le problème est généré par le milieu de la trame de données? Existe-t-il un moyen dedput
reproduire la partie médiane des données, par exemple les lignes 60 à 70?tmp <- mydf[50:70,]
suivi dedput(mydf)
. Si la trame de données est vraiment volumineuse, essayez d'isoler le problème et soumettez simplement les quelques lignes qui causent le problème.head
oudput
de limiter les données au niveau N de manière récursive? J'essaie de trouver un exemple reproductible et mes données sont une liste de trames de données. Donc, celadput(head(myDataObj))
ne semble pas suffisant, car il génère un fichier de sortie de 14 Mo.(Voici mes conseils de Comment écrire un exemple reproductible . J'ai essayé de le rendre court mais doux)
Comment écrire un exemple reproductible.
Vous êtes le plus susceptible d'obtenir une bonne aide avec votre problème R si vous fournissez un exemple reproductible. Un exemple reproductible permet à quelqu'un d'autre de recréer votre problème en copiant et collant simplement le code R.
Vous devez inclure quatre éléments pour rendre votre exemple reproductible: les packages requis, les données, le code et une description de votre environnement R.
Les packages doivent être chargés en haut du script, il est donc facile de voir ceux dont l'exemple a besoin.
Le moyen le plus simple d'inclure des données dans un e-mail ou une question de débordement de pile est d'utiliser
dput()
pour générer le code R pour le recréer. Par exemple, pour recréer l'mtcars
ensemble de données dans R, j'effectuerais les étapes suivantes:dput(mtcars)
in Rmtcars <-
puis collez.Passez un peu de temps à vous assurer que votre code est facile à lire pour les autres:
assurez-vous que vous avez utilisé des espaces et que les noms de vos variables sont concis, mais informatifs
utiliser des commentaires pour indiquer où se situe votre problème
faites de votre mieux pour supprimer tout ce qui n'est pas lié au problème.
Plus votre code est court, plus il est facile à comprendre.
Incluez la sortie de
sessionInfo()
dans un commentaire dans votre code. Cela résume votre environnement R et vous permet de vérifier facilement si vous utilisez un package obsolète.Vous pouvez vérifier que vous avez réellement créé un exemple reproductible en démarrant une nouvelle session R et en collant votre script.
Avant de mettre tout votre code dans un e-mail, pensez à le mettre sur Gist github . Cela donnera à votre code une belle coloration syntaxique et vous n'aurez pas à vous soucier de quoi que ce soit qui soit corrompu par le système de messagerie.
la source
reprex
intidyverse
est un bon package pour produire un exemple minimal et reproductible: github.com/tidyverse/reprexPersonnellement, je préfère les doublures "one". Quelque chose le long des lignes:
La structure des données doit imiter l'idée du problème de l'auteur et non la structure exacte du mot. J'apprécie vraiment quand les variables n'écrasent pas mes propres variables ou que Dieu ne plaise, les fonctions (comme
df
).Alternativement, on pourrait couper quelques coins et pointer vers un ensemble de données préexistant, quelque chose comme:
N'oubliez pas de mentionner les packages spéciaux que vous utilisez.
Si vous essayez de démontrer quelque chose sur des objets plus grands, vous pouvez essayer
Si vous travaillez avec des données spatiales via le
raster
package, vous pouvez générer des données aléatoires. De nombreux exemples peuvent être trouvés dans la vignette du package, mais voici un petit nugget.Si vous avez besoin d'un objet spatial tel qu'implémenté dans
sp
, vous pouvez obtenir certains ensembles de données via des fichiers externes (comme le fichier de formes ESRI) dans des packages "spatiaux" (voir la vue spatiale dans les vues de tâches).la source
sample
ourunif
il est prudent deset.seed
. C'est du moins la suggestion que j'ai reçue lors de la production d'exemples relayant l'échantillonnage ou la génération de nombres aléatoires.runif
ousample
ne sont pas confuses qu'ils ne peuvent pas obtenir les mêmes données.Inspiré par ce message, j'utilise maintenant une fonction pratique
reproduce(<mydata>)
lorsque je dois publier sur StackOverflow.INSTRUCTIONS RAPIDES
Si
myData
est le nom de votre objet à reproduire, exécutez ce qui suit dans R:Détails:
Cette fonction est un wrapper intelligent pour
dput
:dput
sortieobjName <- ...
afin qu'il puisse être facilement copié + collé, mais ...La source est disponible ici:
Exemple:
DF est d'environ 100 x 102. Je veux échantillonner 10 lignes et quelques colonnes spécifiques
Donne la sortie suivante:
Notez également que l'intégralité de la sortie est dans une belle ligne longue et non un grand paragraphe de lignes hachées. Cela rend plus facile à lire sur les messages de questions SO et aussi plus facile à copier + coller.
Mise à jour d'octobre 2013:
Vous pouvez maintenant spécifier combien de lignes de sortie de texte occuperont (c'est-à-dire ce que vous collerez dans StackOverflow). Utilisez l'
lines.out=n
argument pour cela. Exemple:reproduce(DF, cols=c(1:3, 17, 23), lines.out=7)
rendements:la source
Voici un bon guide .
Le point le plus important est: assurez-vous de créer un petit morceau de code que nous pouvons exécuter pour voir quel est le problème . Une fonction utile pour cela est
dput()
, mais si vous avez de très grandes données, vous voudrez peut-être créer un petit échantillon de données ou utiliser uniquement les 10 premières lignes environ.ÉDITER:
Assurez-vous également que vous avez identifié le problème vous-même. L'exemple ne doit pas être un script R complet avec "Sur la ligne 200, il y a une erreur". Si vous utilisez les outils de débogage dans R (j'adore
browser()
) et Google, vous devriez être en mesure d'identifier vraiment où se trouve le problème et de reproduire un exemple trivial dans lequel la même chose ne va pas.la source
La liste de diffusion R-help dispose d'un guide de publication qui couvre à la fois les questions posées et les réponses, y compris un exemple de génération de données:
Le mot petit est particulièrement important. Vous devez viser un exemple reproductible minimal , ce qui signifie que les données et le code doivent être aussi simples que possible pour expliquer le problème.
EDIT: Un joli code est plus facile à lire qu'un code laid. Utilisez un guide de style .
la source
Depuis R.2.14 (je suppose), vous pouvez alimenter votre représentation de texte de données directement pour
read.table
:la source
Parfois, le problème n'est vraiment pas reproductible avec une plus petite quantité de données, peu importe vos efforts, et ne se produit pas avec des données synthétiques (bien qu'il soit utile de montrer comment vous avez produit des ensembles de données synthétiques qui n'ont pas reproduit le problème, car cela exclut certaines hypothèses).
Si vous ne pouvez pas faire l'un ou l'autre, vous devrez probablement engager un consultant pour résoudre votre problème ...
edit : Deux questions SO utiles pour l'anonymisation / brouillage:
la source
fitdistr
etfitdistrplus
.Jusqu'à présent, les réponses sont évidemment excellentes pour la partie reproductibilité. Il s'agit simplement de préciser qu'un exemple reproductible ne peut et ne doit pas être le seul élément d'une question. N'oubliez pas d'expliquer à quoi vous voulez qu'il ressemble et les contours de votre problème, pas seulement comment vous avez tenté d'y arriver jusqu'à présent. Le code ne suffit pas; vous avez aussi besoin de mots.
Voici un exemple reproductible de ce qu'il faut éviter de faire (tiré d'un exemple réel, les noms ont changé pour protéger l'innocent):
Voici des exemples de données et une partie de la fonction avec laquelle j'ai des problèmes.
Comment puis-je atteindre cet objectif ?
la source
J'ai un moyen très simple et efficace de faire un exemple R qui n'a pas été mentionné ci-dessus. Vous pouvez d'abord définir votre structure. Par exemple,
Ensuite, vous pouvez saisir vos données manuellement. Ceci est efficace pour les petits exemples plutôt que pour les gros.
la source
dput(mydata)
for (d in data) {...}
.Pour créer rapidement une
dput
de vos données, vous pouvez simplement copier (un morceau de) les données dans votre presse-papiers et exécuter ce qui suit dans R:pour les données dans Excel:
pour les données dans un fichier txt:
Vous pouvez modifier le
sep
dans ce dernier si nécessaire. Cela ne fonctionnera que si vos données sont dans le presse-papiers bien sûr.la source
Des lignes directrices:
Votre objectif principal dans l'élaboration de vos questions devrait être de permettre aux lecteurs de comprendre et de reproduire votre problème aussi facilement que possible sur leurs systèmes. Faire cela:
Cela nécessite un certain travail, mais semble être un compromis équitable car vous demandez à d'autres de travailler pour vous.
Fournir des données:
Ensembles de données intégrés
La meilleure option est de loin de s'appuyer sur des jeux de données intégrés. Cela permet aux autres de travailler très facilement sur votre problème. Tapez
data()
à l'invite R pour voir quelles données sont disponibles pour vous. Quelques exemples classiques:iris
mtcars
ggplot2::diamonds
(paquet externe, mais presque tout le monde l'a)Consultez ce SO QA pour savoir comment trouver des ensembles de données adaptés à votre problème.
Si vous êtes en mesure de reformuler votre problème pour utiliser les jeux de données intégrés, vous avez beaucoup plus de chances d'obtenir de bonnes réponses (et des votes positifs).
Données auto-générées
Si votre problème est très spécifique à un type de données qui n'est pas représenté dans les ensembles de données existants, fournissez le code R qui génère le plus petit ensemble de données possible sur lequel votre problème se manifeste. Par exemple
Maintenant, quelqu'un qui essaie de répondre à ma question peut copier / coller ces deux lignes et commencer à travailler sur le problème immédiatement.
dput
En dernier recours , vous pouvez utiliser
dput
pour transformer un objet de données en code R (par exempledput(myData)
). Je dis en "dernier recours" car la sortie dedput
est souvent assez lourde, ennuyeuse à copier-coller et obscurcit le reste de votre question.Fournir les résultats attendus:
Quelqu'un a dit un jour:
Si vous pouvez ajouter quelque chose comme "je m'attendais à obtenir ce résultat":
à votre question, les gens sont beaucoup plus susceptibles de comprendre rapidement ce que vous essayez de faire. Si votre résultat escompté est volumineux et peu maniable, vous n'avez probablement pas suffisamment réfléchi à la façon de simplifier votre problème (voir ci-dessous).
Expliquez votre problème de manière succincte
La principale chose à faire est de simplifier au maximum votre problème avant de poser votre question. Recadrer le problème pour travailler avec les jeux de données intégrés aidera beaucoup à cet égard. Vous constaterez également souvent qu'en suivant simplement le processus de simplification, vous répondrez à votre propre problème.
Voici quelques exemples de bonnes questions:
Dans les deux cas, les problèmes de l'utilisateur ne sont certainement pas liés aux exemples simples qu'ils fournissent. Ils ont plutôt résumé la nature de leur problème et l'ont appliqué à un simple ensemble de données pour poser leur question.
Pourquoi encore une autre réponse à cette question?
Cette réponse se concentre sur ce que je pense être la meilleure pratique: utiliser des ensembles de données intégrés et fournir ce que vous attendez en conséquence sous une forme minimale. Les réponses les plus importantes se concentrent sur d'autres aspects. Je ne m'attends pas à ce que cette réponse prenne de l'importance; c'est ici uniquement pour que je puisse y faire un lien dans les commentaires aux questions des débutants.
la source
Un code reproductible est essentiel pour obtenir de l'aide. Cependant, de nombreux utilisateurs pourraient être sceptiques à l'idée de coller même une partie de leurs données. Par exemple, ils pourraient travailler avec des données sensibles ou sur des données originales collectées pour être utilisées dans un document de recherche. Pour une raison quelconque, j'ai pensé qu'il serait bien d'avoir une fonction pratique pour "déformer" mes données avant de les coller publiquement. La
anonymize
fonction du paquetSciencesPo
est très stupide, mais pour moi, cela fonctionne bien avec ladput
fonction.Ensuite, je l'anonymise:
On peut également vouloir échantillonner quelques variables au lieu des données entières avant d'appliquer l'anonymisation et la commande dput.
la source
Souvent, vous avez besoin de données pour un exemple, cependant, vous ne voulez pas publier vos données exactes. Pour utiliser certains data.frame existants dans la bibliothèque établie, utilisez la commande data pour l'importer.
par exemple,
puis faire le problème
la source
mtcars
et lesiris
ensembles de données) n'ont pas réellement besoin de l'data
appel pour être utilisés.Si vous avez un grand ensemble de données qui ne peut pas être facilement mis dans le script à l'aide de
dput()
, postez vos données dans pastebin et chargez-les en utilisantread.table
:Inspiré par @Henrik .
la source
Je développe le package wakefield pour répondre à ce besoin de partager rapidement des données reproductibles,
dput
fonctionne parfois bien pour les petits ensembles de données, mais bon nombre des problèmes que nous traitons sont beaucoup plus importants, le partage d'un si grand ensemble de données viadput
n'est pas pratique.À propos de:
wakefield permet à l'utilisateur de partager un minimum de code pour reproduire les données. L'utilisateur définit
n
(nombre de lignes) et spécifie n'importe quel nombre de fonctions variables prédéfinies (il y en a actuellement 70) qui imitent les données réelles si (des choses comme le sexe, l'âge, le revenu, etc.)Installation:
Actuellement (2015-06-11), wakefield est un package GitHub mais ira finalement au CRAN après l'écriture des tests unitaires. Pour installer rapidement, utilisez:
Exemple:
Voici un exemple:
Cela produit:
la source
Si vous avez une ou plusieurs
factor
variables dans vos données que vous souhaitez rendre reproductiblesdput(head(mydata))
, envisagez d'y ajouterdroplevels
, de sorte que les niveaux de facteurs qui ne sont pas présents dans l'ensemble de données minimisé ne soient pas inclus dans votredput
sortie, afin de rendre l'exemple minimal :la source
Je me demande si un lien http://old.r-fiddle.org/ pourrait être un moyen très soigné de partager un problème. Il reçoit un ID unique comme et on pourrait même penser à l'intégrer dans SO.
la source
Veuillez ne pas coller les sorties de votre console comme ceci:
Nous ne pouvons pas le copier-coller directement.
Pour que les questions et réponses soient correctement reproductibles, essayez de supprimer
+
&>
avant de les publier et de soumettre#
des sorties et des commentaires comme ceci:Encore une chose, si vous avez utilisé une fonction de certains packages, mentionnez cette bibliothèque.
la source
>
et ajoutez-le#
manuellement ou existe-t-il un moyen automatique de le faire?>
manuellement. Mais, pour l'ajout de#
, j'utilise unCtrl+Shift+C
raccourci dans l'RStudio
éditeur.Vous pouvez le faire en utilisant reprex .
Comme l'a noté mt1022 , "... un bon package pour produire un exemple reproductible minimal est " reprex " from tidyverse ".
Selon Tidyverse :
Un exemple est donné sur le site web de tidyverse .
Je pense que c'est la façon la plus simple de créer un exemple reproductible.
la source
En dehors de toutes les réponses ci-dessus que j'ai trouvées très intéressantes, cela peut parfois être très facile car il est discuté ici: - COMMENT FAIRE UN EXEMPLE MINIMAL REPRODUCTIBLE POUR OBTENIR DE L'AIDE AVEC R
Il existe plusieurs façons de créer un vecteur aléatoire Créez un vecteur de 100 nombres avec des valeurs aléatoires en R arrondies à 2 décimales ou une matrice aléatoire en R
Notez qu'il est parfois très difficile de partager une donnée donnée pour diverses raisons telles que la dimension, etc. Cependant, toutes les réponses ci-dessus sont excellentes et très importantes à penser et à utiliser lorsque l'on veut faire un exemple de données reproductibles. Mais notez que pour rendre des données aussi représentatives que l'original (dans le cas où l'OP ne peut pas partager les données d'origine), il est bon d'ajouter des informations avec l'exemple de données comme (si nous appelons les données mydf1)
De plus, il faut connaître le type, la longueur et les attributs d'une donnée qui peut être une structure de données
la source
Voici quelques-unes de mes suggestions:
dput
, afin que d'autres puissent vous aider plus facilementinstall.package()
sauf si c'est vraiment nécessaire, les gens comprendront si vous utilisezrequire
oulibrary
Essayez d'être concis,
Tout cela fait partie d'un exemple reproductible.
la source
dput()
a été mentionné précédemment, et une grande partie de cela ne fait que réitérer les directives standard de SO.install.package
fonction incluse dans l'exemple qui n'est pas vraiment nécessaire (à mon avis). De plus, l'utilisation de l'ensemble de données R par défaut faciliterait la reproductibilité. Les directives de l'OS n'ont pas parlé spécifiquement de ces sujets. De plus, il était censé donner mon avis et ce sont ceux que j'ai le plus rencontrés.C'est une bonne idée d'utiliser les fonctions du
testthat
package pour montrer ce que vous attendez. Ainsi, d'autres personnes peuvent modifier votre code jusqu'à ce qu'il s'exécute sans erreur. Cela allège le fardeau de ceux qui souhaitent vous aider, car cela signifie qu'ils n'ont pas à décoder votre description textuelle. Par exempleest plus clair que "je pense que x serait égal à 1,23 pour y égal ou supérieur à 10, et 3,21 sinon, mais je n'ai obtenu aucun résultat". Même dans cet exemple stupide, je pense que le code est plus clair que les mots. L'utilisation
testthat
permet à votre assistant de se concentrer sur le code, ce qui lui fait gagner du temps et lui permet de savoir qu'il a résolu votre problème avant de le publier.la source