Wie man ein großartiges reproduzierbares R-Beispiel macht

May 11 2011

Wenn Sie die Leistung mit Kollegen besprechen, unterrichten, einen Fehlerbericht senden oder nach Anleitungen zu Mailinglisten und hier zum Stapelüberlauf suchen, wird häufig ein reproduzierbares Beispiel gefragt und ist immer hilfreich.

Was sind Ihre Tipps, um ein hervorragendes Beispiel zu erstellen? Wie füge ich Datenstrukturen aus r in ein Textformat ein? Welche weiteren Informationen sollten Sie angeben?

Gibt es noch andere Tricks zusätzlich zur Verwendung dput(), dump()oder structure()? Wann sollten Sie library()oder require()Aussagen einschließen ? Welche reservierten Worte sollte man vermeiden, zusätzlich zu c, df, dataetc.?

Wie macht man ein gutes reproduzierbares Beispiel?

Antworten

1756 JorisMeys May 11 2011 at 18:40

Ein minimal reproduzierbares Beispiel besteht aus folgenden Elementen:

  • Ein minimaler Datensatz, der zur Demonstration des Problems erforderlich ist
  • Der minimale ausführbare Code, der zum Reproduzieren des Fehlers erforderlich ist und für das angegebene Dataset ausgeführt werden kann
  • die erforderlichen Informationen zu den verwendeten Paketen, der R-Version und dem System, auf dem es ausgeführt wird.
  • bei zufälligen Prozessen ein Keim (gesetzt von set.seed()) für die Reproduzierbarkeit 1

Beispiele für gute Beispiele mit minimaler Reproduzierbarkeit finden Sie in den Hilfedateien der von Ihnen verwendeten Funktion. Im Allgemeinen erfüllt der gesamte dort angegebene Code die Anforderungen eines minimal reproduzierbaren Beispiels: Daten werden bereitgestellt, minimaler Code wird bereitgestellt und alles kann ausgeführt werden. Schauen Sie sich auch Fragen zu Stack Overflow mit vielen positiven Stimmen an.

Erstellen eines minimalen Datensatzes

In den meisten Fällen kann dies einfach durch Bereitstellen eines Vektor- / Datenrahmens mit einigen Werten erfolgen. Oder Sie können eines der integrierten Datasets verwenden, die in den meisten Paketen enthalten sind.
Eine umfassende Liste der integrierten Datensätze finden Sie mit library(help = "datasets"). Zu jedem Datensatz gibt es eine kurze Beschreibung. Weitere Informationen erhalten Sie beispielsweise, ?mtcarswenn 'mtcars' einer der Datensätze in der Liste ist. Andere Pakete enthalten möglicherweise zusätzliche Datensätze.

Das Erstellen eines Vektors ist einfach. Manchmal ist es notwendig, etwas Zufälligkeit hinzuzufügen, und es gibt eine ganze Reihe von Funktionen, um dies zu erreichen. sample()kann einen Vektor randomisieren oder einen zufälligen Vektor mit nur wenigen Werten angeben. lettersist ein nützlicher Vektor, der das Alphabet enthält. Dies kann zur Herstellung von Faktoren verwendet werden.

Einige Beispiele:

  • Zufallswerte: x <- rnorm(10)für Normalverteilung, x <- runif(10)für Gleichverteilung, ...
  • eine Permutation einiger Werte: x <- sample(1:10)für Vektor 1:10 in zufälliger Reihenfolge.
  • ein zufälliger Faktor: x <- sample(letters[1:4], 20, replace = TRUE)

Für Matrizen kann man matrix()zB verwenden:

matrix(1:10, ncol = 2)

Das Erstellen von Datenrahmen kann mit erfolgen data.frame(). Man sollte darauf achten, die Einträge im Datenrahmen zu benennen und nicht zu kompliziert zu machen.

Ein Beispiel :

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

Für einige Fragen können bestimmte Formate benötigt werden. Für diese kann man eine der vorgesehenen Verwendung as.someTypeFunktionen: as.factor, as.Date, as.xts, ... Diese in Kombination mit dem Vektor und / oder Datenrahmen Tricks.

