Jak zrobić świetny powtarzalny przykład R.

May 11 2011

Podczas omawiania wydajności ze współpracownikami, nauczania, wysyłania raportów o błędach lub wyszukiwania wskazówek dotyczących list mailingowych, a tutaj w witrynie Stack Overflow, często zadawane są powtarzalne przykłady, które zawsze są pomocne.

Jakie masz wskazówki, jak stworzyć doskonały przykład? Jak wkleić struktury danych z r w formacie tekstowym? Jakie inne informacje powinieneś dołączyć?

Czy istnieją inne sztuczki oprócz korzystania dput(), dump()albo structure()? Kiedy należy dołączyć oświadczenia library()lub require()? Który zastrzeżone słów należy unikać, w uzupełnieniu do c, df, data, itd.?

W jaki sposób można zrobić wielki r powtarzalne przykład?

Odpowiedzi

1756 JorisMeys May 11 2011 at 18:40

Minimalny powtarzalne przykład składa się z następujących elementów:

  • minimalny zbiór danych, niezbędny do zademonstrowania problemu
  • minimalny możliwy do wykonania kod niezbędny do odtworzenia błędu, który można uruchomić na danym zbiorze danych
  • niezbędne informacje o używanych pakietach, wersji R i systemie, na którym jest uruchamiany.
  • w przypadku procesów losowych ziarno (ustalone przez set.seed()) dla odtwarzalności 1

Przykłady dobrych, minimalnych, powtarzalnych przykładów można znaleźć w plikach pomocy używanej funkcji. Ogólnie rzecz biorąc, cały podany tam kod spełnia wymagania minimalnego powtarzalnego przykładu: dane są dostarczane, minimalny kod jest dostarczany i wszystko jest możliwe do uruchomienia. Spójrz także na pytania dotyczące przepełnienia stosu z wieloma pozytywnymi opiniami.

Tworzenie minimalnego zbioru danych

W większości przypadków można to łatwo zrobić, po prostu dostarczając ramkę wektora / danych z pewnymi wartościami. Możesz też użyć jednego z wbudowanych zestawów danych, które są dostarczane z większością pakietów.
Pełną listę wbudowanych zestawów danych można zobaczyć za pomocą library(help = "datasets"). Każdy zbiór danych ma krótki opis i można uzyskać więcej informacji, na przykład ?mtcarsgdzie „mtcars” jest jednym ze zbiorów danych na liście. Inne pakiety mogą zawierać dodatkowe zbiory danych.

Tworzenie wektora jest łatwe. Czasami trzeba dodać do tego trochę losowości i jest do tego cała liczba funkcji. sample()może losować wektor lub dać losowy wektor zawierający tylko kilka wartości. lettersjest użytecznym wektorem zawierającym alfabet. Można to wykorzystać do tworzenia czynników.

Kilka przykładów:

  • wartości losowe: x <- rnorm(10)dla rozkładu normalnego, x <- runif(10)dla rozkładu równomiernego, ...
  • permutacja niektórych wartości: x <- sample(1:10)dla wektora 1:10 w kolejności losowej.
  • czynnik losowy: x <- sample(letters[1:4], 20, replace = TRUE)

Do matryc można użyć matrix()np .:

matrix(1:10, ncol = 2)

Tworzenie ramek danych można wykonać za pomocą data.frame(). Należy zwrócić uwagę na nazwanie wpisów w ramce danych i nie komplikowanie jej zbytnio.

Przykład :

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

W przypadku niektórych pytań mogą być potrzebne określone formaty. Dla nich, można użyć dowolnego z określonych as.someTypefunkcji: as.factor, as.Date, as.xts, ... To w połączeniu z wektorem i / lub ramka danych sztuczek.

Skopiuj swoje dane

Jeśli masz jakieś dane, które byłyby zbyt trudne do skonstruowania za pomocą tych wskazówek, to zawsze można zrobić podzbiór oryginalnego danych, używając head(), subset()lub indeksy. Następnie użyj, dput()aby dać nam coś, co można natychmiast wstawić do R:

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

