webentwicklung-frage-antwort-db.com.de

Wie man ein gutes R reproduzierbares Beispiel macht

Wenn Sie mit Kollegen über Leistung diskutieren, unterrichten, einen Fehlerbericht senden oder nach Anleitungen für Mailinglisten und hier für Stack Overflow suchen, wird häufig ein reproduzierbares Beispiel gefragt und ist immer hilfreich.

Was sind Ihre Tipps, um ein hervorragendes Beispiel zu schaffen? Wie fügt man Datenstrukturen aus r in ein Textformat ein? Welche weiteren Informationen sollten Sie hinzufügen?

Gibt es andere Tricks zusätzlich zur Verwendung von dput(), dump() oder structure()? Wann sollten Sie library()- oder require() -Anweisungen einfügen? Welche reservierten Wörter sollte man zusätzlich zu c, df, data usw. vermeiden?

Wie macht man ein gutes r reproduzierbares Beispiel?

2474
Andrie

Ein minimal reproduzierbares Beispiel besteht aus folgenden Elementen:

  • ein minimaler Datensatz, der zur Reproduktion des Fehlers erforderlich ist
  • der minimale ausführbare Code, der zum Reproduzieren des Fehlers erforderlich ist und auf dem angegebenen Datensatz ausgeführt werden kann.
  • die erforderlichen Informationen zu den verwendeten Paketen, der R-Version und dem System, auf dem sie ausgeführt werden.
  • bei zufälligen Prozessen ein Startwert (gesetzt durch set.seed()) für die Reproduzierbarkeit

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

Ein Blick auf die Beispiele in den Hilfedateien der verwendeten Funktionen ist oft hilfreich. Im Allgemeinen erfüllt der dort angegebene Code die Anforderungen eines minimal reproduzierbaren Beispiels: Daten werden bereitgestellt, minimaler Code wird bereitgestellt und alles ist ausführbar.

Erstellen eines minimalen Datensatzes

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

Einen Vektor zu erstellen ist einfach. Manchmal muss etwas Zufälliges hinzugefügt werden, und dafür gibt es eine ganze Reihe von Funktionen. sample() kann einen Vektor randomisieren oder einen zufälligen Vektor mit nur wenigen Werten angeben. letters ist ein nützlicher Vektor, der das Alphabet enthält. Dies kann zur Herstellung von Faktoren verwendet werden.

Einige Beispiele:

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

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

matrix(1:10, ncol = 2)

Datenrahmen können mit data.frame() erstellt werden. 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)
)

Bei einigen Fragen können spezielle Formate erforderlich sein. Für diese kann man jede der bereitgestellten as.someType -Funktionen verwenden: as.factor, as.Date, as.xts, ... Diese in Kombination mit den Vektor- und/oder Datenrahmen-Tricks .

Kopieren Sie Ihre Daten

Wenn Sie Daten haben, die sich mit diesen Tipps nur schwer konstruieren lassen, können Sie immer eine Teilmenge Ihrer ursprünglichen Daten erstellen, z. B. mit head(), subset() oder den Indizes. Dann benutze zB. dput() um uns etwas zu geben, das sofort in R eingegeben werden kann:

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

Wenn Ihr Datenrahmen einen Faktor mit vielen Ebenen hat, kann die Ausgabe von dput unhandlich sein, da immer noch alle möglichen Faktorebenen aufgelistet werden, auch wenn sie nicht in der Teilmenge Ihrer Daten vorhanden sind. Um dieses Problem zu beheben, können Sie die Funktion droplevels() verwenden. Beachten Sie unten, wie Arten ein Faktor mit nur einer Ebene sind:

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

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

Im schlimmsten Fall können Sie eine Textdarstellung angeben, die mit dem Parameter text von read.table eingelesen werden kann:

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)

Minimaler Code wird erzeugt

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, das ist natürlich das Problem).
  • kopieren-Einfügen einer ganzen Funktion/eines Codeblocks, der einen Fehler verursacht. Versuchen Sie zunächst herauszufinden, welche Zeilen genau zu dem Fehler führen. Meistens werden Sie selbst herausfinden, wo das Problem liegt.

