Harika bir R tekrarlanabilir örneği nasıl yapılır


2473

Performansı meslektaşları ile tartışırken, öğretirken, hata raporu gönderirken veya posta listelerinde ve burada Stack Overflow'da rehberlik ararken genellikle tekrarlanabilir bir örnek istenir ve her zaman yardımcı olur.

Mükemmel bir örnek oluşturmak için ipuçlarınız nelerdir? Veri yapılarınımetin biçiminde? Başka hangi bilgileri eklemelisiniz?

Ek olarak orada diğer hileler kullanarak misiniz dput(), dump()yoksa structure()? Ne zaman library()veya require()ifadeler eklemelisiniz ? Hangi kelimeleri saklıdır gerektiği bir kaçının, ek olarak c, df, datavb?

Biri nasıl başarılı olur tekrarlanabilir örnek?


34
Sorunun kapsamı hakkında kafam karıştı. İnsanlar, SO veya R-yardımı ("hatayı nasıl yeniden üretebilir") hakkında sorular sorarak tekrarlanabilir örneğin yorumlanmasına atlamış görünüyorlar. Yardım sayfalarındaki tekrarlanabilir R örnekleri ne olacak? Paket tanıtımlarında? Derslerde / sunumlarda?
vaftiz

15
@baptiste: Aynı eksi hata.
Açıkladığım

33
Yapılar simüle edilemeyecek kadar karmaşık olabileceğinden veriler bazen sınırlayıcı faktördür. Özel verilerden kamu verileri üretmek için: stackoverflow.com/a/10458688/742447 içinde stackoverflow.com/questions/10454973/...
Etienne Düşük Decarie

Yanıtlar:


1727

Bir asgari tekrarlanabilir örnek aşağıdaki öğelerden oluşur:

  • problemi göstermek için minimum veri kümesi
  • verilen veri kümesinde çalıştırılabilen hatayı yeniden oluşturmak için gereken minimum çalıştırılabilir kod
  • kullanılan paketler, R sürümü ve üzerinde çalıştığı sistem hakkında gerekli bilgiler.
  • rasgele süreçler durumunda, set.seed()tekrarlanabilirlik için bir tohum (tarafından ayarlanır ) 1

En az tekrarlanabilir iyi örnek örnekleri için , kullandığınız işlevin yardım dosyalarına bakın. Genel olarak, orada verilen tüm kodlar tekrarlanabilir minimum bir örneğin gereksinimlerini karşılar: veriler sağlanır, minimum kod sağlanır ve her şey çalıştırılabilir. Ayrıca yığın taşması ile ilgili yığın taşması ile ilgili sorulara bakın.

Minimum veri kümesi oluşturma

Çoğu durumda, bu sadece bazı değerlere sahip bir vektör / veri çerçevesi sağlayarak kolayca yapılabilir. Veya çoğu paketle birlikte verilen yerleşik veri kümelerinden birini kullanabilirsiniz.
Dahili veri kümelerinin kapsamlı bir listesi görülebilir library(help = "datasets"). Her veri kümesine kısa bir açıklama vardır ve örneğin ?mtcars'mtcars'ın listedeki veri kümelerinden biri olduğu durumlarda daha fazla bilgi elde edilebilir . Diğer paketler ek veri kümeleri içerebilir.

Bir vektör yapmak kolaydır. Bazen ona biraz rastgelelik eklemek gerekir ve bunu yapmak için çok sayıda işlev vardır. sample()bir vektörü rastgele seçebilir veya sadece birkaç değer içeren rastgele bir vektör verebilir. lettersalfabe içeren yararlı bir vektördür. Bu, faktör yapmak için kullanılabilir.

Birkaç örnek:

  • rastgele değerler: x <- rnorm(10)normal dağılım x <- runif(10)için, düzgün dağılım için, ...
  • bazı değerlerin permütasyonu: x <- sample(1:10)vektör 1:10 için rastgele sırayla.
  • rastgele bir faktör: x <- sample(letters[1:4], 20, replace = TRUE)

Matrisler için matrix(), örneğin şunlar kullanılabilir:

matrix(1:10, ncol = 2)

Veri kareleri yapmak kullanılarak yapılabilir data.frame(). Veri çerçevesindeki girişleri adlandırmaya ve aşırı karmaşık hale getirmemeye dikkat edilmelidir.

Bir örnek :

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