Kopieren Sie Ihre Daten

Wenn Sie einige Daten, die zu schwierig sein würde , mit diesen Tipps zu konstruieren, dann können Sie immer einen Teil Ihrer ursprünglichen Daten machen, verwenden head(), subset()oder die Indizes. Verwenden Sie dann dput(), um uns etwas zu geben, das sofort in R eingefügt werden kann:

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

Wenn Ihr Datenrahmen einen Faktor mit vielen Ebenen enthält, kann die dputAusgabe unhandlich sein, da weiterhin alle möglichen Faktorstufen aufgelistet werden, auch wenn sie nicht in der Teilmenge Ihrer Daten vorhanden sind. Um dieses Problem zu lösen, können Sie die droplevels()Funktion verwenden. Beachten Sie unten, wie Arten ein Faktor mit nur einer Ebene sind:

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

Bei der Verwendung dputmöchten Sie möglicherweise auch nur relevante Spalten einschließen:

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

Eine weitere Einschränkung dputist, dass es nicht für verschlüsselte data.tableObjekte oder für gruppierte tbl_df(Klassen grouped_df) von funktioniert dplyr. In diesen Fällen können Sie vor der Freigabe wieder in einen regulären Datenrahmen konvertieren dput(as.data.frame(my_data)).

Im schlimmsten Fall können Sie eine Textdarstellung angeben, die mit den folgenden textParametern eingelesen werden kann 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)

Minimalen Code produzieren

Dies sollte der einfache Teil sein, ist es aber oft nicht. Was Sie nicht tun sollten, ist:

  • Fügen Sie alle Arten von Datenkonvertierungen hinzu. Stellen Sie sicher, dass die bereitgestellten Daten bereits im richtigen Format vorliegen (es sei denn, dies ist natürlich das Problem).
  • Kopieren und Einfügen einer ganzen Funktion / eines Codeabschnitts, der einen Fehler ausgibt. Versuchen Sie zunächst herauszufinden, welche Zeilen genau zum Fehler führen. Meistens werden Sie selbst herausfinden, wo das Problem liegt.

Was Sie tun sollten, ist:

  • fügen Sie hinzu, welche Pakete verwendet werden sollen, wenn Sie welche verwenden (using library())
  • Wenn Sie Verbindungen öffnen oder Dateien erstellen, fügen Sie Code hinzu, um sie zu schließen, oder löschen Sie die Dateien (mit unlink())
  • Wenn Sie Optionen ändern, stellen Sie sicher, dass der Code eine Anweisung enthält, um sie auf die ursprünglichen zurückzusetzen. (zB op <- par(mfrow=c(1,2)) ...some code... par(op))
  • Testen Sie Ihren Code in einer neuen, leeren R-Sitzung, um sicherzustellen, dass der Code ausführbar ist. Die Benutzer sollten in der Lage sein, Ihre Daten und Ihren Code einfach in die Konsole zu kopieren und einzufügen und genau das zu erhalten, was Sie haben.

Geben Sie zusätzliche Informationen

In den meisten Fällen reichen nur die R-Version und das Betriebssystem aus. Wenn Konflikte mit Paketen auftreten, sessionInfo()kann es wirklich hilfreich sein , die Ausgabe von zu geben. Wenn Sie über Verbindungen zu anderen Anwendungen sprechen (sei es über ODBC oder irgendetwas anderes), sollten Sie auch Versionsnummern für diese und, wenn möglich, auch die erforderlichen Informationen zum Setup angeben.

Wenn Sie R in R Studio mit rstudioapi::versionInfo()ausführen , kann es hilfreich sein, Ihre RStudio-Version zu melden.

Wenn Sie ein Problem mit einem bestimmten Paket haben, können Sie die Version des Pakets bereitstellen, indem Sie die Ausgabe von angeben packageVersion("name of the package").


1 Hinweis: Die Ausgabe von set.seed()unterscheidet sich zwischen R> 3.6.0 und früheren Versionen. Geben Sie an, welche R-Version Sie für den Zufallsprozess verwendet haben, und wundern Sie sich nicht, wenn Sie bei der Beantwortung alter Fragen leicht unterschiedliche Ergebnisse erhalten. Um in solchen Fällen das gleiche Ergebnis zu erzielen, können Sie die RNGversion()-funktion vorher verwenden set.seed()(zB :) RNGversion("3.5.2").