Jeśli ramka danych ma czynnik z wieloma poziomami, dane dputwyjściowe mogą być nieporęczne, ponieważ nadal będą zawierać listę wszystkich możliwych poziomów czynników, nawet jeśli nie są one obecne w podzbiorze danych. Aby rozwiązać ten problem, możesz użyć droplevels()funkcji. Zauważ poniżej, jak gatunek jest czynnikiem tylko na jednym poziomie:

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

Podczas używania dputmożesz również chcieć uwzględnić tylko odpowiednie kolumny:

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

Innym zastrzeżeniem dputjest to, że nie będzie działać dla data.tableobiektów z kluczem lub zgrupowanych tbl_df(klas grouped_df) z dplyr. W takich przypadkach można przekształcić z powrotem do regularnego ramki danych przed udostępnianie dput(as.data.frame(my_data)).

W najgorszym przypadku możesz podać reprezentację tekstową, którą można odczytać za pomocą textparametru 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)

Tworzenie minimalnego kodu

To powinna być łatwa część, ale często tak nie jest. To, czego nie powinieneś robić, to:

  • dodać wszelkiego rodzaju konwersje danych. Upewnij się, że podane dane są już w odpowiednim formacie (chyba że jest to oczywiście problem)
  • skopiuj i wklej całą funkcję / fragment kodu, który powoduje błąd. Najpierw spróbuj zlokalizować dokładnie, które wiersze powodują błąd. Najczęściej sam się przekonasz, na czym polega problem.

Co powinieneś zrobić, to:

  • dodaj, które pakiety powinny być używane, jeśli używasz (używając library())
  • jeśli otwierasz połączenia lub tworzysz pliki, dodaj kod, aby je zamknąć lub usunąć pliki (za pomocą unlink())
  • jeśli zmienisz opcje, upewnij się, że kod zawiera instrukcję, aby przywrócić je z powrotem do oryginalnych. (np. op <- par(mfrow=c(1,2)) ...some code... par(op))
  • test uruchom kod w nowej, pustej sesji języka R, aby upewnić się, że kod można uruchomić. Ludzie powinni móc po prostu skopiować i wkleić twoje dane i kod w konsoli i uzyskać dokładnie to samo, co masz.

Podaj dodatkowe informacje

W większości przypadków wystarczy wersja R i system operacyjny. Kiedy pojawiają się konflikty z pakietami, podanie wyniku sessionInfo()może naprawdę pomóc. Mówiąc o połączeniach z innymi aplikacjami (czy to przez ODBC, czy cokolwiek innego), należy również podać numery wersji dla tych aplikacji, a jeśli to możliwe, również niezbędne informacje o konfiguracji.

Jeśli używasz R w R Studio, użycie rstudioapi::versionInfo()może być pomocne w zgłoszeniu wersji RStudio.

Jeśli masz problem z określonym pakietem, możesz chcieć podać wersję pakietu, podając wynik polecenia packageVersion("name of the package").


1 Uwaga: wynik set.seed()różni się między R> 3.6.0 a poprzednimi wersjami. Określ, której wersji R użyłeś w losowym procesie, i nie zdziw się, jeśli uzyskasz nieco inne wyniki podczas odpowiedzi na stare pytania. Aby uzyskać ten sam wynik w takich przypadkach, możesz użyć funkcji RNGversion()przed set.seed()(np RNGversion("3.5.2"). :) .

595 hadley May 11 2011 at 20:57

(Oto moja rada z artykułu Jak napisać powtarzalny przykład . Starałem się, aby był krótki, ale słodki)

Jak napisać powtarzalny przykład.

Najprawdopodobniej uzyskasz dobrą pomoc w rozwiązaniu problemu z językiem R, jeśli podasz powtarzalny przykład. Odtwarzalny przykład pozwala komuś innemu odtworzyć Twój problem, po prostu kopiując i wklejając kod R.