Bazı sorular için belirli biçimlere ihtiyaç duyulabilir. Bu, bir sağlanan herhangi birini kullanabilirsiniz as.someType: fonksiyonlar as.factor, as.Date, as.xtsvektör ve / veya veri çerçevesi hileler ile birlikte, ... Bunlar.

Verilerinizi kopyalayın

Bu ipuçlarını kullanarak inşa etmek çok zor olacaktır bazı veriler varsa, o zaman her zaman kullanarak, orijinal verilerin bir alt kümesini yapabilir head(), subset()ya da endeksleri. Sonra dput()bize hemen R içine konabilecek bir şey vermek için kullanın :

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

Veri çerçevenizin birçok düzeyi olan bir faktörü varsa, dputçıktı verileriniz alt kümesinde bulunmasa bile olası tüm faktör düzeylerini listeleyeceğinden çıktı uygun olmayabilir. Bu sorunu çözmek için droplevels()işlevi kullanabilirsiniz . Türlerin sadece tek seviyeli bir faktör olduğuna dikkat edin:

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

Kullanırken dput, yalnızca alakalı sütunları dahil etmek isteyebilirsiniz:

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

Diğer bir uyarı dput, anahtarlı data.tablenesneler için veya gruplandırılmış tbl_df(sınıf grouped_df) için çalışmayacağıdır dplyr. Bu gibi durumlarda, paylaşmadan önce normal veri çerçevesine dönüştürebilirsiniz dput(as.data.frame(my_data)).

En kötü senaryo, aşağıdaki textparametreyi kullanarak okunabilen bir metin temsili verebilirsiniz 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)

Minimum kod üretmek

Bu kolay bir parça olmalı, ancak çoğu zaman değil. Yapmamanız gereken şey:

  • her türlü veri dönüşümünü ekleyin. Sağlanan verilerin zaten doğru biçimde olduğundan emin olun (tabii ki sorun bu değilse)
  • hata veren tüm fonksiyonu / kod yığınını kopyalayıp yapıştırın. İlk olarak, hangi satırların tam olarak hataya neden olduğunu bulmaya çalışın. Çoğu zaman sorunun kendinizin ne olduğunu öğreneceksiniz.

Yapmanız gereken şey:

  • (kullanıyorsanız library()) kullanıyorsanız, hangi paketlerin kullanılması gerektiğini ekleyin
  • bağlantıları açar veya dosya oluşturursanız, bunları kapatmak için bir kod ekleyin veya dosyaları silin (kullanarak unlink())
  • seçenekleri değiştirirseniz, kodun orijinaline geri döndürmek için bir ifade içerdiğinden emin olun. (ör. op <- par(mfrow=c(1,2)) ...some code... par(op))
  • testin, kodun çalıştırılabilir olduğundan emin olmak için kodunuzu yeni, boş bir R oturumunda çalıştırın. Kişiler verilerinizi ve kodunuzu konsola kopyalayıp yapıştırabilmeli ve tam olarak aynı şekilde alabilmelidir.

Ek bilgi verin

Çoğu durumda, sadece R sürümü ve işletim sistemi yeterli olacaktır. Paketlerle çatışmalar ortaya çıktığında, çıktısını vermek sessionInfo()gerçekten yardımcı olabilir. Diğer uygulamalarla (ODBC veya başka bir şey aracılığıyla) bağlantılar hakkında konuşurken, bunlar için sürüm numaraları ve mümkünse kurulum hakkında gerekli bilgiler de sağlanmalıdır.

İçinde R çalıştırıyorsanız R Studio kullanarak rstudioapi::versionInfo()sizin RStudio sürümünü bildirmek için yararlı olabilir.

Belirli bir paketle ilgili bir sorununuz varsa, çıktısını vererek paketin sürümünü sağlamak isteyebilirsiniz packageVersion("name of the package").


1 Not: Çıkışı set.seed()R> 3.6.0 ve önceki sürümler arasında farklılık gösterir. Rastgele işlem için hangi R sürümünü kullandığınızı belirtin ve eski soruları takip ederken biraz farklı sonuçlar alırsanız şaşırmayın. Bu gibi durumlarda aynı sonucu almak için, RNGversion()önce -fonksiyonunu kullanabilirsiniz set.seed()(örneğin :) RNGversion("3.5.2").


6
Nasıl kullanırım dputdataframe çok büyük ve problem dataframe ortasında tarafından oluşturulan olur? dputVerilerin orta bölümünü yeniden oluşturmak için kullanmanın bir yolu var mı , diyelim ki 60 ile 70 arasındaki satırlar?
BgnR

