반응형

훌륭한 R 재현 가능한 예를 만드는 방법


질문

 

동료와의 성과를 논의하고, 교육, 버그 보고서 보내기, 메일 링리스트에 대한 지침을 검색하거나 스택 오버 플로우에 대한 지침을 검색하고 재현 가능한 예제는 종종 질문되며 항상 도움이됩니다.

훌륭한 예를 만드는 팁은 무엇입니까?어떻게 텍스트 형식의 데이터 구조를 어떻게 붙여 넣습니까?어떤 다른 정보를 포함해야합니까?

DPUT (), dump () 또는 구조 ()를 사용하는 것 외에도 다른 트릭이 있습니까?언제 라이브러리 () 또는 요구 () 문을 포함시켜야합니까?C, DF, 데이터 등 외에도 예약 된 단어가 하나의 피해야합니까?

하나는 어떻게 재현 가능한 예를 누릴 수 있습니까?


답변

 

기본적으로, 최소한의 재현 가능한 예제 (MRE)는 다른 사용자가 자신의 컴퓨터에서 문제를 정확하게 재현 할 수있게 해줍니다.

MRE는 다음 항목으로 구성됩니다.

문제를 입증하는 데 필요한 최소한의 데이터 집합 주어진 데이터 집합에서 실행할 수있는 오류를 재현하는 데 필요한 최소한의 실행 가능 코드 사용 된 패키지, R 버전 및 OS에서 필요한 모든 정보는 켜져 있습니다. 임의의 프로세스의 경우 재현성을 위해 시드 (set.seed ()로 설정)

좋은 MRE의 예로 사용중인 함수의 도움말 파일의 하단의 "예제"섹션을 참조하십시오.단순히 예를 들어 입력하십시오.도움 (평균), 또는 짧은 팀은 당신의 r 콘솔에 의미합니다.

최소한의 데이터 집합을 제공합니다

일반적으로 거대한 데이터 세트를 공유하는 것은 필요하지 않으며 다른 사람들이 귀하의 질문을 읽지 못하게 할 수 있습니다.따라서 내장 데이터 세트를 사용하거나 원래 데이터와 유사한 작은 "장난감"예제를 만들어내는 것이 더 좋습니다. 이는 실제로 최소한의 의미가있는 것입니다.어떤 이유로 원래 데이터를 공유 해야하는 경우 DPUT ()과 같은 메소드를 사용해야합니다.이 메서드는 다른 사용자가 데이터의 정확한 복사본을 가져올 수있게합니다.

내장 데이터 세트

기본 제공 데이터 세트 중 하나를 사용할 수 있습니다.데이터 세트의 포괄적 인 목록은 데이터 ()로 볼 수 있습니다.모든 데이터 세트에 대한 간단한 설명이 있으며, 더 많은 정보를 얻을 수 있습니다.IRIS와 함께 R. 설치된 패키지와 함께 제공되는 '조리개'데이터 세트에는 추가 데이터 집합이 포함될 수 있습니다.

예제 데이터 세트 만들기

예비 참고 사항 : 때로는 요소, 날짜 또는 시계열과 같은 특별한 형식 (즉, 클래스)이 필요할 수 있습니다.이를 위해 다음과 같은 기능을 사용하십시오. AS.FACTOR, AS.DATE, AS.XTS, 예 :

d <- as.Date("2020-12-30")

어디

class(d)
# [1] "Date"

벡터

x <- rnorm(10)  ## random vector normal distributed
x <- runif(10)  ## random vector uniformly distributed    
x <- sample(1:100, 10)  ## 10 random draws out of 1, 2, ..., 100    
x <- sample(LETTERS, 10)  ## 10 random draws out of built-in latin alphabet

매트릭스

m <- matrix(1:12, 3, 4, dimnames=list(LETTERS[1:3], LETTERS[1:4]))
m
#   A B C  D
# A 1 4 7 10
# B 2 5 8 11
# C 3 6 9 12

데이터 프레임

set.seed(42)  ## for sake of reproducibility
n <- 6
dat <- data.frame(id=1:n, 
                  date=seq.Date(as.Date("2020-12-26"), as.Date("2020-12-31"), "day"),
                  group=rep(LETTERS[1:2], n/2),
                  age=sample(18:30, n, replace=TRUE),
                  type=factor(paste("type", 1:n)),
                  x=rnorm(n))