Aby Twój przykład był odtwarzalny, musisz uwzględnić cztery rzeczy: wymagane pakiety, dane, kod i opis środowiska języka R.

  • Pakiety powinny być ładowane w górnej części skryptu, aby łatwo było zobaczyć, które z nich są potrzebne w przykładzie.

  • Najłatwiejszym sposobem uwzględnienia danych w wiadomości e-mail lub w pytaniu dotyczącym przepełnienia stosu jest dput()wygenerowanie kodu R w celu jego odtworzenia. Na przykład, aby odtworzyć mtcarszestaw danych w R, wykonałbym następujące kroki:

    1. Uruchom dput(mtcars)w R.
    2. Skopiuj wynik
    3. W moim odtwarzalnym skrypcie wpisz, mtcars <-a następnie wklej.
  • Poświęć trochę czasu, aby upewnić się, że Twój kod jest łatwy do odczytania dla innych:

    • upewnij się, że użyłeś spacji, a nazwy zmiennych są zwięzłe, ale zawierają informacje

    • użyj komentarzy, aby wskazać, gdzie leży twój problem

    • postaraj się usunąć wszystko, co nie jest związane z problemem.
      Im krótszy jest twój kod, tym łatwiej jest go zrozumieć.

  • Uwzględnij wyniki sessionInfo()w komentarzu w swoim kodzie. To podsumowuje twoje środowisko R i ułatwia sprawdzenie, czy używasz nieaktualnego pakietu.

Możesz sprawdzić, czy rzeczywiście utworzyłeś powtarzalny przykład, uruchamiając nową sesję języka R i wklejając skrypt.

Przed umieszczeniem całego kodu w e-mailu rozważ umieszczenie go na Gist github . Dzięki temu Twój kod będzie dobrze podświetlony i nie musisz się martwić, że cokolwiek zostanie zniekształcone przez system poczty elektronicznej.

307 RomanLuštrik May 11 2011 at 18:22

Osobiście wolę „jeden” wkład. Coś w stylu:

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)

Struktura danych powinna naśladować ideę problemu pisarza, a nie dokładną strukturę dosłowną. Naprawdę doceniam to, gdy zmienne nie zastępują moich własnych zmiennych ani nie daj Boże, funkcje (takie jak df).

Alternatywnie można pójść na kilka rogów i wskazać na istniejący zestaw danych, na przykład:

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

Nie zapomnij wspomnieć o specjalnych pakietach, których możesz używać.

Jeśli próbujesz zademonstrować coś na większych obiektach, możesz spróbować

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

Jeśli pracujesz z danymi przestrzennymi za pośrednictwem rasterpakietu, możesz wygenerować losowe dane. Wiele przykładów można znaleźć w winiecie pakietu, ale tutaj jest mały samorodek.

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)

Jeśli potrzebujesz jakiegoś obiektu przestrzennego zaimplementowanego w programie sp, możesz pobrać niektóre zestawy danych za pośrednictwem plików zewnętrznych (takich jak plik kształtu ESRI) w pakietach „przestrzennych” (zobacz widok przestrzenny w widokach zadań).

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

Zainspirowany tym postem, teraz używam przydatnej funkcji,
reproduce(<mydata>)gdy muszę publikować w StackOverflow.


SZYBKA INSTRUKCJA

Jeśli myDatajest to nazwa obiektu do odtworzenia, uruchom w R:

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

reproduce(myData)

Detale:

Ta funkcja jest inteligentnym opakowaniem dputi wykonuje następujące czynności:

  • automatycznie próbkuje duży zestaw danych (na podstawie rozmiaru i klasy. Wielkość próbki można dostosować)
  • tworzy dputwynik
  • umożliwia określenie, które kolumny mają zostać wyeksportowane
  • dołącza się do przodu, objName <- ...dzięki czemu można go łatwo skopiować + wkleić, ale ...
  • Jeśli pracujesz na komputerze Mac, dane wyjściowe są automatycznie kopiowane do schowka, dzięki czemu możesz je po prostu uruchomić, a następnie wkleić do pytania.

Źródło jest dostępne tutaj:

  • Github - pubR / reproduce.R

Przykład:

# 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 wynosi około 100 x 102. Chcę pobrać próbkę z 10 wierszy i kilku określonych kolumn

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

Daje następujący wynik:

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

Zauważ również, że całość wyniku jest w ładnej pojedynczej, długiej linii, a nie w wysokim akapicie z pociętymi wierszami. Ułatwia to czytanie postów z pytaniami SO, a także ułatwia kopiowanie i wklejanie.


Aktualizacja październik 2013:

Możesz teraz określić, ile wierszy tekstu zajmie wyjście (tj. Co wkleisz do StackOverflow). Użyj lines.out=nargumentu do tego. Przykład:

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

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

Oto dobry przewodnik .

Najważniejsze jest to: po prostu upewnij się, że utworzyłeś mały fragment kodu, który możemy uruchomić, aby zobaczyć, na czym polega problem . Przydatna jest do tego funkcja dput(), ale jeśli masz bardzo duże dane, możesz chcieć utworzyć mały przykładowy zestaw danych lub użyć tylko pierwszych 10 wierszy.

EDYTOWAĆ:

Upewnij się również, że sam zidentyfikowałeś problem. Przykładem nie powinien być cały skrypt R z komunikatem „W linii 200 jest błąd”. Jeśli używasz narzędzi do debugowania w R (uwielbiam browser()) i Google, powinieneś być w stanie naprawdę zidentyfikować problem i odtworzyć trywialny przykład, w którym to samo poszło nie tak.

167 RichieCotton May 11 2011 at 20:17

Lista mailingowa R-help zawiera przewodnik po publikowaniu, który obejmuje zarówno zadawanie pytań, jak i odpowiadanie na nie, w tym przykład generowania danych:

Przykłady: Czasami warto podać mały przykład, który ktoś może faktycznie uruchomić. Na przykład:

Jeśli mam macierz x w następujący sposób:

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

jak mogę przekształcić go w ramkę danych z 8 wierszami i trzema kolumnami o nazwach „row”, „col” i „value”, które mają nazwy wymiarów jako wartości „row” i „col”, na przykład:

  > x.df
     row col value
  1    A   x      1

...
(na co odpowiedź może brzmieć:

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

)

Szczególnie ważne jest słowo małe . Powinieneś dążyć do uzyskania minimalnego powtarzalnego przykładu, co oznacza, że ​​dane i kod powinny być tak proste, jak to tylko możliwe, aby wyjaśnić problem.

EDYCJA: Ładny kod jest łatwiejszy do odczytania niż brzydki kod. Użyj przewodnika stylistycznego .

164 Paolo Jun 29 2012 at 15:32

Od wersji R.2.14 (chyba) możesz przesyłać reprezentację tekstu danych bezpośrednio do 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

Czasami problem naprawdę nie jest odtwarzalny z mniejszą ilością danych, bez względu na to, jak bardzo się starasz, i nie występuje w przypadku danych syntetycznych (chociaż warto pokazać, jak utworzyłeś syntetyczne zestawy danych, które nie odtworzyły problemu, ponieważ wyklucza to pewne hipotezy).

  • Konieczne może być umieszczenie danych w Internecie i podanie adresu URL.
  • Jeśli danych nie można udostępnić publicznie, ale w ogóle można by je udostępnić, możesz zaoferować przesłanie ich pocztą e-mail zainteresowanym stronom (chociaż zmniejszy to liczbę osób, które będą kłopotać się pracą na tym).
  • W rzeczywistości nie widziałem tego, ponieważ ludzie, którzy nie mogą ujawnić swoich danych, są wrażliwi na udostępnianie ich w jakiejkolwiek formie, ale wydaje się prawdopodobne, że w niektórych przypadkach można nadal publikować dane, jeśli byłyby wystarczająco anonimowe / zaszyfrowane / lekko uszkodzone w pewnym sensie.

Jeśli nie możesz tego zrobić, prawdopodobnie musisz zatrudnić konsultanta, aby rozwiązać problem ...

edycja : Dwa przydatne pytania SO dotyczące anonimizacji / szyfrowania:

  • Jak utworzyć przykładowy zestaw danych z danych prywatnych (zastępując nazwy zmiennych i poziomy nieinformacyjnymi symbolami miejsca)?
  • Mając zestaw liczb losowych wylosowanych z ciągłego rozkładu jednowymiarowego, znajdź rozkład
136 AriB.Friedman Jul 09 2012 at 22:41

Dotychczasowe odpowiedzi są oczywiście świetne, jeśli chodzi o część dotyczącą odtwarzalności. Ma to na celu jedynie wyjaśnienie, że odtwarzalny przykład nie może i nie powinien być jedynym składnikiem pytania. Nie zapomnij wyjaśnić, jak chcesz, aby wyglądało i zarys Twojego problemu, a nie tylko, jak próbowałeś się tam dostać do tej pory. Kod to za mało; potrzebujesz też słów.