27
@BgnR Veri çerçevesinin bir bölümünü indeksler kullanarak çıkarabilirsiniz, örneğin: tmp <- mydf[50:70,]ardından dput(mydf). Veri çerçevesi gerçekten büyükse, sorunu yalıtmayı deneyin ve soruna neden olan birkaç satırı gönderin.
Joris Meys

4
@JorisMeys: Verileri özyinelemeli olarak N düzeyine anlatmanın headveya dputsınırlamanın bir yolu var mı ? Tekrarlanabilir örnek ile gelmeye çalışıyorum ve verilerim veri çerçeveleri bir listesidir. Yani, dput(head(myDataObj))14MB boyutunda bir çıktı dosyası oluşturduğundan, yeterli görünmüyor.
Aleksandr Blekh

5
@JorisMeys: Sadece FYI - yukarıdaki yorumda ayrı bir soru olarak soru gönderdi: stackoverflow.com/questions/25127026/… .
Aleksandr Blekh

4
@Konrad Yapabileceğiniz en iyi şey, dosyaya bağlantı oluşturmak ve o dosyada okumak için en az komutu vermektir. Bu, dput () :) 'in çıktısını kopyalamaktan daha az güçlük çekecektir
Joris Meys

590

(İşte yeniden üretilebilir bir örnek nasıl yazılır . Tavsiyem kısa ama tatlı yapmaya çalıştım)

Tekrarlanabilir bir örnek nasıl yazılır.

Tekrarlanabilir bir örnek sunarsanız, R sorununuzla ilgili iyi bir yardım alabilirsiniz. Tekrarlanabilir bir örnek, başka birinin sadece R kodunu kopyalayıp yapıştırarak sorununuzu yeniden oluşturmasına izin verir.

Örneğinizi tekrarlanabilir hale getirmek için eklemeniz gereken dört şey vardır: gerekli paketler, veriler, kod ve R ortamınızın açıklaması.

  • Paketler komut dosyasının üst kısmına yüklenmelidir, bu nedenle örneğin hangisine ihtiyaç duyduğunu görmek kolaydır.

  • Bir e-postaya veya Yığın Taşması sorusuna veri eklemenin en kolay yolu dput(), yeniden oluşturmak için R kodunu oluşturmaktır. Örneğin, mtcarsveri kümesini R'de yeniden oluşturmak için aşağıdaki adımları gerçekleştiririm:

    1. dput(mtcars)R'de koş
    2. Çıktıyı kopyalayın
    3. Tekrarlanabilir komut dosyama yazın ve mtcars <-yapıştırın.
  • Kodunuzun başkalarının okuması için kolay olduğundan emin olmak için biraz zaman harcayın :

    • boşluk kullandığınızdan ve değişken adlarınızın kısa ve bilgilendirici olduğundan emin olun

    • probleminizin nerede olduğunu belirtmek için yorumları kullanın

    • sorunla ilgili olmayan her şeyi kaldırmak için elinizden geleni yapın.
      Kodunuz ne kadar kısa olursa, anlaşılması o kadar kolay olur.

  • Kodunun sessionInfo()bir yorumuna çıkışını ekleyin . Bu, R ortamınızı özetler ve güncel olmayan bir paket kullanıp kullanmadığınızı kontrol etmenizi kolaylaştırır.

Yeni bir R oturumu başlatarak ve komut dosyanızı yapıştırarak gerçekten tekrarlanabilir bir örnek oluşturduğunuzu kontrol edebilirsiniz.

Tüm kodunuzu bir e-postaya koymadan önce Gist github'a koymayı düşünün . Kodunuza güzel sözdizimi vurgulama sağlar ve e-posta sistemi tarafından yönetilen hiçbir şey hakkında endişelenmenize gerek yoktur.


24
reprexin tidyverse, minimal, tekrarlanabilir örnek üretmek için iyi bir paket: github.com/tidyverse/reprex
mt1022

19
Düzenli olarak içinde kod olan e-postalar alıyorum. Hatta kod içeren ekli kelime belgeleri ile e-postalar alıyorum. Bazen SCREENSHOTS kod içeren ekli kelime belgelerine sahip e-postalar bile alıyorum.
hadley

304

Şahsen ben "bir" gömlekleri tercih ederim. Çizgiler boyunca bir şey:

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)