595 hadley May 11 2011 at 20:57

(Hier ist mein Rat von Wie man ein reproduzierbares Beispiel schreibt . Ich habe versucht, es kurz, aber süß zu machen.)

Wie schreibe ich ein reproduzierbares Beispiel?

Es ist am wahrscheinlichsten, dass Sie bei Ihrem R-Problem gute Hilfe erhalten, wenn Sie ein reproduzierbares Beispiel angeben. Ein reproduzierbares Beispiel ermöglicht es einer anderen Person, Ihr Problem durch einfaches Kopieren und Einfügen von R-Code neu zu erstellen.

Es gibt vier Dinge, die Sie einschließen müssen, um Ihr Beispiel reproduzierbar zu machen: erforderliche Pakete, Daten, Code und eine Beschreibung Ihrer R-Umgebung.

  • Pakete sollten oben im Skript geladen werden, damit Sie leicht erkennen können, welche im Beispiel benötigt werden.

  • Der einfachste Weg, Daten in eine E-Mail- oder Stapelüberlauffrage aufzunehmen, besteht darin dput(), den R-Code zu generieren, um ihn neu zu erstellen. Um beispielsweise das mtcarsDataset in R neu zu erstellen , führen Sie die folgenden Schritte aus:

    1. Laufen Sie dput(mtcars)in R.
    2. Kopieren Sie die Ausgabe
    3. Geben Sie in mein reproduzierbares Skript ein und mtcars <-fügen Sie es ein.
  • Nehmen Sie sich etwas Zeit, um sicherzustellen, dass Ihr Code für andere leicht lesbar ist:

    • Stellen Sie sicher, dass Sie Leerzeichen verwendet haben und Ihre Variablennamen präzise, ​​aber informativ sind

    • Verwenden Sie Kommentare, um anzugeben, wo Ihr Problem liegt

    • Geben Sie Ihr Bestes, um alles zu entfernen, was nicht mit dem Problem zusammenhängt.
      Je kürzer Ihr Code ist, desto leichter ist es zu verstehen.

  • Fügen Sie die Ausgabe von sessionInfo()in einen Kommentar in Ihren Code ein. Dies fasst Ihre R-Umgebung zusammen und erleichtert die Überprüfung, ob Sie ein veraltetes Paket verwenden.

Sie können überprüfen, ob Sie tatsächlich ein reproduzierbares Beispiel erstellt haben, indem Sie eine neue R-Sitzung starten und Ihr Skript einfügen.

Bevor Sie Ihren gesamten Code in eine E-Mail einfügen , sollten Sie ihn auf Gist Github ablegen . Dadurch wird Ihrem Code eine schöne Syntaxhervorhebung verliehen, und Sie müssen sich keine Sorgen machen, dass das E-Mail-System etwas beschädigt.

307 RomanLuštrik May 11 2011 at 18:22

Persönlich bevorzuge ich "Ein" -Liner. Etwas in der Richtung:

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)

Die Datenstruktur sollte die Idee des Autorenproblems imitieren und nicht die genaue wörtliche Struktur. Ich weiß es wirklich zu schätzen, wenn Variablen meine eigenen Variablen nicht überschreiben oder Gott verbietet, Funktionen (wie df).

Alternativ könnte man ein paar Ecken abschneiden und auf einen bereits vorhandenen Datensatz verweisen, etwa:

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

Vergessen Sie nicht, spezielle Pakete zu erwähnen, die Sie möglicherweise verwenden.

Wenn Sie versuchen, etwas auf größeren Objekten zu demonstrieren, können Sie es versuchen

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

Wenn Sie über das rasterPaket mit räumlichen Daten arbeiten , können Sie zufällige Daten generieren. Viele Beispiele finden Sie in der Paketvignette, aber hier ist ein kleines Nugget.