Oto powtarzalny przykład tego, czego należy unikać (zaczerpnięty z prawdziwego przykładu, imiona zostały zmienione, aby chronić niewinnych):


Poniżej znajdują się przykładowe dane i część funkcji, z którą mam problem.

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

Jak mogę to osiągnąć?


124 jasmine_007 Feb 20 2014 at 16:11

Mam bardzo łatwy i skuteczny sposób na zrobienie przykładu R, który nie został wspomniany powyżej. Najpierw możesz zdefiniować swoją strukturę. Na przykład,

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

>fix(mydata)

Następnie możesz wprowadzić dane ręcznie. Jest to wydajne w przypadku mniejszych przykładów, a nie dużych.

119 JT85 Apr 10 2013 at 21:51

Aby szybko utworzyć dputdane, możesz po prostu skopiować (fragment) danych do schowka i uruchomić następujące polecenie w R:

dla danych w Excelu:

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

dla danych w pliku txt:

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

W seprazie potrzeby możesz zmienić to drugie. To zadziała oczywiście tylko wtedy, gdy twoje dane znajdują się w schowku.

118 BrodieG Feb 12 2015 at 22:24

Wytyczne:


Twoim głównym celem podczas tworzenia pytań powinno być ułatwienie czytelnikom zrozumienia i odtworzenia problemu w ich systemach. Aby to zrobić:

  1. Podaj dane wejściowe
  2. Zapewnij oczekiwane wyniki
  3. Wyjaśnij zwięźle swój problem
    • jeśli masz ponad 20 linii tekstu + kod, prawdopodobnie możesz wrócić i uprościć
    • maksymalnie uprość swój kod, zachowując problem / błąd

To wymaga trochę pracy, ale wydaje się być uczciwym kompromisem, ponieważ prosisz innych, aby wykonali za Ciebie pracę.

Podanie danych:


Wbudowane zestawy danych

Najlepszym rozwiązaniem zdecydowanie ma polegać na wbudowanej zbiorów danych. Ułatwia to innym pracę nad Twoim problemem. Wpisz data()po znaku zachęty R, aby zobaczyć, jakie dane są dla Ciebie dostępne. Kilka klasycznych przykładów:

  • iris
  • mtcars
  • ggplot2::diamonds (pakiet zewnętrzny, ale prawie każdy go ma)

Sprawdź wbudowane zestawy danych, aby znaleźć taki, który pasuje do Twojego problemu.

Jeśli jesteś w stanie przeformułować swój problem, używając wbudowanych zestawów danych, znacznie bardziej prawdopodobne jest, że uzyskasz dobre odpowiedzi (i głosy za).

Dane wygenerowane samodzielnie

Jeśli problem jest bardzo specyficzny dla typu danych, które nie są reprezentowane w istniejących zestawach danych, podaj kod R, który generuje najmniejszy możliwy zestaw danych, w którym objawia się problem. Na przykład

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

Teraz ktoś, kto próbuje odpowiedzieć na moje pytanie, może skopiować / wkleić te dwie linie i natychmiast rozpocząć pracę nad problemem.

dput

W ostateczności możesz użyć dputdo przekształcenia obiektu danych na kod R (np dput(myData).). Mówię jako „ostatnia deska ratunku”, ponieważ wyjście z programu dputjest często dość nieporęczne, irytujące przy kopiowaniu i wklejaniu i przesłania resztę pytania.

Zapewnij oczekiwane wyniki:


Ktoś kiedyś powiedział:

Obraz oczekiwanego wyniku jest wart 1000 słów

- bardzo mądra osoba

Jeśli możesz dodać coś w rodzaju „Oczekiwano uzyskania tego wyniku”:

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

jeśli chodzi o twoje pytanie, ludzie są znacznie bardziej skłonni do szybkiego zrozumienia, co próbujesz zrobić. Jeśli oczekiwany wynik jest duży i nieporęczny, prawdopodobnie nie zastanawiałeś się wystarczająco, jak uprościć problem (patrz dalej).