Veri yapısı, tam olarak kelimesi kelimesine yapıyı değil, yazarın problemini taklit etmelidir. Değişkenler kendi değişkenlerimin veya tanrımın yasakladığı fonksiyonların üzerine yazılmadığında bunu gerçekten takdir ediyorum df.

Alternatif olarak, birkaç köşe kesilebilir ve önceden var olan bir veri kümesine işaret edebilir, örneğin:

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

Kullanabileceğiniz özel paketlerden bahsetmeyi unutmayın.

Daha büyük nesnelerde bir şey göstermeye çalışıyorsanız,

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

rasterPaket aracılığıyla uzamsal verilerle çalışıyorsanız , bazı rastgele veriler oluşturabilirsiniz. Paket vinyetinde birçok örnek bulunabilir, ancak burada küçük bir külçe.

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)

Uygulandığı gibi bazı uzamsal nesnelere ihtiyacınız varsa sp, "uzamsal" paketlerde harici dosyalar (ESRI şekil dosyası gibi) aracılığıyla bazı veri kümeleri alabilirsiniz (Görev Görünümlerindeki Uzamsal görünüme bakın).

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

1
IMHO, kullanırken sampleveya runifihtiyatlı set.seed. En azından, bu örnekleme veya rasgele sayı üretimi üzerine aktarma örnekleri üretirken aldığım öneri.
Konrad

1
@Konrad Kabul ediyorum, ama bu değişebilir. Sadece bazı sayılar üretmeye çalışıyorsanız, bir tohum gerekli olmayabilir, ancak sabit sayıların gerekli olduğu yerlerde belirli bir şeyi anlamaya çalışıyorsanız, bir tohum zorunlu olacaktır.
Roman Luštrik

1
Bu imo bir tohum, daha kolay, beklenen çıkışına kendi çözümünü karşılaştırma kendi aralarında çözüm karşılaştırma yapar ile her zaman daha iyidir ve bilmiyorum (ve bilmek gerekmez) gibi işlevler bu şekilde kullanıcıların runifveya samplekarışıklığa neden olmaması aynı verileri alamamaları.
Moody_Mudskipper

2
@mikey usmap paketine baktınız mı?
Roman Luštrik

2
@mikey paket tigris Sayım Bürosu'ndan çeşitli formatlarda şekil dosyaları indiriyor
camille

277

Bu yazıdan esinlenerek, şimdi
reproduce(<mydata>)StackOverflow'a mesaj göndermem gerektiğinde kullanışlı bir işlev kullanıyorum .


HIZLI TALİMATLAR

Eğer myDataçoğaltmak için nesnenin adıdır, Ar aşağıdaki çalıştırın:

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

reproduce(myData)

Detaylar:

Bu işlev akıllı bir sarmalayıcıdır dputve aşağıdakileri yapar:

  • büyük bir veri setini otomatik olarak örnekler (boyuta ve sınıfa göre. Örnek boyutu ayarlanabilir)
  • dputçıktı oluşturur
  • hangi sütunların dışa aktarılacağını belirlemenizi sağlar
  • objName <- ...kolayca kopyalanıp yapıştırılabilmesi için ön tarafa eklenir, ancak ...
  • Bir mac üzerinde çalışıyorsa, çıktı otomatik olarak panoya kopyalanır, böylece çalıştırabilir ve ardından sorunuza yapıştırabilirsiniz.

Kaynak burada mevcuttur:


Misal:

# 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 yaklaşık 100 x 102'dir. 10 satır ve birkaç belirli sütun örneklemek istiyorum

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

Aşağıdaki çıktıyı verir:

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

Çıktının bütününün, kesilmiş satırların uzun bir paragrafında değil, güzel bir tek, uzun satırda olduğuna dikkat edin. Bu, SO sorularının yazılarını okumayı ve kopyalayıp yapıştırmayı kolaylaştırır.


Ekim 2013 Güncellemesi:

Artık kaç satır metin çıktısı alacağını belirtebilirsiniz (yani StackOverflow'a yapıştıracağınız şey). Bunun için lines.out=nargümanı kullanın . Misal:

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

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

196

İşte iyi bir rehber .

En önemli nokta şudur: Sorunun ne olduğunu görmek için çalıştırabileceğimiz küçük bir kod parçası oluşturduğunuzdan emin olun . Bunun için yararlı bir işlevdir dput(), ancak çok büyük verileriniz varsa, küçük bir örnek veri kümesi yapmak veya yalnızca ilk 10 satırı kullanmak isteyebilirsiniz.

DÜZENLE:

Ayrıca sorunun kendinizin nerede olduğunu belirlediğinizden emin olun. Örnek "200 satırında bir hata var" ile tüm R komut dosyası olmamalıdır. R (Seviyorum browser()) ve Google'daki hata ayıklama araçlarını kullanıyorsanız, sorunun gerçekten nerede olduğunu tanımlayabilmeniz ve aynı şeyin yanlış gittiği önemsiz bir örneği yeniden üretebilmeniz gerekir.


165

R-yardım posta listesinde veri oluşturma örneği de dahil olmak üzere hem soru sormayı hem de cevaplamayı kapsayan bir gönderme kılavuzu bulunur:

Örnekler: Bazen birinin gerçekten çalıştırabileceği küçük bir örnek sağlamaya yardımcı olur. Örneğin:

Aşağıdaki gibi bir matris x varsa:

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

8 satırlı ve 'row', 'col' ve 'value' adlı üç sütuna sahip, bu şekilde 'row' ve 'col' değerleri olarak boyut adlarına sahip bir veri çerçevesine nasıl dönüştürebilirim:

  > x.df
     row col value
  1    A   x      1

...
(Bunun cevabı olabilir:

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

)

Sözcük küçük özellikle önemlidir. Minimum tekrarlanabilir bir örnek almayı hedeflemelisiniz , bu da verilerin ve kodun sorunu açıklamak için olabildiğince basit olması gerektiği anlamına gelir.

EDIT: Güzel kod çirkin koddan daha kolay okunur. Bir stil kılavuzu kullanın .


164

R.2.14'ten (sanırım) veri metni temsilini doğrudan aşağıdakilere besleyebilirsiniz 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
") 

3
@ sebastian-c nasıl tekrarlanabilir örnek yapmak için iyi ?? :)
TMS

@TMS Ciddi bir düşünce vermek, eğer asker veriyi sağladıysa ve sorun küçükse (ancak birkaç çözümü olabilir), o zaman daha hızlı olabilir ve yine de tüm adımları takip edebilirsiniz.
sebastian-c

146

Bazen sorun gerçekten verilerin daha küçük bir parçası, kadar uğraşırsan uğraş hiçbir madde ile tekrarlanabilir değildir ve bunu vermedi sentetik veri setleri üretilen göstermek için yararlıdır rağmen (sentetik verilerle olmaz değil sorunu yeniden çünkü, bazı hipotezleri ekarte eder).

  • Verileri web'e bir yere göndermek ve bir URL sağlamak gerekebilir.
  • Veriler herkese açık olarak yayınlanamıyorsa ancak hiç paylaşılabiliyorsa, ilgili taraflara e-posta ile göndermeyi teklif edebilirsiniz (ancak bu, çalışmaktan rahatsız olacak kişi sayısını azaltacaktır) üstünde).
  • Aslında bunu yapmadım, çünkü verilerini serbest bırakamayan insanlar herhangi bir formu serbest bırakma konusunda hassastırlar, ancak bazı durumlarda yeterince anonimleştirilmiş / karıştırılmış / biraz bozuksa hala veri gönderebilirler. bir şekilde.

Bunlardan herhangi birini yapamıyorsanız, muhtemelen probleminizi çözmek için bir danışman tutmanız gerekir ...

edit : anonimleştirme / karıştırmak için iki yararlı SO sorular:


1
Sentetik veri setleri üreten için, bu soruya cevap ait uygulamalar dahil kullanışlı örnekler vermek fitdistrve fitdistrplus.
Iterator

137

Şimdiye kadarki cevaplar tekrarlanabilirlik kısmı için harika. Bu sadece tekrarlanabilir bir örneğin bir sorunun tek bileşeni olamayacağını ve olmaması gerektiğini açıklığa kavuşturmak içindir. Sadece oraya nasıl gitmeye çalıştığınızı değil, nasıl görünmesini istediğinizi ve probleminizin konturlarını açıklamayı unutmayın. Kod yeterli değil; kelimelere de ihtiyacın var.

İşte ne yapmamanız gerektiğine dair tekrarlanabilir bir örnek (gerçek bir örnekten alınmıştır, masumları korumak için isimler değiştirilmiştir):


Aşağıda örnek veriler ve işlevin bir kısmı sorun yaşıyorum.

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

