Comment faire un bon exemple reproductible

En discutant des performances avec des collègues, en enseignant, en envoyant un rapport de bogue ou en recherchant 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 coller des structures de données de r dans un format texte? Quelles autres informations devriez-vous inclure?

Y a-t-il d’autres astuces en plus d’utiliser dput() , dump() ou structure() ? Quand faut-il inclure des instructions library() ou require() ? Quels mots réservés faut-il éviter, en plus de c , df , data , etc.?

Comment fait-on un excellent exemple reproductible?

Un exemple reproductible minimal comprend les éléments suivants:

  • un dataset minimal, nécessaire pour reproduire l’erreur
  • le code exécutable minimal nécessaire pour reproduire l’erreur, qui peut être exécuté sur le jeu de données donné.
  • les informations nécessaires sur les packages, la version R et le système utilisés.
  • dans le cas de processus aléatoires, une graine (définie par set.seed() ) pour la reproductibilité

Il est souvent utile de regarder les exemples dans les fichiers d’aide des fonctions utilisées. En général, tout le code donné répond aux exigences d’un exemple reproductible minimal: les données sont fournies, un code minimal est fourni et tout est exécutable.

Produire un dataset minimal

Pour la plupart des cas, cela peut être facilement effectué en fournissant simplement un vecteur / une trame de données avec certaines valeurs. Vous pouvez également utiliser l’un des jeux de données intégrés, fournis avec la plupart des packages.
Une liste complète de jeux de données intégrés peut être vue avec la library(help = "datasets") . Il y a une brève description de chaque jeu de données et plus d’informations peuvent être obtenues, par exemple, avec ?mtcars où «mtcars» est l’un des jeux de données de la liste. D’autres packages peuvent contenir des jeux de données supplémentaires.

Faire un vecteur est facile. Parfois, il faut y append un peu d’aléa, et il y a un grand nombre de fonctions pour faire cela. sample() peut randomiser un vecteur ou donner un vecteur aléatoire avec seulement quelques valeurs. letters sont un vecteur utile contenant l’alphabet. Cela peut être utilisé pour créer des facteurs.

Quelques exemples:

  • valeurs aléatoires: x <- rnorm(10) pour une dissortingbution normale, x <- runif(10) pour une dissortingbution uniforme, ...
  • une permutation de certaines valeurs: x <- sample(1:10) pour le vecteur 1:10 dans un ordre aléatoire.
  • un facteur aléatoire: x <- sample(letters[1:4], 20, replace = TRUE)

Pour les masortingces, on peut utiliser masortingx() , par exemple:

 masortingx(1:10, ncol = 2) 

Faire des trames de données peut être fait en utilisant data.frame() . Il faut faire attention à nommer les entrées dans le bloc de données et à ne pas le compliquer trop.

Un exemple :

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

Pour certaines questions, des formats spécifiques peuvent être nécessaires. Pour celles-ci, on peut utiliser n'importe as.someType fonctions as.someType fournies: as.factor , as.Date , as.xts , ... Celles-ci en combinaison avec les astuces vector et / ou trame de données.

Copiez vos données