Wyjaśnij zwięźle swój problem


Najważniejsze jest, aby maksymalnie uprościć problem, zanim zadasz pytanie. Przeformułowanie problemu, aby działał z wbudowanymi zbiorami danych, bardzo w tym pomoże. Często przekonasz się również, że przechodząc przez proces upraszczania, odpowiesz na swój własny problem.

Oto kilka przykładów dobrych pytań:

  • z wbudowanym zestawem danych
  • z danymi wygenerowanymi przez użytkowników

W obu przypadkach problemy użytkownika prawie na pewno nie wynikają z przedstawionych przez nich prostych przykładów. Raczej wyabstrahowali naturę swojego problemu i zastosowali go do prostego zestawu danych, aby zadać swoje pytanie.

Dlaczego jeszcze jedna odpowiedź na to pytanie?


Ta odpowiedź skupia się na tym, co uważam za najlepszą praktykę: korzystaj z wbudowanych zestawów danych i dostarczaj w rezultacie tego, czego oczekujesz w minimalnej formie. Najbardziej widoczne odpowiedzi dotyczą innych aspektów. Nie spodziewam się, że ta odpowiedź stanie się widoczna; jest to tutaj wyłącznie po to, aby móc linkować do niego w komentarzach do pytań początkujących.

113 daniel Nov 27 2014 at 09:02

Powtarzalny kod jest kluczem do uzyskania pomocy. Jednak jest wielu użytkowników, którzy mogą być sceptyczni co do wklejenia nawet części swoich danych. Na przykład mogą pracować z danymi wrażliwymi lub oryginalnymi danymi zebranymi w celu wykorzystania w pracy naukowej. Z jakiegoś powodu pomyślałem, że fajnie byłoby mieć przydatną funkcję do „deformowania” moich danych przed ich publicznym wklejeniem. anonymizeFunkcji z pakietu SciencesPojest bardzo głupie, ale dla mnie to działa ładnie z dputfunkcji.

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

Następnie anonimizuję to:

> 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

Można również chcieć pobrać próbkę kilku zmiennych zamiast całych danych przed zastosowaniem polecenia anonimizacji i dput.

    # 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

Często potrzebujesz pewnych danych na przykład, jednak nie chcesz publikować dokładnych danych. Aby użyć istniejącej ramki data.frame w istniejącej bibliotece, użyj polecenia data do zaimportowania jej.

na przykład,

data(mtcars)

a następnie rozwiąż problem

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

Jeśli masz duży zbiór danych, którego nie można łatwo wprowadzić do skryptu za pomocą dput(), prześlij swoje dane do wklejania i załaduj je za pomocą read.table:

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

Zainspirowany @Henrik .

90 TylerRinker Jun 11 2015 at 20:57

Opracowuję pakiet wakefield , aby rozwiązać tę potrzebę szybkiego udostępniania odtwarzalnych danych, czasami dputdziała dobrze w przypadku mniejszych zestawów danych, ale wiele problemów, z którymi mamy do czynienia, jest znacznie większych, udostępnianie tak dużego zestawu danych przez dputjest niepraktyczne.

O:

wakefield pozwala użytkownikowi udostępniać minimalny kod w celu odtworzenia danych. Użytkownik ustawian(liczbę wierszy) i określa dowolną liczbę wstępnie ustawionych funkcji zmiennych (obecnie jest ich 70), które naśladują rzeczywiste dane (takie jak płeć, wiek, dochód itp.)

Instalacja:

Obecnie (2015-06-11) wakefield jest pakietem GitHub, ale ostatecznie trafi do CRAN po napisaniu testów jednostkowych. Aby szybko zainstalować, użyj:

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

Przykład:

Oto przykład:

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

To daje:

    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

Jeśli masz jedną lub więcej factorzmiennych w swoich danych, które chcesz odtworzyć za pomocą dput(head(mydata)), rozważ dodanie droplevelsdo nich, tak aby poziomy czynników, które nie są obecne w zminimalizowanym zestawie danych, nie były uwzględniane w dputwynikach, aby uczyń przykład minimalnym :

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