Bunu nasıl başarabilirim ?



124

Yukarıda belirtilmeyen bir R örneği yapmanın çok kolay ve etkili bir yolunu buluyorum. Öncelikle yapınızı tanımlayabilirsiniz. Örneğin,

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

>fix(mydata)

'Düzelt' komutunu çalıştırdığınızda bu açılır kutuyu alacaksınız

Ardından verilerinizi manuel olarak girebilirsiniz. Bu, büyük olanlar yerine küçük örnekler için etkilidir.


18
... o zamandput(mydata)
GSee

Ön ucun nedir? Tam bir cevap almak güzel olurdu. Vb doğrudan döngü gibi bir veri yapmak for (d in data) {...}.
Léo Léopold Hertz 준영

119

Verilerinizden birini hızlı bir şekilde oluşturmak dputiçin verileri panonuza kopyalayabilir (bir parça) ve R'de aşağıdakileri çalıştırabilirsiniz:

Excel'deki veriler için:

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

txt dosyasındaki veriler için:

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

sepGerekirse ikincisini değiştirebilirsiniz . Bu yalnızca verileriniz elbette panodaysa çalışır.


116

Kuralları:


Sorularınızı hazırlarken temel amacınız, okuyucuların sorununuzu sistemlerinde anlamasını ve yeniden oluşturmasını mümkün olduğunca kolaylaştırmak olmalıdır. Böyle yaparak:

  1. Girdi verilerini sağlayın
  2. Beklenen çıktıyı sağlayın
  3. Sorununuzu kısa ve öz bir şekilde açıklayın
    • 20 satırdan fazla metin + kodunuz varsa geri dönüp basitleştirebilirsiniz
    • sorunu / hatayı korurken kodunuzu mümkün olduğunca basitleştirin

Bu biraz iş gerektiriyor, ancak başkalarından sizin için iş yapmalarını istediğiniz için adil bir takas gibi görünüyor.

Veri Sağlama:


Yerleşik Veri Kümeleri

Şimdiye kadarki en iyi seçenek yerleşik veri kümelerine güvenmektir. Bu, başkalarının probleminiz üzerinde çalışmasını kolaylaştırır. Tip data()veri sizin için kullanılabilir ne olduğunu görmek için istemi Ar. Bazı klasik örnekler:

  • iris
  • mtcars
  • ggplot2::diamonds (harici paket, ancak neredeyse herkes buna sahip)

Sorununuza uygun veri kümelerini nasıl bulacağınız için bu SO QA'ya bakın .

Yerleşik veri kümelerini kullanmak için sorununuzu yeniden ifade edebiliyorsanız, iyi yanıtlar (ve upvotes) alma olasılığı daha yüksektir.

Kendi Üreten Veri

Sorununuz varolan veri kümelerinde temsil edilmeyen bir veri türüne çok özelse, sorununuzun kendini gösterdiği olası en küçük veri kümesini oluşturan R kodunu sağlayın. Örneğin

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

Şimdi soruma cevap vermeye çalışan biri bu iki satırı kopyalayıp yapıştırabilir ve problem üzerinde derhal çalışmaya başlayabilir.

dput

Bir şekilde son çare , kullanabilirsiniz dputR kodu (örneğin bir veri nesnesini dönüştürmek için dput(myData)). Ben bir "son çare" diyorum çünkü çıktısı dputgenellikle oldukça hantal, kopyala yapıştırmak için can sıkıcı ve sorunuzun geri kalanını gizler.

Beklenen Çıktıyı Sağlayın:


Birisi bir keresinde şöyle dedi:

Beklenen çıktının resmi 1000 kelimeye bedeldir

- çok akıllı bir insan

"Bu sonucu almayı bekledim" gibi bir şey ekleyebilirsiniz:

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

sorunuza göre, insanların ne yapmaya çalıştığınızı hızlı bir şekilde anlama olasılığı daha yüksektir. Beklediğiniz sonuç büyük ve hantalsa, muhtemelen probleminizi nasıl basitleştireceğiniz hakkında yeterince düşünmediniz (bir sonraki bölüme bakın).

Sorununuzu Kısa Bir Şekilde Açıklayın


Yapılacak en önemli şey, sorunuzu sormadan önce probleminizi olabildiğince basitleştirmektir. Yerleşik veri kümeleriyle çalışmak için sorunu yeniden çerçevelemek bu konuda çok yardımcı olacaktır. Ayrıca, basitleştirme sürecinden geçerek kendi sorununuzu cevaplayacağınızı da sıklıkla göreceksiniz.