Si vous avez des données trop difficiles à construire à l'aide de ces astuces, vous pouvez toujours créer un sous-ensemble de vos données d'origine, en utilisant par exemple head() , subset() ou les index. Ensuite, utilisez par exemple. dput() pour nous donner quelque chose qui peut être mis immédiatement dans R:

 > dput(head(iris,4)) structure(list(Sepal.Length = c(5.1, 4.9, 4.7, 4.6), Sepal.Width = c(3.5, 3, 3.2, 3.1), Petal.Length = c(1.4, 1.4, 1.3, 1.5), Petal.Width = c(0.2, 0.2, 0.2, 0.2), Species = structure(c(1L, 1L, 1L, 1L), .Label = c("setosa", "versicolor", "virginica"), class = "factor")), .Names = c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species"), row.names = c(NA, 4L), class = "data.frame") 

Si votre dput données a un facteur à plusieurs niveaux, la sortie dput peut être lourde car elle répertorie 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 la fonction droplevels() . Notez ci-dessous comment l’espèce est un facteur à un seul niveau:

 > dput(droplevels(head(iris, 4))) structure(list(Sepal.Length = c(5.1, 4.9, 4.7, 4.6), Sepal.Width = c(3.5, 3, 3.2, 3.1), Petal.Length = c(1.4, 1.4, 1.3, 1.5), Petal.Width = c(0.2, 0.2, 0.2, 0.2), Species = structure(c(1L, 1L, 1L, 1L), .Label = "setosa", class = "factor")), .Names = c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species"), row.names = c(NA, 4L), class = "data.frame") 

Une autre mise en garde pour dput est que cela ne fonctionnera pas pour les objects data.table clé ou pour groupé tbl_df (class grouped_df ) à partir de dplyr . Dans ces cas, vous pouvez reconvertir en un dput(as.data.frame(my_data)) données normal avant de le partager, dput(as.data.frame(my_data)) .

Dans le pire des cas, vous pouvez donner une représentation de texte lisible en utilisant le paramètre text 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) 

Produire un code minimal

Cela devrait être la partie la plus facile, mais ce n'est souvent pas le cas. Ce que vous ne devriez pas faire, c'est:

  • Ajoutez tous les types de conversions de données. Assurez-vous que les données fournies sont déjà au bon format (à moins que ce soit le problème bien sûr)
  • copier-coller une fonction entière / morceau de code qui donne une erreur. Tout d'abord, essayez de localiser les lignes qui entraînent exactement l'erreur. Plus souvent qu'autrement, vous découvrirez quel est le problème vous-même.

Ce que vous devez faire, c'est:

  • ajoutez les paquets à utiliser si vous en utilisez (en utilisant library() )
  • si vous ouvrez des connexions ou créez des fichiers, ajoutez du code pour les fermer ou supprimez les fichiers (en utilisant unlink() )
  • Si vous modifiez les options, assurez-vous que le code contient une déclaration pour rétablir les valeurs d'origine. (par exemple op <- par(mfrow=c(1,2)) ...some code... par(op) )
  • testez votre code dans une nouvelle session R vide pour vous assurer que le code est exécutable. Les gens devraient pouvoir copier-coller vos données et votre code dans la console et obtenir exactement la même chose que vous.

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), vous devez également fournir des numéros de version pour ceux-ci et, si possible, les informations nécessaires sur la configuration.

Si vous utilisez R in R Studio avec rstudioapi::versionInfo() peut être utile de signaler votre version de RStudio.

Si vous rencontrez un problème avec un package spécifique, vous pouvez fournir la version du package en donnant la sortie de packageVersion("name of the package") .

(Voici mon conseil de Comment écrire un exemple reproductible . J’ai essayé de le rendre court mais doux)

Comment écrire un exemple reproductible.

Si vous fournissez un exemple reproductible, vous êtes plus susceptible d’avoir de l’aide avec votre problème R. Un exemple reproductible permet à quelqu’un d’autre de recréer votre problème en copiant et en collant simplement le code R.

Vous devez inclure quatre éléments pour rendre votre exemple reproductible: les packages requirejs, 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 Stack Overflow consiste à utiliser dput() pour générer le code R afin de le recréer. Par exemple, pour recréer le jeu de données mtcars dans R, procédez comme suit:

    1. Exécuter dput(mtcars) dans R
    2. Copier la sortie
    3. Dans mon script reproductible, tapez mtcars <- 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 vos noms de variables sont concis, mais informatifs

    • utiliser des commentaires pour indiquer où se trouve 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.

  • Inclure la sortie de sessionInfo() dans un commentaire dans votre code. Cela résume votre environnement R et facilite la vérification de l’utilisation d’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 email, envisagez de le mettre sur Gist github . Cela donnera à votre code une belle coloration syntaxique, et vous n’avez pas à vous soucier de ce que le système de messagerie pourrait égrener.

Personnellement, je préfère les “one” liners. Quelque chose dans ce sens:

 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 structure de données devrait imiter l’idée du problème de l’écrivain et non la structure exacte exacte. J'apprécie vraiment quand les variables n'écrasent pas mes propres variables ou que Dieu m'interdit, fonctions (comme df ).

Alternativement, on pourrait couper quelques coins et pointer vers un dataset préexistant, quelque chose comme:

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

N'oubliez pas de mentionner tous les forfaits spéciaux que vous pourriez utiliser.