Zastanawiam się, czy plik http://old.r-fiddle.org/link może być bardzo fajnym sposobem na podzielenie się problemem. Otrzymuje unikalny identyfikator, taki jak i można by nawet pomyśleć o umieszczeniu go w SO.

49 user2100721 Jul 22 2016 at 17:01

Proszę nie wklejać danych wyjściowych konsoli w ten sposób:

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

Nie możemy go bezpośrednio skopiować i wkleić.

Aby pytania i odpowiedzi były właściwie odtwarzalne, spróbuj je usunąć +& >przed opublikowaniem i umieść #wyniki i komentarze w następujący sposób:

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

I jeszcze jedno, jeśli użyłeś jakiejś funkcji z jakiegoś pakietu, wspomnij o tej bibliotece.

34 andrii Aug 19 2017 at 02:02

Możesz to zrobić za pomocą reprex .

Jak zauważył mt1022 , „... dobrym pakietem do tworzenia minimalnego, odtwarzalnego przykładu jest „ reprex ” z tidyverse ”.

Według Tidyverse :

Celem „reprex” jest spakowanie problematycznego kodu w taki sposób, aby inni ludzie mogli go uruchomić i poczuć Twój ból.

Przykład podano na stronie internetowej tidyverse .

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

Myślę, że to najprostszy sposób na stworzenie powtarzalnego przykładu.

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

Poza wszystkimi powyższymi odpowiedziami, które uznałem za bardzo interesujące, czasami może być bardzo łatwe, ponieważ zostało to omówione tutaj: - JAK ZROBIĆ MINIMALNY POWTARZALNY PRZYKŁAD, ABY UZYSKAĆ ​​POMOC Z R

Istnieje wiele sposobów na utworzenie losowego wektora Utwórz wektor liczbowy o wartości 100 z losowymi wartościami w R zaokrąglonymi do 2 miejsc po przecinku lub macierz losową w R

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

Zauważ, że czasami bardzo trudno jest udostępnić dane dane z różnych powodów, takich jak wymiar itp. Jednak wszystkie powyższe odpowiedzi są świetne i bardzo ważne do przemyślenia i wykorzystania, gdy chce się stworzyć powtarzalny przykład danych. Należy jednak pamiętać, że aby dane były tak reprezentatywne jak oryginał (w przypadku gdy PO nie może udostępniać oryginalnych danych), dobrze jest dodać pewne informacje do przykładu danych, tak jak (jeśli nazywamy dane mydf1)

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

Ponadto należy znać typ, długość i atrybuty danych, którymi mogą być struktury danych

#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

Oto kilka moich sugestii:

  • Spróbuj użyć domyślnych zestawów danych R.
  • Jeśli masz własny zbiór danych, dołącz go do niego dput, aby inni mogli Ci łatwiej pomóc
  • Nie używaj, install.package()chyba że jest to naprawdę konieczne, ludzie zrozumieją, jeśli używasz po prostu requirelublibrary
  • Staraj się być zwięzły,

    • Mam zbiór danych
    • Postaraj się jak najprościej opisać potrzebne dane wyjściowe
    • Zrób to sam, zanim zadasz pytanie
  • Przesyłanie obrazu jest łatwe, więc jeśli masz, prześlij wykresy
  • Uwzględnij również ewentualne błędy

Wszystko to jest częścią powtarzalnego przykładu.

18 dank Apr 05 2017 at 04:08

Dobrym pomysłem jest użycie funkcji z testthatpakietu, aby pokazać, czego się spodziewasz. W ten sposób inne osoby mogą zmieniać Twój kod, dopóki nie będzie działał bez błędów. Zmniejsza to ciężar tych, którzy chcieliby Ci pomóc, ponieważ oznacza to, że nie muszą dekodować Twojego opisu tekstowego. Na przykład

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

jest jaśniejsze niż „Myślę, że x wyniósłby 1,23 dla y równej lub przekraczającej 10, a 3,21 w innym przypadku, ale nie otrzymałem żadnego wyniku”. Myślę, że nawet w tym głupim przykładzie kod jest jaśniejszy niż słowa. Użycie testthatpozwala pomocnikowi skupić się na kodzie, co oszczędza czas i daje im pewność, że rozwiązali problem, zanim go opublikują