İşte bazı iyi soru örnekleri:

Her iki durumda da, kullanıcının sorunları neredeyse kesinlikle verdikleri basit örneklerde değildir. Aksine, sorunlarının doğasını soyutladılar ve sorularını sormak için basit bir veri kümesine uyguladılar.

Neden Bu Soruya Başka Bir Cevap Daha?


Bu cevap, en iyi uygulama olduğuna inandığım şeylere odaklanıyor: yerleşik veri kümelerini kullanın ve sonuç olarak beklediğiniz şeyi en az biçimde sağlayın. En belirgin cevaplar diğer yönlere odaklanır. Bu cevabın herhangi bir önem kazanmasını beklemiyorum; Bu sadece burada, yeni başlayanlar sorularına yorumlarda bağlantı kurabilmem için.


113

Tekrarlanabilir kod yardım almanın anahtarıdır. Bununla birlikte, verilerinin bir kısmını bile yapıştırma konusunda şüpheci olabilecek birçok kullanıcı var. Örneğin, hassas verilerle veya bir araştırma belgesinde kullanılmak üzere toplanan orijinal veriler üzerinde çalışıyor olabilirler. Herhangi bir nedenle, herkese açık bir şekilde yapıştırmadan önce verilerimi "deforme etmek" için kullanışlı bir işleve sahip olmanın iyi olacağını düşündüm. anonymizePaketinden işlevi SciencesPoçok saçma, ama benim için birlikte güzel çalışıyor dputfonksiyonu.

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

Sonra anonimleştiriyorum:

> 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

Anonimleştirme ve dput komutu uygulanmadan önce tüm veriler yerine birkaç değişkenin örneklenmesi de istenebilir.

    # 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

Bununla birlikte, bir örnek için genellikle bazı verilere ihtiyacınız vardır, kesin verilerinizi göndermek istemezsiniz. Kurulu kütüphanede varolan bazı data.frame öğelerini kullanmak için veri komutunu almak üzere kullanın.

Örneğin,

data(mtcars)

ve sonra problemi yap

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

13
Birçok yerleşik veri kümesinin (popüler mtcarsve irisveri kümeleri gibi ) gerçekte datakullanılması için çağrıya ihtiyacı yoktur .
Gregor Thomas


90

Geliştiriyorum Yeniden üretilebilir verileri hızlı bir şekilde paylaşmak için bu ihtiyacı gidermek wakefield paketini, bazendputdaha küçük veri kümeleri için iyi çalışıyor,ancak uğraştığımız sorunların çoğu çok daha büyük, bu kadar büyük bir veri kümesini paylaşmakdputpratik değil.

Hakkında:

wakefield kullanıcının verileri yeniden oluşturmak için minimum kodu paylaşmasına olanak tanır. Kullanıcınverileri (satır sayısı) belirler ve verileri taklit eden (cinsiyet, yaş, gelir vb.

Kurulum:

Şu anda (2015-06-11), wakefield bir GitHub paketidir, ancak birim testleri yazıldıktan sonra sonundagidecektir. Hızlı kurulum için şunu kullanın:

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

Misal:

İşte bir örnek:

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

Bu şunu üretir:

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

72

factorVerilerinizde çoğaltılabilir olmasını istediğiniz bir veya daha fazla değişkeniniz varsa, en aza indirilmiş veri kümesinde bulunmayan faktör düzeylerinin çıktınıza dahil edilmemesi için bu verileri dput(head(mydata))eklemeyi düşünün . örneği en aza indirgeyin :droplevelsdput

dput(droplevels(head(mydata)))

65

Bir http://old.r-fiddle.org/ bağlantısının bir sorunu paylaşmanın çok düzgün bir yolu olup olmadığını merak ediyorum . Gibi benzersiz bir kimlik alır ve hatta SO içine gömmek düşünebilirsiniz.


47

Lütfen konsol çıkışlarınızı şu şekilde yapıştırmayın:

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

Doğrudan kopyalayıp yapıştıramayız.

Soruları ve cevapları düzgün bir şekilde tekrarlanabilir hale getirmek için, göndermeden önce +& öğesini kaldırmaya çalışın ve >bunun #gibi çıktılar ve yorumlar koyun :

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

Bir şey daha, belirli bir paketten herhangi bir işlev kullandıysanız, bu kütüphaneden bahsedin.


2
Eğer silerim >ve eklemek #manuel veya bunu otomatik bir yol var?
BCArg

3
@BCArg >Manuel olarak kaldırırım . Ancak, ek olarak #, editörde Ctrl+Shift+Ckısayol kullanıyorum RStudio.
user2100721

33

Bunu reprex kullanarak yapabilirsiniz .

As mt1022 kaydetti "... asgari, tekrarlanabilir örneğini üretmek için iyi bir pakettir, 'reprex' dan tidyverse ".

Tidyverse'e göre :

"Reprex" in amacı, sorunlu kodunuzu diğer insanların çalıştırabileceği ve acınızı hissedecek şekilde paketlemektir.

Düzenli web sitesinde bir örnek verilmiştir .

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

Bence bu tekrarlanabilir bir örnek oluşturmanın en basit yolu .


33

Burada tartışılan olarak dışında çok ilginç bulduğu cevapların her şeyden dolayı, bazen çok kolay olabilir: - R İLE YARDIM ALMAK İÇİN minimal TEKRARLANABILIR ÖRNEK NASIL

Rastgele bir vektör yapmanın birçok yolu vardır R'de 2 ondalık sayıya veya R'de rastgele matrise yuvarlanmış rastgele değerlerle 100 sayı vektörü oluşturma

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

Bazen boyut vb. Gibi çeşitli nedenlerle belirli bir veriyi paylaşmak çok zor olabilir. Ancak, yukarıdaki yanıtların tümü, tekrarlanabilir bir veri örneği oluşturmak istediğinde düşünmek ve kullanmak için çok önemlidir. Ancak, bir veriyi orijinal olarak temsili hale getirmek için (OP'nin orijinal verileri paylaşamaması durumunda), veri örneğine (mydf1 verilerini çağırırsak) bazı bilgiler eklemenin iyi olduğunu unutmayın.

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

Ayrıca, veri yapıları olabilecek bir verinin tipini, uzunluğunu ve niteliklerini bilmek gerekir.

#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

İşte önerilerimden bazıları:

  • Varsayılan R veri kümelerini kullanmaya çalışın
  • Kendi veri kümeniz varsa, dput , böylece diğerleri size daha kolay yardımcı olabilir
  • Kullanmayın install.package()sadece kullanırsanız gerçekten gerekli olmadıkça, insanlar anlayacaktır requireveyalibrary
  • Kısa ve öz olmaya çalışın,

    • Bazı veri kümeleriniz var
    • İhtiyacınız olan çıkışı mümkün olduğunca basit bir şekilde açıklamaya çalışın
    • Soruyu sormadan önce kendin yap
  • Bir resim yüklemek kolaydır, bu nedenle varsa grafikleri yükleyin
  • Ayrıca olabilecek hataları da dahil et

Bütün bunlar tekrarlanabilir bir örneğin parçasıdır.


1
Buraya gerçekten hiçbir madde eklemediniz. dput()daha önce bahsedilmişti ve bunların çoğu sadece standart SO yönergelerini yineliyor.
Rich Scriven

1
install.package(Bence) gerçekten gerekli olmayan örnekte yer alan işlev ile ilgili sorun yaşıyordum . Ayrıca, varsayılan R veri kümesinin kullanılması tekrarlanabilirliği kolaylaştıracaktır. SO yönergeleri bu konular hakkında özel olarak konuşmamıştır. Dahası, benim görüşümü ifade etmekti ve en çok karşılaştığım bunlardı.
TheRimalaya

18

testthatNe olmasını beklediğinizi göstermek için paketin işlevlerini kullanmak iyi bir fikirdir . Böylece, başkaları hatasız çalışana kadar kodunuzu değiştirebilir. Bu, size yardımcı olmak isteyenlerin yükünü hafifletir, çünkü bu, metinsel açıklamanızı deşifre etmek zorunda olmadıkları anlamına gelir. Örneğin

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

"Ben x'in y için 10'a eşit veya 10'u aşacağını ve aksi takdirde 3.21 olduğunu düşünüyorum, ama her iki sonucu da elde edemedim" den daha net. Bu aptal örnekte bile, kodun kelimelerden daha net olduğunu düşünüyorum. Kullanmak testthat, yardımcınızın zamandan tasarruf sağlayan koda odaklanmasını sağlar ve sorunu göndermeden önce sorununuzu çözdüklerini bilmeleri için bir yol sağlar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.