Was Sie tun sollten, ist:

  • füge hinzu, welche Pakete verwendet werden sollen, wenn du welche verwendest (benutze 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, mit der Sie die ursprünglichen Optionen wiederherstellen können. (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 Leute sollten in der Lage sein, einfach Ihre Daten und Ihren Code in die Konsole einzufügen und genau das zu bekommen, 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, kann die Ausgabe von sessionInfo() wirklich hilfreich sein. Wenn es um Verbindungen zu anderen Anwendungen geht (sei es über ODBC oder irgendetwas anderes), sollte man auch Versionsnummern für diese und wenn möglich auch die notwendigen Informationen zum Setup bereitstellen.

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

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

1635
Joris Meys

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

Wie schreibe ich ein reproduzierbares Beispiel.

Am ehesten erhalten Sie bei Ihrem R-Problem Hilfe, 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 wiederherzustellen.

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 das Beispiel benötigt.

  • Der einfachste Weg, Daten in eine E-Mail- oder Stapelüberlauf-Frage aufzunehmen , ist die Verwendung von dput(), um den R-Code für die Neuerstellung zu generieren. Um beispielsweise das mtcars -Dataset in R neu zu erstellen, führen Sie die folgenden Schritte aus:

    1. Führen Sie dput(mtcars) in R aus
    2. Kopieren Sie die Ausgabe
    3. Geben Sie in mein reproduzierbares Skript mtcars <- ein und fügen Sie es ein.
  • Verbringen Sie ein wenig Zeit damit, 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 einfacher ist es zu verstehen.

  • Fügen Sie die Ausgabe von sessionInfo() in einen Kommentar in Ihrem 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 setzen. Es gibt Ihrem Code eine schöne Hervorhebung der Syntax und Sie müssen sich keine Sorgen machen, dass das E-Mail-System etwas kaputt macht.

572
hadley

Persönlich bevorzuge ich "one" Liner. Etwas in die richtige 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 Schreibproblems nachahmen und nicht die genaue wörtliche Struktur. Ich weiß es wirklich zu schätzen, wenn Variablen meine eigenen Variablen nicht überschreiben oder Funktionen (wie df) verbieten.

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 anzugeben, die Sie möglicherweise verwenden.

Wenn Sie versuchen, etwas an 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 mit Geodaten über das Paket raster arbeiten, können Sie einige 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 sp implementiert ist, können Sie einige Datensätze über externe Dateien (z. B. ESRI-Shapefile) in "räumlichen" Paketen abrufen (siehe die räumliche Ansicht in Task-Ansichten).

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

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


SCHNELLE ANWEISUNGEN

Wenn myData der Name Ihres zu reproduzierenden Objekts ist, 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 dput und führt folgende Aktionen aus:

  • tastet automatisch einen großen Datensatz ab (basierend auf Größe und Klasse. Die Stichprobengröße kann angepasst werden)
  • erzeugt eine dput Ausgabe
  • hier können Sie angeben , welche Spalten exportiert werden sollen
  • hängt es vorne an 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 ist hier verfügbar:


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 bestimmte Spalten abtasten

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

Gibt die folgende Ausgabe aus:

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 einzigen, langen Zeile befindet, nicht in einem hohen Absatz aus zerlegten Zeilen. Dies erleichtert das Lesen von SO Fragenbeiträgen und das Kopieren und Einfügen.


Update Oktober 2013:

Sie können jetzt festlegen, wie viele Zeilen Text ausgegeben werden sollen (dh was Sie in StackOverflow einfügen). Verwenden Sie dazu das Argument lines.out=n. Beispiel:

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

    ==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==
270
Ricardo Saporta

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 erkennen . Eine nützliche Funktion hierfür ist dput(). Wenn Sie jedoch sehr große Datenmengen haben, möchten Sie möglicherweise einen kleinen Beispieldatensatz erstellen oder nur die ersten 10 Zeilen oder so verwenden.

EDIT:

Stellen Sie außerdem sicher, dass Sie selbst identifiziert 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 einfaches Beispiel zu reproduzieren, in dem dasselbe schief geht.

189
Sacha Epskamp

Die R-Help-Mailingliste enthält eine Posting-Anleitung , die sowohl das Stellen als auch das Beantworten von Fragen abdeckt, einschließlich eines Beispiels für das Generieren von Daten:

Beispiele: Manchmal ist es hilfreich, ein kleines Beispiel anzugeben, das tatsächlich von jemandem ausgeführt werden 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 namens 'row', 'col' und 'value' machen, deren Dimensionsnamen die Werte von 'row' und 'col' sind?

  > x.df
     row col value
  1    A   x      1

...
(Worauf 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 minimales 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 ein Formatvorlage .

162
Richie Cotton

Seit R.2.14 können Sie Ihre Datentextdarstellung direkt an read.table übergeben:

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

Manchmal ist das Problem mit einer kleineren Datenmenge wirklich nicht reproduzierbar, unabhängig davon, wie sehr Sie es versuchen, und tritt auch bei synthetischen Daten nicht auf (obwohl es nützlich ist, zu zeigen, wie Sie synthetische Datensätze erstellt haben, die reproduziere das Problem nicht , da es einige Hypothesen ausschließt).

  • Das Posten der Daten im Internet und die Angabe einer URL kann erforderlich sein.
  • Wenn die Daten nicht für die Öffentlichkeit freigegeben werden können, aber überhaupt geteilt 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 das noch nicht gesehen, weil Leute, die ihre Daten nicht veröffentlichen können, sensibel sind, sie in irgendeiner Form freizugeben, aber es erscheint plausibel, dass in einigen Fällen noch Daten veröffentlicht werden könnten, wenn sie ausreichend anonymisiert/verschlüsselt/leicht verfälscht 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:

142
Ben Bolker

Die bisherigen Antworten sind offensichtlich großartig für den Teil der Reproduzierbarkeit. Dies soll lediglich klarstellen, dass ein reproduzierbares Beispiel nicht der einzige Bestandteil einer Frage sein kann und sollte. Vergessen Sie nicht zu erklären, wie es aussehen soll und wie sich Ihr Problem entwickelt, 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 Sie vermeiden sollten (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 der ich Probleme habe.

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

Wie kann ich das erreichen?


132
Ari B. Friedman

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)

When you execute 'fix' command, you will get this pop-up box

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

120
jasmine_007

Um schnell ein dput Ihrer Daten zu erstellen, können Sie die Daten einfach (teilweise) in Ihre Zwischenablage kopieren und Folgendes in R 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 bei Bedarf das sep in letzterem ändern. Dies funktioniert natürlich nur, wenn sich Ihre Daten in der Zwischenablage befinden.

117
JT85

Richtlinien:


Ihr Hauptziel bei der Bearbeitung Ihrer Fragen sollte es sein, es den Lesern so einfach wie möglich zu machen, Ihr Problem auf ihren Systemen zu verstehen und zu reproduzieren. Um dies zu tun:

  1. Geben Sie Eingabedaten ein
  2. Geben Sie die erwartete Ausgabe an
  3. Erklären Sie kurz Ihr Problem
    • 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 das Problem/der Fehler erhalten bleibt

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

Daten bereitstellen:


Eingebaute Datensätze

Die beste Option bei weitem ist, sich auf integrierte Datasets zu verlassen. Dies macht es für andere sehr einfach, an Ihrem Problem zu arbeiten. Geben Sie an der Eingabeaufforderung R data() 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)

In diesem SO QA erfahren Sie, wie Sie für Ihr Problem geeignete Datensätze finden.

Wenn Sie in der Lage sind, Ihr Problem neu zu formulieren, um die integrierten Datensätze zu verwenden, erhalten Sie mit größerer Wahrscheinlichkeit gute Antworten (und positive Bewertungen).

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 kleinsten möglichen Datensatz generiert dass sich dein problem an 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 Bearbeitung des Problems beginnen.

dput

Als letzte Möglichkeit können Sie dput verwenden, um ein Datenobjekt in R-Code umzuwandeln (z. B. dput(myData)). Ich sage als "letzter Ausweg", weil die Ausgabe von dput oft ziemlich unhandlich ist, das Kopieren und Einfügen stört und den Rest Ihrer Frage verdeckt.

Erwartete Ausgabe bereitstellen:


Jemand sagte einmal:

Ein Bild der erwarteten Ausgabe sagt mehr als 1000 Worte

- eine sehr weise Person

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

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

in Bezug auf Ihre Frage ist es viel wahrscheinlicher, dass die Leute schnell verstehen, was Sie versuchen. 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. Das Problem mit den eingebauten Datensätzen neu zu gestalten, wird in dieser Hinsicht sehr hilfreich sein. Sie werden auch oft feststellen, dass Sie Ihr eigenes Problem lösen, wenn Sie den Vereinfachungsprozess durchlaufen.

Hier einige Beispiele für gute Fragen:

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

Warum noch eine Antwort auf diese Frage?


Diese Antwort konzentriert sich auf das, was meiner Meinung nach die beste Vorgehensweise ist: Verwenden Sie integrierte Datensätze und stellen Sie das, was Sie erwarten, in minimaler Form zur Verfügung. Die wichtigsten Antworten konzentrieren sich auf andere Aspekte. Ich erwarte nicht, dass diese Antwort zu irgendeiner Berühmtheit aufsteigt. Dies ist hier nur, damit ich in Kommentaren zu neuen Fragen darauf verlinken kann.

112
BrodieG

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. Beispielsweise könnten sie mit vertraulichen 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 anonymize -Funktion aus dem Paket SciencesPo ist sehr albern, aber für mich funktioniert es gut mit der dput -Funktion.

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 Anonymisierungs- und Dput-Befehl 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
110
daniel

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 vorhandenen Bibliothek zu verwenden, importieren Sie ihn mit dem Befehl data.

z.B.,

data(mtcars)

und dann mach das problem

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

Wenn Sie einen großen Datensatz haben, der mit dput() nicht einfach in das Skript eingefügt werden kann, senden Sie Ihre Daten an Pastebin und laden Sie sie mit read.table:

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

Inspiriert von @ Henrik .

90
TMS

Ich entwickle das wakefield Paket , um dieses Bedürfnis schnell zu teilen, anzusprechen Reproduzierbare Daten, manchmal dput funktionieren gut für kleinere Datenmengen, aber viele der Probleme, mit denen wir zu tun haben, sind viel größer. Die gemeinsame Nutzung einer so großen Datenmenge über dput ist unpraktisch.

Über:

Mit wakefield kann der Benutzer minimalen Code für die Wiedergabe von Daten freigeben. Der Benutzer legt n (Anzahl der Zeilen) fest und gibt eine beliebige Anzahl von voreingestellten Variablenfunktionen an (derzeit gibt es 70), die reale Daten imitieren (z. B. Geschlecht, Alter, Einkommen usw.).

Installation:

Derzeit (11.06.2015) ist wakefield ein GitHub Paket, wird aber irgendwann nach dem Schreiben von Komponententests an CRAN gesendet. Verwenden Sie zur schnellen Installation:

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
.. ...   ... ...    ...      ... ...    ...   ...
87
Tyler Rinker

Wenn Ihre Daten eine oder mehrere factor Variable (n) enthalten, die Sie mit dput(head(mydata)) reproduzieren möchten, sollten Sie droplevels hinzufügen, damit die Ebenen der Faktoren nicht vorhanden sind im minimierten Datensatz sind nicht in Ihrer dput Ausgabe enthalten, um das Beispiel zu machen minimal:

dput(droplevels(head(mydata)))
70

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

61
CMichael

Bitte fügen Sie Ihre Konsolenausgaben nicht so 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.

Versuchen Sie, + & > vor dem Posten zu entfernen und # für Ausgaben und Kommentare wie diese zu setzen, um die Reproduzierbarkeit von Fragen und Antworten zu gewährleisten:

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

Wenn Sie eine Funktion aus einem bestimmten Paket verwendet haben, erwähnen Sie diese Bibliothek.

44
user2100721

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

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

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

Beachten Sie, dass es manchmal aus verschiedenen Gründen, wie z. B. der Dimension usw., sehr schwierig ist, bestimmte Daten gemeinsam zu nutzen. Alle oben genannten Antworten sind jedoch großartig und sehr wichtig, wenn Sie ein Beispiel für reproduzierbare Daten erstellen möchten. Beachten Sie jedoch, dass, um Daten so repräsentativ wie das Original zu machen (falls das OP die Originaldaten nicht teilen kann), einige Informationen mit dem Datenbeispiel hinzugefügt werden sollten (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, die Datenstrukturen sein können

#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))
30
user5947301

Sie können dies mit reprex tun.

Wie mt1022 vermerkt "... ist eine gute Verpackung zur Herstellung eines minimalen, reproduzierbaren Beispiels " reprex " von tidyverse ".

Nach 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 Website tidyverse .

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

Ich denke das ist der einfachste Weg ein reproduzierbares Beispiel zu erstellen.

30
andrii

Hier sind einige meiner Vorschläge:

  • Versuchen Sie, Standard-R-Datasets zu verwenden
  • Wenn Sie über einen eigenen Datensatz verfügen, fügen Sie diese in dput ein, damit andere Ihnen leichter helfen können
  • Verwenden Sie install.package() nur, wenn dies wirklich notwendig ist. Die Leute werden verstehen, wenn Sie require oder library verwenden.
  • Versuchen Sie, prägnant zu sein,

    • Habe einen Datensatz
    • Versuchen Sie, die Ausgabe so einfach wie möglich zu beschreiben
    • Tun Sie es selbst, bevor Sie die Frage stellen
  • Es ist einfach, ein Bild hochzuladen. Laden Sie also Plots hoch, wenn Sie welche haben
  • Schließen Sie auch alle Fehler ein, die Sie möglicherweise haben

All dies ist Teil eines reproduzierbaren Beispiels.

26
TheRimalaya

Es ist eine gute Idee, Funktionen aus dem Paket testthat zu verwenden, um zu zeigen, was Sie erwarten. Auf diese Weise können andere Benutzer Ihren Code so lange ä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äre 1,23 für y gleich oder größer als 10 und 3,21 sonst, aber ich habe kein Ergebnis". Sogar in diesem albernen Beispiel denke ich, dass der Code klarer als die Wörter ist. Durch die Verwendung von testthat kann sich Ihr Helfer auf den Code konzentrieren, was Zeit spart und es ermöglicht, dass er weiß, dass er Ihr Problem gelöst hat, bevor er es veröffentlicht

16
dank