dat
#   id       date group age   type         x
# 1  1 2020-12-26     A  27 type 1 0.0356312
# 2  2 2020-12-27     B  19 type 2 1.3149588
# 3  3 2020-12-28     A  20 type 3 0.9781675
# 4  4 2020-12-29     B  26 type 4 0.8817912
# 5  5 2020-12-30     A  26 type 5 0.4822047
# 6  6 2020-12-31     B  28 type 6 0.9657529

참고 : 널리 사용되고 있지만 DF ()는 F 배포판의 밀도 (즉, 곡선의 높이의 높이)가 F 분포의 충돌이므로 데이터 프레임 DF의 이름을 더 잘 지정하지는 않습니다....에

원본 데이터를 복사합니다

특정 이유가 있거나 예제를 구성하기가 너무 어려울 수있는 데이터가있는 경우 DPUT을 사용하여 원래 데이터의 작은 하위 집합을 제공 할 수 있습니다.

DPUT ()을 사용하는 이유는 무엇입니까?

DPUT은 콘솔에서 데이터를 정확하게 재현하는 데 필요한 모든 정보를 던졌습니다.출력을 복사하여 질문에 붙여 넣을 수 있습니다.

통화 DAT (위)는 귀하의 질문에 공유하는 경우 가변 클래스 및 기타 기능에 대한 정보가 여전히 없어야하는 출력을 생성합니다.또한, 타입 열의 공간은 그 중에는 아무 것도 할 수 없게합니다.우리가 데이터를 사용하기 위해 출력 할 때조차도 데이터의 중요한 기능을 얻을 수 없습니다.

  id       date group age   type         x
1  1 2020-12-26     A  27 type 1 0.0356312
2  2 2020-12-27     B  19 type 2 1.3149588
3  3 2020-12-28     A  20 type 3 0.9781675

데이터를 하위 집합하십시오

하위 집합을 공유하려면 head (), subset () 또는 인덱스 아이리스 [1 : 4,]를 사용하십시오.그런 다음 DPUT ()에 랩핑하여 즉시 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")), row.names = c(NA, 
4L), class = "data.frame")

DPUT을 사용할 때 관련 열 만 포함 할 수도 있습니다.DPUT (MTCARS [1 : 3, C (2, 5, 6)])

참고 : 데이터 프레임에 많은 레벨이있는 요소가있는 경우 DPUT 출력은 데이터의 하위 집합에 없더라도 가능한 모든 요소 레벨을 모두 나열하기 때문에 DPUT 출력이 다루기 때문입니다.이 문제를 해결하려면 drioplevels () 함수를 사용할 수 있습니다.종이가 하나의 수준 만있는 요인이되는 방법은 아래에 주목하십시오.DPUT (조리개 (조리개 [1 : 4,])).DPUT에 대한 하나의 다른 경고는 키가있는 DATA.TABLE 객체 또는 티셔티버지에서 그룹화 된 TBL_DF (CLASS GROUPED_DF)에 대해 작동하지 않는다는 것입니다.이러한 경우 공유, DPUT (AS.Data.Frame (my_data))을 공유하기 전에 일반 데이터 프레임으로 다시 변환 할 수 있습니다.

최소한의 코드 생산

최소한의 데이터와 결합 된 (위 참조) 코드는 복사 및 붙여 넣기 만하면 다른 시스템에서 문제를 정확하게 재현해야합니다.

이것은 쉬운 부분이어야하지만 종종 그렇지 않습니다.당신이해야 할 일 :

모든 종류의 데이터 전환을 보여줍니다.제공된 데이터가 이미 올바른 형식인지 확인하십시오 (물론 문제가 아닌 경우) 복사 - 어딘가에 오류를 제공하는 전체 스크립트를 붙여 넣습니다.오류가 발생한 모든 행을 찾으십시오.더 자주하지 않으면 문제가 무엇인지 알아낼 것입니다.

당신이해야 할 일 :