library(raster)
r1 <- r2 <- r3 <- raster(nrow=10, ncol=10)
values(r1) <- runif(ncell(r1))
values(r2) <- runif(ncell(r2))
values(r3) <- runif(ncell(r3))
s <- stack(r1, r2, r3)

Wenn Sie ein räumliches Objekt benötigen, wie es in implementiert ist sp, können Sie einige Datensätze über externe Dateien (wie ESRI-Shapefile) in "räumlichen" Paketen abrufen (siehe Raumansicht in Aufgabenansichten).

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

Inspiriert von diesem Beitrag verwende ich jetzt eine praktische Funktion,
reproduce(<mydata>)wenn ich in StackOverflow posten muss.


SCHNELLE ANWEISUNGEN

Wenn myDatader Name Ihres zu reproduzierenden Objekts lautet, führen Sie in R Folgendes aus:

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

reproduce(myData)

Einzelheiten:

Diese Funktion ist ein intelligenter Wrapper für dputund führt Folgendes aus:

  • tastet automatisch einen großen Datensatz ab (basierend auf Größe und Klasse. Die Stichprobengröße kann angepasst werden).
  • erstellt eine dputAusgabe
  • Hier können Sie angeben, welche Spalten exportiert werden sollen
  • wird an die Vorderseite angehängt, objName <- ...damit es leicht kopiert und eingefügt werden kann, aber ...
  • Wenn Sie auf einem Mac arbeiten, wird die Ausgabe automatisch in die Zwischenablage kopiert, sodass Sie sie einfach ausführen und dann in Ihre Frage einfügen können.

Die Quelle finden Sie hier:

  • Github - pubR / reproduce.R

Beispiel:

# 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 ist ungefähr 100 x 102. Ich möchte 10 Zeilen und einige spezifische Spalten abtasten

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

Gibt die folgende Ausgabe:

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

Beachten Sie auch, dass sich die gesamte Ausgabe in einer schönen, langen Zeile befindet, nicht in einem hohen Absatz aus zerhackten Zeilen. Dies erleichtert das Lesen von SO-Fragen und das Kopieren und Einfügen.


Update Okt 2013:

Sie können jetzt angeben, wie viele Zeilen Textausgabe benötigt werden (dh was Sie in StackOverflow einfügen). Verwenden Sie dazu das lines.out=nArgument. Beispiel:

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

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

Hier ist eine gute Anleitung .

Der wichtigste Punkt ist: Stellen Sie einfach sicher, dass Sie einen kleinen Code erstellen, den wir ausführen können, um das Problem zu ermitteln . Eine nützliche Funktion hierfür ist dput(), aber wenn Sie sehr große Datenmengen haben, möchten Sie möglicherweise einen kleinen Beispieldatensatz erstellen oder nur die ersten 10 Zeilen oder so verwenden.

BEARBEITEN:

Stellen Sie außerdem sicher, dass Sie selbst festgestellt haben, wo das Problem liegt. Das Beispiel sollte kein vollständiges R-Skript mit "In Zeile 200 liegt ein Fehler vor" sein. Wenn Sie die Debugging-Tools in R (ich liebe browser()) und Google verwenden, sollten Sie in der Lage sein, das Problem wirklich zu identifizieren und ein triviales Beispiel zu reproduzieren, in dem dasselbe schief geht.

167 RichieCotton May 11 2011 at 20:17

Die R-Help-Mailingliste enthält einen Posting-Leitfaden, der sowohl das Stellen als auch das Beantworten von Fragen umfasst, einschließlich eines Beispiels zum Generieren von Daten:

Beispiele: Manchmal ist es hilfreich, ein kleines Beispiel anzugeben, das jemand tatsächlich ausführen kann. Zum Beispiel:

Wenn ich eine Matrix x wie folgt habe:

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

Wie kann ich daraus einen Datenrahmen mit 8 Zeilen und drei Spalten mit den Namen 'row', 'col' und 'value' machen, deren Dimensionsnamen die Werte von 'row' und 'col' haben?

  > x.df
     row col value
  1    A   x      1

...
(auf die die Antwort lauten könnte:

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

)