Si vous essayez de démontrer quelque chose sur des objects plus gros, vous pouvez essayer

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

Si vous travaillez avec des données spatiales via le package raster , vous pouvez générer des données aléatoires. Vous trouverez beaucoup d'exemples dans la vignette du paquet, mais voici un petit pépite.

 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 vous avez besoin d'un object spatial tel qu'il est implémenté dans sp , vous pouvez obtenir des jeux de données via des fichiers externes (comme le fichier de formes ESRI) dans des packages "spatiaux" (voir la vue Spatial dans les vues des tâches).

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

Inspiré par ce post même, j’utilise maintenant une fonction pratique
reproduce() lorsque je dois publier sur StackOverflow.


INSTRUCTIONS RAPIDES

Si myData est le nom de votre object à reproduire, exécutez la commande suivante dans R:

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

Détails:

Cette fonction est un wrapper intelligent pour dput et effectue les opérations suivantes:

  • échantillonne automatiquement un grand dataset (basé sur la taille et la classe. La taille de l’échantillon peut être ajustée)
  • crée une sortie de sortie
  • vous permet de spécifier les colonnes à exporter
  • ajoute à l’avant de l’ objName <- ... pour qu'il puisse être facilement copié + collé, mais ...
  • Si vous travaillez sur un mac, la sortie est automatiquement copiée dans le presse-papier, de sorte que vous pouvez simplement l'exécuter et coller ensuite à votre question.

La source est disponible ici:

  • Github - pubR / reproduire.R

Exemple:

 # 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 est environ 100 x 102. Je veux échantillonner 10 lignes et quelques colonnes spécifiques

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

Donne la sortie suivante:

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

Notez également que l'intégralité de la sortie est une belle et unique longue ligne, et non un grand paragraphe de lignes découpées. Cela facilite la lecture sur les messages de questions SO et facilite également la copie + le collage.


Mise à jour octobre 2013:

Vous pouvez maintenant spécifier le nombre de lignes de sortie de texte à prendre (c.-à-d. Ce que vous allez coller dans StackOverflow). Utilisez l'argument lines.out=n pour cela. Exemple:

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

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

Voici un bon guide:

http://www.r-bloggers.com/three-tips-for-posting-good-questions-to-r-help-and-stack-overflow/

Mais le plus important est le suivant: assurez-vous de créer un petit 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 pouvez créer un petit jeu de données ou utiliser uniquement les 10 premières lignes.

MODIFIER:

Assurez-vous également que vous avez identifié le problème vous-même. L’exemple ne doit pas être un script R complet avec “En ligne 200, il y a une erreur”. Si vous utilisez les outils de débogage dans R (j’aime le browser() ) et que google, vous devriez être capable d’identifier vraiment le problème et reproduire un exemple sortingvial dans lequel la même chose se passe mal.

La liste de diffusion R-help comprend 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:

Exemples: Parfois, il est utile de fournir un petit exemple que quelqu’un peut réellement exécuter. Par exemple:

Si j’ai une masortingce x comme suit:

  > x <- matrix(1:8, nrow=4, ncol=2, dimnames=list(c("A","B","C","D"), c("x","y")) > x xy A 1 5 B 2 6 C 3 7 D 4 8 > 

comment puis-je le transformer en un dataframe avec 8 lignes et trois colonnes nommées “row”, “col” et “value”, qui ont les noms de dimension comme valeurs de “row” et “col”, comme ceci:

  > x.df row col value 1 A x 1 


(À qui la réponse pourrait être:

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

)

Le mot petit est particulièrement important. Vous devriez 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: Le code est plus facile à lire que le code. Utilisez un guide de style .

Depuis la version R.2.14 (je suppose), vous pouvez directement transmettre votre représentation de texte à read.table:

 df <- read.table(header=T, 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 ") 

Parfois, le problème n’est pas reproductible avec un fichier plus petit, aussi difficile soit-il, et non 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 ne reproduisaient pas le problème, car il exclut certaines hypothèses).

  • Publier les données sur le Web quelque part et fournir une URL peut être nécessaire.
  • Si les données ne peuvent pas être diffusées au grand public mais peuvent être partagées, vous pouvez proposer de les envoyer par courrier électronique aux parties intéressées (bien que cela réduise le nombre de personnes qui se donneront la peine de travailler). dessus).
  • Je n’ai pas réellement vu cela, car les gens qui ne peuvent pas publier leurs données sont sensibles à le publier sous une forme quelconque, mais il semblerait plausible que dans certains cas, on puisse toujours publier des données suffisamment anonymisées, brouillées ou corrompues en quelque sorte.