(라이브러리 (라이브러리 ()를 사용하는 경우) 사용하는 패키지를 추가하십시오. 테스트 코드가 실행될 수 있도록 코드를 신선한 R 세션으로 실행하십시오.사람들은 콘솔에 데이터와 코드를 복사하여 붙여 넣고 가지고있는 것과 동일하게 얻을 수 있어야합니다. 연결 또는 파일 만들기를 열면 일부 코드를 추가하여 닫거나 파일을 삭제하십시오 (링크 링크 () 사용) 옵션을 변경하는 경우 코드에 문이 포함되어 있는지 확인하십시오.(예 : OP <- PAR (MFROW = C (1,2)) ... 일부 코드 ... PAR (OP))

필요한 정보를 제공합니다

대부분의 경우 R 버전과 운영 체제만으로 충분합니다.충돌이 패키지로 발생하면 SessionInfo ()의 출력이 실제로 도움이 될 수 있습니다.다른 응용 프로그램에 대한 연결에 대해 이야기 할 때 (ODBC 또는 다른 항목을 통해) 또한 버전 번호를 제공해야하며 가능한 경우 설치에 필요한 정보도 제공해야합니다.

R 스튜디오에서 R을 실행하는 경우 rstudioapi :: versionInfo ()를 사용하여 RSTUDIO 버전을보고하는 데 도움이 될 수 있습니다.

특정 패키지에 문제가있는 경우 Packageversion ( "패키지 이름")의 출력을 제공하여 패키지 버전을 제공 할 수 있습니다.

씨앗

set.seed ()를 사용하여 SEED1, 즉 특정 상태를 지정할 수 있습니다. R의 난수 생성기가 수정되었습니다.이렇게하면 샘플 (), rnorm (), runif () 및 많은 다른 것들과 같은 무작위 기능이 동일한 결과를 항상 반환 할 수 있습니다.

set.seed(42)
rnorm(3)
# [1]  1.3709584 -0.5646982  0.3631284

set.seed(42)
rnorm(3)
# [1]  1.3709584 -0.5646982  0.3631284

1 주 : set.seed ()의 출력은 r> 3.6.0 및 이전 버전간에 다릅니다.임의의 프로세스에 사용한 r 버전을 지정하고 오래된 질문을 할 때 약간 다른 결과가 발생하면 놀라지 마십시오.이러한 경우 동일한 결과를 얻으려면 set.seed () (예 : "3.5.2") 전에 rngversion () - 함수를 사용할 수 있습니다.



답변

(여기에 재현 가능한 예를 작성하는 방법의 조언이 있습니다. 나는 그것을 짧지 만 달콤하게 만들려고 노력했습니다.)

재현 가능한 예제를 작성하는 방법

재현 가능한 예제를 제공하는 경우 r 문제에 대한 좋은 도움을받을 가능성이 가장 높습니다.재현 가능한 예제에서는 R 코드를 복사하고 붙여 넣는 것만으로 인해 다른 사람이 문제를 해결할 수있게합니다.

예를 들어 재현 가능한 네 가지 사항을 포함시켜야합니다. 필요한 패키지, 데이터, 코드 및 R 환경에 대한 설명.

스크립트 맨 위에 패키지를로드해야하므로 쉽게 사용할 수 있습니다. 어떤 것들이 필요한 어떤 것들을보십시오. 전자 메일 또는 스택 오버플로 질문에 데이터를 포함하는 가장 쉬운 방법은 DPUT ()을 사용하여 R 코드를 생성하여 다시 작성하는 것입니다.예를 들어, r에서 MTCARS 데이터 세트를 다시 만들려면, 나는 다음 단계를 수행 할 것이다 : R.에서 DPUT (MTCARS)을 실행하십시오 출력을 복사하십시오 재현 가능한 스크립트에서 MTCARS <- 다음 붙여 넣기를 입력하십시오. 다른 사람들이 쉽게 쉽게 할 수 있도록 조금 시간을 보내십시오. 읽다: 공백을 사용했는지 확인하고 변수 이름은 간결하지만 유익한 의견을 사용하여 문제가있는 곳을 나타냅니다 문제와 관련이없는 모든 것을 제거하기 위해 최선을 다하십시오. 코드가 짧아지면 더 쉽게 이해할 수 있습니다. SessionInfo ()의 출력을 코드의 주석에 포함시킵니다.이것은 당신의 R을 요약합니다 환경을 사용하고 오래된 날짜를 사용하는지 쉽게 확인할 수 있습니다. 패키지.

신선한 R 세션을 시작하고 스크립트를 붙여서 실제로 재현 가능한 예제를 사용하여 실제로 재현 가능한 예제를 확인할 수 있습니다.

모든 코드를 이메일에 넣기 전에 Gist GitHub에 넣는 것을 고려하십시오.코드가 멋진 구문 강조 표시를 제공하며 전자 메일 시스템에서 맹렬한 것에 대해 걱정할 필요가 없습니다.



답변

개인적으로, 나는 "하나의"라이너를 선호합니다.줄을 따라 뭔가 :

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)

데이터 구조는 작가의 문제점의 아이디어를 모방해야하며 정확한 축 어림 구조가 아닙니다.변수가 내 자신의 변수 나 하나님을 forbid, 함수 (df와 같은)를 겹쳐 쓰지 않을 때 정말 감사드립니다.