Das Wort klein ist besonders wichtig. Sie sollten ein minimal reproduzierbares Beispiel anstreben , was bedeutet, dass die Daten und der Code so einfach wie möglich sein sollten, um das Problem zu erklären.

BEARBEITEN: Hübscher Code ist leichter zu lesen als hässlicher Code. Verwenden Sie einen Styleguide .

164 Paolo Jun 29 2012 at 15:32

Seit R.2.14 (ich denke) können Sie Ihre Datentextdarstellung direkt an Folgendes weitergeben 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

Manchmal ist das Problem mit einem kleineren Datenelement wirklich nicht reproduzierbar, egal wie sehr Sie es versuchen, und es tritt nicht mit synthetischen Daten auf (obwohl es nützlich ist zu zeigen, wie Sie synthetische Datensätze erstellt haben, die das Problem nicht reproduziert haben, weil es schließt einige Hypothesen aus).

  • Möglicherweise müssen Sie die Daten irgendwo im Internet veröffentlichen und eine URL angeben.
  • Wenn die Daten nicht öffentlich zugänglich gemacht werden können, sondern überhaupt weitergegeben werden können, können Sie möglicherweise anbieten, sie per E-Mail an interessierte Parteien zu senden (obwohl dies die Anzahl der Personen verringert, die sich die Mühe machen, zu arbeiten darauf).
  • Ich habe dies nicht wirklich gesehen, weil Leute, die ihre Daten nicht veröffentlichen können, sensibel dafür sind, sie in irgendeiner Form freizugeben, aber es erscheint plausibel, dass man in einigen Fällen immer noch Daten veröffentlichen könnte, wenn sie ausreichend anonymisiert / verschlüsselt / leicht beschädigt wären irgendwie.

Wenn Sie beides nicht können, müssen Sie wahrscheinlich einen Berater beauftragen, um Ihr Problem zu lösen ...

edit : Zwei nützliche SO-Fragen zur Anonymisierung / Verschlüsselung:

  • Wie erstelle ich einen Beispieldatensatz aus privaten Daten (Ersetzen von Variablennamen und -ebenen durch nicht informative Platzhalter)?
  • Finden Sie die Verteilung anhand einer Reihe von Zufallszahlen, die aus einer kontinuierlichen univariaten Verteilung gezogen wurden
136 AriB.Friedman Jul 09 2012 at 22:41

Die bisherigen Antworten sind offensichtlich großartig für den Teil der Reproduzierbarkeit. Dies dient lediglich der Klarstellung, dass ein reproduzierbares Beispiel nicht der alleinige Bestandteil einer Frage sein kann und sollte. Vergessen Sie nicht zu erklären, wie es aussehen soll und welche Konturen Ihr Problem aufweist, und nicht nur, wie Sie bisher versucht haben, dorthin zu gelangen. Code ist nicht genug; Du brauchst auch Worte.

Hier ist ein reproduzierbares Beispiel dafür, was zu vermeiden ist (anhand eines realen Beispiels wurden die Namen geändert, um die Unschuldigen zu schützen):


Das Folgende sind Beispieldaten und ein Teil der Funktion, mit denen ich Probleme habe.

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

Wie kann ich das erreichen?


124 jasmine_007 Feb 20 2014 at 16:11

Ich habe eine sehr einfache und effiziente Möglichkeit, ein R-Beispiel zu erstellen, das oben nicht erwähnt wurde. Sie können zunächst Ihre Struktur definieren. Zum Beispiel,

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

>fix(mydata)

Dann können Sie Ihre Daten manuell eingeben. Dies ist eher für kleinere als für große Beispiele effizient.

119 JT85 Apr 10 2013 at 21:51

Um schnell dputDaten zu erstellen, können Sie die Daten einfach in Ihre Zwischenablage kopieren und in R Folgendes ausführen:

für Daten in Excel:

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

für Daten in einer txt-Datei:

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

Sie können die sepin letzterem bei Bedarf ändern . Dies funktioniert natürlich nur, wenn sich Ihre Daten in der Zwischenablage befinden.

118 BrodieG Feb 12 2015 at 22:24

Richtlinien:


Ihr Hauptziel bei der Erstellung Ihrer Fragen sollte es sein, den Lesern das Verständnis und die Reproduktion Ihres Problems auf ihren Systemen so einfach wie möglich zu machen. Um dies zu tun:

  1. Geben Sie Eingabedaten ein
  2. Geben Sie die erwartete Ausgabe an
  3. Erklären Sie Ihr Problem kurz und bündig
    • Wenn Sie mehr als 20 Zeilen Text + Code haben, können Sie wahrscheinlich zurückgehen und vereinfachen
    • Vereinfachen Sie Ihren Code so weit wie möglich, während Sie das Problem / den Fehler beibehalten

Dies erfordert zwar einige Arbeit, scheint jedoch ein fairer Kompromiss zu sein, da Sie andere bitten, für Sie zu arbeiten.

Daten bereitstellen:


Eingebaute Datensätze

Die mit Abstand beste Option besteht darin, sich auf integrierte Datensätze zu verlassen. Dies macht es für andere sehr einfach, an Ihrem Problem zu arbeiten. Geben Sie data()an der Eingabeaufforderung R ein, um zu sehen, welche Daten für Sie verfügbar sind. Einige klassische Beispiele:

  • iris
  • mtcars
  • ggplot2::diamonds (externes Paket, aber fast jeder hat es)

Überprüfen Sie die integrierten Datensätze, um einen für Ihr Problem geeigneten zu finden.

Wenn Sie Ihr Problem umformulieren können, um die integrierten Datensätze zu verwenden, erhalten Sie mit größerer Wahrscheinlichkeit gute Antworten (und positive Stimmen).

Selbst generierte Daten

Wenn Ihr Problem sehr spezifisch für einen Datentyp ist, der nicht in den vorhandenen Datensätzen enthalten ist, geben Sie den R-Code an, der den kleinstmöglichen Datensatz generiert, in dem sich Ihr Problem manifestiert. Zum Beispiel

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

Jetzt kann jemand, der versucht, meine Frage zu beantworten, diese beiden Zeilen kopieren / einfügen und sofort mit der Arbeit an dem Problem beginnen.

dput

Als letzten Ausweg können Sie dputein Datenobjekt in R-Code umwandeln (z dput(myData). B. ). Ich sage als "letzter Ausweg", weil die Ausgabe von dputoft ziemlich unhandlich ist, beim Kopieren und Einfügen ärgerlich ist und den Rest Ihrer Frage verdeckt.

Erwartete Ausgabe bereitstellen:


Jemand hat einmal gesagt:

Ein Bild der erwarteten Ausgabe sagt mehr als 1000 Worte

- eine sehr weise Person

Wenn Sie etwas wie "Ich habe erwartet, dass dieses Ergebnis erzielt wird" hinzufügen können:

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

Auf Ihre Frage hin ist es viel wahrscheinlicher, dass die Leute schnell verstehen, was Sie versuchen zu tun. Wenn Ihr erwartetes Ergebnis groß und unhandlich ist, haben Sie wahrscheinlich nicht genug darüber nachgedacht, wie Sie Ihr Problem vereinfachen können (siehe weiter unten).

Erklären Sie Ihr Problem kurz und bündig


Die Hauptsache ist, Ihr Problem so weit wie möglich zu vereinfachen, bevor Sie Ihre Frage stellen. Die Neuformulierung des Problems, um mit den integrierten Datensätzen zu arbeiten, wird in dieser Hinsicht sehr hilfreich sein. Sie werden auch oft feststellen, dass Sie Ihr eigenes Problem beantworten, indem Sie den Vereinfachungsprozess durchlaufen.

Hier einige Beispiele für gute Fragen:

  • mit eingebautem Datensatz
  • mit benutzergenerierten Daten

In beiden Fällen liegen die Probleme des Benutzers mit ziemlicher Sicherheit nicht in den einfachen Beispielen, die sie liefern. Vielmehr abstrahierten sie die Natur ihres Problems und wandten es auf einen einfachen Datensatz an, um ihre Frage zu stellen.

Warum noch eine Antwort auf diese Frage?