Si vous ne pouvez pas faire l’un ou l’autre de ces cas, vous devrez probablement engager un consultant pour résoudre votre problème …

edit : Deux questions SO utiles pour l’anonymisation / le brouillage:

  • Comment créer des exemples de données à partir de données privées (en remplaçant les noms de variables et les niveaux par des espaces réservés non informatifs)?
  • Étant donné un ensemble de nombres aléatoires tirés d’une dissortingbution univariée continue, trouvez la dissortingbution

Les réponses à ce jour sont évidemment excellentes pour la partie reproductibilité. Cela vise simplement à préciser qu’un exemple reproductible ne peut et ne doit pas être le seul composant d’une question. N’oubliez pas d’expliquer à quoi vous voulez ressembler et quels sont les contours de votre problème, et pas seulement comment vous avez essayé d’y arriver. Le code ne suffit pas vous avez besoin de mots aussi.

Voici un exemple reproductible de ce qu’il faut éviter (tiré d’un exemple réel, les noms ont été modifiés pour protéger les innocents):


Voici des exemples de données et une partie de la fonction avec laquelle j’ai des problèmes.

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

Comment puis-je atteindre cet objective ?


Pour créer rapidement un dput de vos données, vous pouvez simplement copier (un morceau de) les données dans votre presse-papiers et exécuter les opérations suivantes dans R:

pour les données dans Excel:

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

pour les données dans un fichier txt:

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

Si nécessaire, vous pouvez modifier le sep . Cela ne fonctionnera que si vos données sont dans le presse-papiers bien sûr.

J’ai un moyen très simple et efficace de créer un exemple R qui n’a pas été mentionné ci-dessus. Vous pouvez définir votre structure en premier. Par exemple,

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

Lorsque vous exécutez la commande 'fix', vous obtiendrez cette boîte de dialogue

Vous pouvez ensuite saisir vos données manuellement. Ceci est efficace pour les petits exemples plutôt que pour les grands.

Des lignes direcsortingces:


Votre principal objective dans la conception de vos questions devrait être de faciliter au maximum la compréhension et la reproduction de votre problème par les lecteurs. Faire cela:

  1. Fournir des données d’entrée
  2. Fournir les résultats attendus
  3. Expliquez votre problème succinctement
    • si vous avez plus de 20 lignes de texte + code, vous pouvez probablement revenir en arrière et simplifier
    • simplifiez votre code autant que possible tout en préservant le problème / l’erreur

Cela demande du travail, mais cela semble être un compromis puisque vous demandez aux autres de faire le travail pour vous.

Fournir des données:


Jeux de données intégrés

La meilleure option consiste de loin à s’appuyer sur des jeux de données intégrés. Cela rend très facile pour les autres de travailler 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)

Reportez-vous à cette section sur la façon de trouver des jeux de données adaptés à votre problème.

Si vous parvenez à reformuler votre problème pour utiliser les jeux de données intégrés, vous aurez beaucoup plus de chances d’obtenir de bonnes réponses (et des commentaires positifs).

Données auto-générées

Si votre problème est très spécifique à un type de données non représenté dans les ensembles de données existants, indiquez le code R qui génère le plus petit jeu de données possible sur lequel votre problème se manifeste. Par exemple

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

Maintenant, quelqu'un qui tente 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 object de données en code R (par exemple, dput(myData) ). Je dis comme un "dernier recours" parce que la sortie de dput est souvent assez lourde, ennuyeuse à copier-coller et obscurcit le rest de votre question.

Fournir les résultats attendus:


Quelqu'un a dit un jour:

Une image de la production attendue vaut 1000 mots

- une personne très sage

Si vous pouvez append quelque chose comme "Je m'attendais à obtenir ce résultat":

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

À votre question, les gens sont beaucoup plus susceptibles de comprendre rapidement ce que vous essayez de faire. Si le résultat escompté est volumineux et peu maniable, vous n'avez probablement pas réfléchi à la manière de simplifier votre problème (voir ci-après).