또는 하나는 몇 가지 모서리를 자르고 기존의 데이터 세트를 가리킬 수 있습니다.

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

사용중인 특별한 패키지를 언급하는 것을 잊지 마십시오.

더 큰 객체에서 뭔가를 보여 주려고하면 시도 할 수 있습니다.

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

래스터 패키지를 통해 공간 데이터로 작업하는 경우 일부 임의의 데이터를 생성 할 수 있습니다.패키지 비 네트에서 많은 예제를 찾을 수 있지만 여기에는 작은 덩어리가 있습니다.

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)

SP에서 구현 된 공간 객체가 필요한 경우 "공간적"패키지의 공간보기를 참조하십시오.

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


답변

이 바로 게시물에서 영감을 얻은 이제 나는 편리한 기능을 사용하고, 스택 오버플로에 게시해야 할 때 재생산 ()을 재현합니다.


빠른 지침

mydata가 재현 할 객체의 이름이면 다음을 실행하십시오.

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

reproduce(myData)

세부:

이 함수는 DPUT에 대한 지능형 래퍼이며 다음을 수행합니다.

대용량 데이터 세트를 자동으로 샘플링합니다 (크기 및 클래스 기반. 샘플 크기 조정 가능) DPUT 출력을 만듭니다 내보낼 열을 지정할 수 있습니다 objname <- ... 앞면에 첨가되어 쉽게 붙여 넣을 수 있도록 쉽게 복사 할 수 있지만 ... Mac에서 작업하는 경우 출력은 자동으로 클립 보드에 복사되므로 단순히 실행 한 다음 질문에 붙여 넣을 수 있습니다.

소스는 여기에서 사용할 수 있습니다.

github - pubr / 재현


예시:

# 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는 약 100 x 102입니다. 나는 10 개의 행과 몇 개의 특정 열을 샘플링하고 싶습니다.

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

다음과 같은 출력을 제공합니다.

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

또한 출력의 전체가 잘게 잘린 선의 높이 단락이 아닌 멋진 단 하나, 긴 줄에 있습니다. 이렇게하면 스택 오버플로 질문 게시물을 쉽게 읽고 쉽게 복사 할 수 있습니다.


2013 년 10 월 업데이트 :

이제 텍스트 출력의 줄을 얼마나 많이 가져갈 수 있는지를 지정할 수 있습니다 (즉, 스택 오버플로에 붙여 넣을 것).이를 위해 lines.out = n 인수를 사용하십시오.예시:

재현 (DF, COLS = C (1 : 3, 17, 23), LINES.OUT = 7) 수확량 :

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


답변

R-HELP 메일 링리스트에는 데이터 생성 예제를 포함하여 질문을 묻고 답하고 답변하는 게시 가이드가 있습니다.

예 : 때로는 도움이됩니다 누군가가 작은 예를 제공하십시오 실제로 실행할 수 있습니다.예를 들어: 다음과 같이 매트릭스 x가있는 경우 :

  > 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 행, 그리고 3 개의 열이라는 3 개의 열 '행', 'col'및 '가치'가있는 'col' 차원 이름은 다음과 같이 '행'과 'col'의 값으로 표시됩니다.

  > x.df
     row col value
  1    A   x      1

...에 ... (대답은 다음과 같습니다.

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

)

작은 단어는 특히 중요합니다.최소한의 재현 가능한 예제를 목표로해야합니다. 즉, 데이터와 코드가 문제를 설명하기 위해 가능한 한 간단해야 함을 의미합니다.

편집 : 예쁜 코드는 못생긴 코드보다 읽기 쉽습니다.스타일 가이드를 사용하십시오.



답변

여기 좋은 가이드가 있습니다.

가장 중요한 점은 다음과 같습니다. 우리가 실행할 수있는 작은 코드를 만드는 것이 문제가 무엇인지 확인하십시오.이것을위한 유용한 기능은 DPUT ()이지만 매우 큰 데이터가있는 경우 작은 샘플 데이터 집합을 만들거나 처음 10 줄 정도 만 사용할 수 있습니다.

편집하다:

또한 문제가 어디에 있는지 확인했는지 확인하십시오.이 예제는 "오류가 발생했습니다"라는 오류가있는 "오류가있는"오류가있는 전체 R 스크립트가 아닙니다.r (i Love Browser ()) 및 Google의 디버깅 도구를 사용하는 경우 문제가있는 곳과 동일한 작업이 잘못되는 사소한 예제를 재현 할 수 있어야합니다.

출처:https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example
반응형