Diese Antwort konzentriert sich auf das, was ich für die beste Vorgehensweise halte: Verwenden Sie integrierte Datensätze und geben Sie das, was Sie als Ergebnis erwarten, in minimaler Form an. Die wichtigsten Antworten konzentrieren sich auf andere Aspekte. Ich erwarte nicht, dass diese Antwort an Bedeutung gewinnt. Dies ist nur hier, damit ich in Kommentaren zu Fragen von Neulingen darauf verlinken kann.

113 daniel Nov 27 2014 at 09:02

Reproduzierbarer Code ist der Schlüssel, um Hilfe zu erhalten. Es gibt jedoch viele Benutzer, die skeptisch sind, auch nur einen Teil ihrer Daten einzufügen. Zum Beispiel könnten sie mit sensiblen Daten oder mit Originaldaten arbeiten, die zur Verwendung in einem Forschungsbericht gesammelt wurden. Aus irgendeinem Grund dachte ich, es wäre schön, eine praktische Funktion zum "Verformen" meiner Daten zu haben, bevor sie öffentlich eingefügt werden. Die anonymizeFunktion aus dem Paket SciencesPoist sehr albern, aber für mich funktioniert es gut mit der dputFunktion.

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

Dann anonymisiere ich es:

> 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

Möglicherweise möchten Sie auch einige Variablen anstelle der gesamten Daten abtasten, bevor Sie den Befehl Anonymisierung und dput anwenden.

    # 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

Oft benötigen Sie einige Daten für ein Beispiel, möchten jedoch nicht Ihre genauen Daten veröffentlichen. Um einen vorhandenen data.frame in einer eingerichteten Bibliothek zu verwenden, importieren Sie ihn mit dem Befehl data.

z.B,

data(mtcars)

und dann das Problem machen

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

Wenn Sie einen großen Datensatz haben, der nicht einfach mit dem Skript erstellt werden kann dput(), senden Sie Ihre Daten an den Pastebin und laden Sie sie mit read.table:

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

Inspiriert von @Henrik .

90 TylerRinker Jun 11 2015 at 20:57

Ich entwickle das Wakefield- Paket , um diesem Bedürfnis nach schnellem dputAustausch reproduzierbarer Daten gerecht zu werden. Manchmal funktioniert es gut für kleinere Datensätze, aber viele der Probleme, mit denen wir uns befassen, sind viel größer. Das Teilen eines so großen Datensatzes über dputist unpraktisch.

Über:

Mit wakefield kann der Benutzer nur minimalen Code zur Reproduktion von Daten freigeben . Der Benutzer legtn(Anzahl der Zeilen) fest und gibt eine beliebige Anzahl von voreingestellten Variablenfunktionen an (derzeit sind es 70), die reale Daten nachahmen (z. B. Geschlecht, Alter, Einkommen usw.).

Installation:

Derzeit (2015.06.11), wakefield ist ein Paket GitHub aber zu CRAN geht schließlich nach Unit - Tests geschrieben werden. Verwenden Sie zur schnellen Installation Folgendes:

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

Beispiel:

Hier ist ein Beispiel:

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

Dies erzeugt:

    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

Wenn Sie ein oder mehr factorVariable (n) in Ihren Daten , die Sie mit reproduzierbarer machen wollen dput(head(mydata)), sollten Sie erwägen , droplevelsum es, so dass das Niveau der Faktoren , die nicht in der minimierten Datensatz nicht in Ihrem enthalten ist , dputausgegeben, um zu Machen Sie das Beispiel minimal :

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

Ich frage mich, ob ein http://old.r-fiddle.org/Link könnte eine sehr nette Möglichkeit sein, ein Problem zu teilen. Es erhält eine eindeutige ID wie und man könnte sogar darüber nachdenken, es in SO einzubetten.

49 user2100721 Jul 22 2016 at 17:01

Bitte fügen Sie Ihre Konsolenausgaben nicht wie folgt ein:

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

Wir können es nicht direkt kopieren und einfügen.

Um Fragen und Antworten richtig reproduzierbar zu machen, versuchen Sie, +& zu entfernen, >bevor Sie sie veröffentlichen, und geben Sie folgende #Ausgaben und Kommentare ein:

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