Expliquez succinctement votre problème


La principale chose à faire est de simplifier votre problème autant que possible avant de poser votre question. Re-cadrer le problème pour travailler avec les jeux de données intégrés aidera beaucoup à cet égard. Vous constaterez également souvent que simplement en passant par le processus de simplification, vous répondrez à votre propre problème.

Voici quelques exemples de bonnes questions:

  • avec jeu de données intégré
  • avec des données générées par l' utilisateur

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 dataset simple 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 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 soit mise en évidence; Ceci est ici uniquement pour que je puisse y faire un lien dans les commentaires aux questions de débutant.

Le code reproductible est la clé pour obtenir de l’aide. Cependant, nombreux sont les utilisateurs qui 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 des données originales collectées pour les utiliser dans un document de recherche. Pour une raison quelconque, j’ai pensé que ce serait bien d’avoir une fonction pratique pour “déformer” mes données avant de les coller publiquement. La fonction d’ anonymize du paquetage SciencesPo est très idiote, mais pour moi cela fonctionne très bien avec la fonction dput .

 install.packages("SciencesPo") dt <- data.frame( Z = sample(LETTERS,10), X = sample(1:10), Y = sample(c("yes", "no"), 10, replace = TRUE) ) > dt ZXY 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 

Alors je l’anonymise:

 > anonymize(dt) ZXY 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 

On peut aussi vouloir échantillonner quelques variables au lieu des données entières avant d’appliquer l’anonymisation et la commande dput.

  # sample two variables without replacement > anonymize(sample.df(dt,5,vars=c("Y","X"))) YX 1 a1 -0.4 2 a1 0.6 3 a2 -2.4 4 a1 -1.4 5 a2 3.6 

Souvent, vous avez besoin de données pour un exemple, cependant, vous ne souhaitez pas publier vos données exactes. Pour utiliser certaines données.frame dans une bibliothèque établie, utilisez la commande data pour l’importer.

par exemple,

 data(mtcars) 

et ensuite faire le problème

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

Si vous avez un dataset volumineux qui ne peut pas être facilement placé dans le script à l’aide de dput() , publiez vos données sur pastebin et chargez-les à l’aide de read.table :

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

Inspiré par @Henrik .

Je développe le paquet wakefield pour répondre à ce besoin de partager rapidement des données reproductibles. Parfois, le dput fonctionne bien pour des ensembles de données plus petits, mais beaucoup de problèmes sont beaucoup plus importants.

Sur:

wakefield permet à l’utilisateur de partager un code minimal pour reproduire des données. L’utilisateur définit n (nombre de lignes) et spécifie un nombre quelconque de fonctions variables prédéfinies (il y en a actuellement 70) qui reproduisent des données réelles (par exemple, le sexe, l’âge, le revenu, etc.).

Installation:

Actuellement (2015-06-11), Wakefield est un paquet GitHub mais ira finalement à CRAN après la rédaction des tests unitaires. Pour installer rapidement, utilisez:

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

Exemple:

Voici un exemple:

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

Cela produit:

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

Si vous souhaitez rendre une ou plusieurs variables factor reproductibles avec dput(head(mydata)) ) dans vos données, envisagez d’y append des droplevels , afin que les niveaux de facteurs non présents dans le jeu de données minimisé soient non inclus dans votre sortie dput , afin de rendre l’exemple minimal :

 dput(droplevels(head(mydata))) 

Je me demande si un lien http://www.r-fiddle.org/ pourrait être un moyen très efficace de partager un problème. Il reçoit un identifiant unique et on pourrait même envisager de l’intégrer dans SO.

http://www.r-fiddle.org/#/help

Veuillez ne pas coller les sorties de votre console comme ceci:

 If I have a masortingx x as follows: > x <- matrix(1:8, nrow=4, ncol=2, dimnames=list(c("A","B","C","D"), c("x","y"))) > x xy 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 masortingx x as follows: x <- matrix(1:8, nrow=4, ncol=2, dimnames=list(c("A","B","C","D"), c("x","y"))) x # xy #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.

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 masortingx 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 atsortingbutes 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. atsortingbutes(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)) 

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.

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.

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

 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