Eine weitere Sache, wenn Sie eine Funktion aus einem bestimmten Paket verwendet haben, erwähnen Sie diese Bibliothek.

34 andrii Aug 19 2017 at 02:02

Sie können dies mit reprex tun .

Wie mt1022 feststellte , ist "... ein gutes Paket zur Herstellung eines minimalen, reproduzierbaren Beispiels " reprex " von tidyverse ".

Laut Tidyverse :

Das Ziel von "reprex" ist es, Ihren problematischen Code so zu verpacken, dass andere ihn ausführen und Ihren Schmerz spüren können.

Ein Beispiel finden Sie auf der tidyverse -Website.

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

Ich denke, dies ist der einfachste Weg , um ein reproduzierbares Beispiel zu erstellen.

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

Abgesehen von allen oben genannten Antworten, die ich sehr interessant fand, konnte es manchmal sehr einfach sein, wie hier diskutiert wird: - WIE MAN EIN MINDESTPRODUZIERBARES BEISPIEL MACHT, UM HILFE BEI ​​R ZU ERHALTEN

Es gibt viele Möglichkeiten, einen Zufallsvektor zu erstellen. Erstellen Sie einen 100-Zahlen-Vektor mit Zufallswerten in R, gerundet auf 2 Dezimalstellen oder einer Zufallsmatrix in R.

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

Beachten Sie, dass es manchmal aus verschiedenen Gründen wie der Dimension usw. sehr schwierig ist, bestimmte Daten gemeinsam zu nutzen. Alle oben genannten Antworten sind jedoch großartig und sehr wichtig zu denken und zu verwenden, wenn ein Beispiel für reproduzierbare Daten erstellt werden soll. Beachten Sie jedoch, dass es gut ist, dem Datenbeispiel einige Informationen hinzuzufügen, um Daten so repräsentativ wie das Original zu machen (falls das OP die Originaldaten nicht gemeinsam nutzen kann) (wenn wir die Daten mydf1 nennen).

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

Darüber hinaus sollte man den Typ, die Länge und die Attribute von Daten kennen, bei denen es sich um Datenstrukturen handeln kann

#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

Hier sind einige meiner Vorschläge:

  • Versuchen Sie, Standard-R-Datasets zu verwenden
  • Wenn Sie über einen eigenen Datensatz verfügen, fügen Sie diesen hinzu dput, damit andere Ihnen leichter helfen können
  • Verwenden Sie install.package()nicht, es sei denn, es ist wirklich notwendig, die Leute werden verstehen, wenn Sie nur requireoder verwendenlibrary
  • Versuche prägnant zu sein,

    • Haben Sie einen Datensatz
    • Versuchen Sie, die Ausgabe, die Sie benötigen, so einfach wie möglich zu beschreiben
    • Mach es selbst, bevor du die Frage stellst
  • Es ist einfach, ein Bild hochzuladen. Laden Sie also Diagramme hoch, wenn Sie welche haben
  • Fügen Sie auch eventuelle Fehler hinzu

All dies ist Teil eines reproduzierbaren Beispiels.

18 dank Apr 05 2017 at 04:08

Es ist eine gute Idee, Funktionen aus dem testthatPaket zu verwenden, um zu zeigen, was Sie erwarten. Auf diese Weise können andere Personen Ihren Code ändern, bis er fehlerfrei ausgeführt wird. Dies entlastet diejenigen, die Ihnen helfen möchten, da sie Ihre Textbeschreibung nicht entschlüsseln müssen. Zum Beispiel

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

ist klarer als "Ich denke, x würde 1,23 für y gleich oder größer als 10 und 3,21 sonst ergeben, aber ich habe kein Ergebnis erhalten". Selbst in diesem albernen Beispiel denke ich, dass der Code klarer ist als die Wörter. Durch testthatdie Verwendung kann sich Ihr Helfer auf den Code konzentrieren, was Zeit spart, und bietet ihm die Möglichkeit, zu erkennen, dass er Ihr Problem gelöst hat, bevor er es veröffentlicht