Como fazer um ótimo exemplo R reproduzível

May 11 2011

Ao discutir desempenho com colegas, ensinar, enviar um relatório de bug ou buscar orientação em listas de e-mail e aqui no Stack Overflow, um exemplo reproduzível é frequentemente solicitado e sempre útil.

Quais são suas dicas para criar um excelente exemplo? Como você cola estruturas de dados de r em um formato de texto? Que outras informações você deve incluir?

Existem outros truques além de usar dput(), dump()ou structure()? Quando você deve incluir declarações library()ou require()? Que palavras reservadas deve uma evitar, além de c, df, data, etc.?

Como é que se faz um grande r exemplo reproduzível?

Respostas

1756 JorisMeys May 11 2011 at 18:40

Um exemplo mínimo reproduzível consiste nos seguintes itens:

  • um conjunto de dados mínimo, necessário para demonstrar o problema
  • o código mínimo executável necessário para reproduzir o erro, que pode ser executado no conjunto de dados fornecido
  • as informações necessárias sobre os pacotes usados, versão R e sistema em que é executado.
  • no caso de processos aleatórios, uma semente (definida por set.seed()) para reprodutibilidade 1

Para obter exemplos de bons exemplos mínimos reproduzíveis , consulte os arquivos de ajuda da função que você está usando. Em geral, todo o código fornecido atende aos requisitos de um exemplo reproduzível mínimo: os dados são fornecidos, o código mínimo é fornecido e tudo é executável. Veja também as perguntas no Stack Overflow com muitos votos positivos.

Produzindo um conjunto mínimo de dados

Na maioria dos casos, isso pode ser feito facilmente fornecendo apenas um quadro de vetor / dados com alguns valores. Ou você pode usar um dos conjuntos de dados integrados, que são fornecidos com a maioria dos pacotes.
Uma lista abrangente de conjuntos de dados integrados pode ser vista com library(help = "datasets"). Há uma breve descrição para cada conjunto de dados e mais informações podem ser obtidas, por exemplo, ?mtcarsonde 'mtcars' é um dos conjuntos de dados na lista. Outros pacotes podem conter conjuntos de dados adicionais.

Criar um vetor é fácil. Às vezes é necessário adicionar alguma aleatoriedade a ele, e há um grande número de funções para fazer isso. sample()pode tornar um vetor aleatório ou fornecer um vetor aleatório com apenas alguns valores. lettersé um vetor útil que contém o alfabeto. Isso pode ser usado para fazer fatores.

Alguns exemplos:

  • valores aleatórios: x <- rnorm(10)para distribuição normal, x <- runif(10)para distribuição uniforme, ...
  • uma permutação de alguns valores: x <- sample(1:10)para o vetor 1:10 em ordem aleatória.
  • um fator aleatório: x <- sample(letters[1:4], 20, replace = TRUE)

Para matrizes, pode-se usar matrix(), por exemplo:

matrix(1:10, ncol = 2)

A criação de quadros de dados pode ser feita usando data.frame(). Deve-se prestar atenção ao nomear as entradas no quadro de dados e não torná-lo excessivamente complicado.

Um exemplo :

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

Para algumas questões, formatos específicos podem ser necessários. Para estes, pode-se usar qualquer um dos fornecidos as.someTypefunções: as.factor, as.Date, as.xts, ... Estes, em combinação com os truques vetor e / ou quadro de dados.

Copie seus dados

Se você tem alguns dados que seriam muito difíceis de construir usando essas dicas, então você sempre pode fazer um subconjunto de seus dados originais, usando head(), subset()ou os índices. Em seguida, use dput()para nos dar algo que pode ser colocado em R imediatamente:

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

Se o seu quadro de dados tiver um fator com muitos níveis, a dputsaída pode ser complicada porque ainda listará todos os níveis de fator possíveis, mesmo se eles não estiverem presentes no subconjunto de seus dados. Para resolver esse problema, você pode usar a droplevels()função. Observe abaixo como a espécie é um fator com apenas um nível:

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

Ao usar dput, você também pode querer incluir apenas colunas relevantes:

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

Uma outra ressalva dputé que não funcionará para data.tableobjetos com chave ou para agrupados tbl_df(classe grouped_df) de dplyr. Nestes casos, você pode converter de volta para um quadro de dados regular antes de compartilhar dput(as.data.frame(my_data)).

Na pior das hipóteses, você pode fornecer uma representação de texto que pode ser lida usando o textparâmetro de 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)

Produção de código mínimo

Essa deveria ser a parte fácil, mas geralmente não é. O que você não deve fazer é:

  • adicione todos os tipos de conversões de dados. Certifique-se de que os dados fornecidos já estejam no formato correto (a menos que esse seja o problema, é claro)
  • copiar e colar uma função / pedaço de código inteiro que apresenta um erro. Primeiro, tente localizar quais linhas resultam exatamente no erro. Na maioria das vezes, você mesmo descobrirá qual é o problema.

O que você deve fazer é:

  • adicione quais pacotes devem ser usados ​​se você usar algum (usando library())
  • se você abrir conexões ou criar arquivos, adicione algum código para fechá-los ou exclua os arquivos (usando unlink())
  • se você alterar as opções, certifique-se de que o código contém uma instrução para reverter para os originais. (por exemplo op <- par(mfrow=c(1,2)) ...some code... par(op))
  • teste execute seu código em uma sessão R nova e vazia para certificar-se de que o código pode ser executado. As pessoas devem ser capazes de apenas copiar e colar seus dados e seu código no console e obter exatamente o mesmo que você.

Dê informações extras

Na maioria dos casos, apenas a versão R e o sistema operacional serão suficientes. Quando surgem conflitos com pacotes, fornecer a saída de sessionInfo()pode realmente ajudar. Quando se fala em conexões com outros aplicativos (seja através de ODBC ou qualquer outro), deve-se também fornecer os números das versões dos mesmos e, se possível, também as informações necessárias sobre a configuração.

Se você estiver executando R em R Estúdio utilizando rstudioapi::versionInfo()pode ser útil para relatar sua versão rstudio.

Se você tiver um problema com um pacote específico, poderá fornecer a versão do pacote fornecendo o resultado de packageVersion("name of the package").


1 Nota: A saída de set.seed()difere entre R> 3.6.0 e versões anteriores. Especifique qual versão R você usou para o processo aleatório e não se surpreenda se obtiver resultados ligeiramente diferentes ao seguir perguntas antigas. Para obter o mesmo resultado em tais casos, você pode usar a RNGversion()função-antes set.seed()(por exemplo :) RNGversion("3.5.2").

595 hadley May 11 2011 at 20:57

(Aqui está meu conselho em Como escrever um exemplo reproduzível . Tentei ser curto, mas agradável)

Como escrever um exemplo reproduzível.

É mais provável que você obtenha uma boa ajuda com seu problema de R se fornecer um exemplo reproduzível. Um exemplo reproduzível permite que outra pessoa recrie seu problema apenas copiando e colando o código R.

Há quatro coisas que você precisa incluir para tornar seu exemplo reproduzível: pacotes necessários, dados, código e uma descrição de seu ambiente R.

  • Os pacotes devem ser carregados no início do script, para que seja fácil ver de quais deles o exemplo precisa.

  • A maneira mais fácil de incluir dados em um e-mail ou pergunta do Stack Overflow é usar dput()para gerar o código R para recriá-lo. Por exemplo, para recriar o mtcarsconjunto de dados em R, realizaria as seguintes etapas:

    1. Executar dput(mtcars)em R
    2. Copie o resultado
    3. No meu script reproduzível, digite mtcars <-e cole.
  • Gaste um pouco de tempo garantindo que seu código seja fácil de ler:

    • certifique-se de usar espaços e os nomes de suas variáveis ​​são concisos, mas informativos

    • use comentários para indicar onde está o seu problema

    • faça o possível para remover tudo o que não está relacionado ao problema.
      Quanto mais curto for o código, mais fácil será de entender.

  • Inclua a saída de sessionInfo()em um comentário em seu código. Isso resume seu ambiente R e torna mais fácil verificar se você está usando um pacote desatualizado.

Você pode verificar se realmente criou um exemplo reproduzível iniciando uma nova sessão R e colando seu script.

Antes de colocar todo o seu código em um e-mail, considere colocá-lo no github do Gist . Isso dará ao seu código um bom realce de sintaxe, e você não precisa se preocupar se nada será interrompido pelo sistema de e-mail.

307 RomanLuštrik May 11 2011 at 18:22

Pessoalmente, prefiro forros "um". Algo nesse sentido:

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)

A estrutura de dados deve imitar a ideia do problema do escritor e não a estrutura exata literal. Eu realmente aprecio quando as variáveis ​​não sobrescrevem minhas próprias variáveis ​​ou Deus me livre, funções (como df).

Como alternativa, pode-se cortar alguns cantos e apontar para um conjunto de dados pré-existente, algo como:

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

Não se esqueça de mencionar quaisquer pacotes especiais que você possa estar usando.

Se você está tentando demonstrar algo em objetos maiores, você pode tentar

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

Se você estiver trabalhando com dados espaciais por meio do rasterpacote, poderá gerar alguns dados aleatórios. Muitos exemplos podem ser encontrados na vinheta do pacote, mas aqui está uma pequena pepita.

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)

Se precisar de algum objeto espacial conforme implementado no sp, você pode obter alguns conjuntos de dados por meio de arquivos externos (como o arquivo de forma ESRI) em pacotes "espaciais" (consulte a visualização Espacial em Visualizações de Tarefas).

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

Inspirado por esta mesma postagem, agora uso uma função útil
reproduce(<mydata>)quando preciso postar no StackOverflow.


INSTRUÇÕES RÁPIDAS

Se myDatafor o nome do seu objeto a reproduzir, execute o seguinte em R:

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

reproduce(myData)

Detalhes:

Esta função é um wrapper inteligente para dpute faz o seguinte:

  • amostra automaticamente um grande conjunto de dados (com base no tamanho e classe. O tamanho da amostra pode ser ajustado)
  • cria uma dputsaída
  • permite que você especifique quais colunas exportar
  • anexa na frente dele objName <- ...para que possa ser facilmente copiado e colado, mas ...
  • Se estiver trabalhando em um mac, a saída será copiada automaticamente para a área de transferência, para que você possa simplesmente executá-la e colar na sua pergunta.

A fonte está disponível aqui:

  • Github - pubR / reproduce.R

Exemplo:

# 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 tem cerca de 100 x 102. Quero amostrar 10 linhas e algumas colunas específicas

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

Dá a seguinte saída:

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

Observe também que a totalidade da saída está em uma única linha longa e agradável, não em um parágrafo alto de linhas cortadas. Isso torna mais fácil ler as postagens de perguntas do SO e também copiar e colar.


Atualização em outubro de 2013:

Agora você pode especificar quantas linhas de saída de texto ocupará (ou seja, o que você colará no StackOverflow). Use o lines.out=nargumento para isso. Exemplo:

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

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

Aqui está um bom guia .

O ponto mais importante é: apenas certifique-se de fazer um pequeno trecho de código que possamos executar para ver qual é o problema . Uma função útil para isso é dput(), mas se você tiver dados muito grandes, pode querer fazer um pequeno conjunto de dados de amostra ou usar apenas as primeiras 10 linhas ou mais.

EDITAR:

Além disso, certifique-se de identificar onde está o problema. O exemplo não deve ser um script R inteiro com "Na linha 200, há um erro". Se você usar as ferramentas de depuração em R (adoro browser()) e no Google, deve ser capaz de realmente identificar onde está o problema e reproduzir um exemplo trivial em que a mesma coisa dá errado.

167 RichieCotton May 11 2011 at 20:17

A lista de e-mails R-help tem um guia de postagem que cobre tanto fazer quanto responder a perguntas, incluindo um exemplo de geração de dados:

Exemplos: Às vezes, ajuda a fornecer um pequeno exemplo que alguém pode realmente executar. Por exemplo:

Se eu tiver uma matriz x da seguinte forma:

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

como posso transformá-lo em um dataframe com 8 linhas e três colunas chamadas 'linha', 'col' e 'valor', que têm os nomes das dimensões como os valores de 'linha' e 'col', assim:

  > x.df
     row col value
  1    A   x      1

...
(para o qual a resposta pode ser:

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

)

A palavra pequeno é especialmente importante. Você deve ter como objetivo um exemplo reproduzível mínimo , o que significa que os dados e o código devem ser o mais simples possível para explicar o problema.

EDIT: um código bonito é mais fácil de ler do que um código feio. Use um guia de estilo .

164 Paolo Jun 29 2012 at 15:32

Desde R.2.14 (eu acho), você pode alimentar sua representação de texto de dados diretamente para 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

Às vezes, o problema realmente não é reproduzível com um dado menor, não importa o quanto você tente, e não acontece com dados sintéticos (embora seja útil mostrar como você produziu conjuntos de dados sintéticos que não reproduziram o problema, porque exclui algumas hipóteses).

  • Publicar os dados em algum lugar da web e fornecer um URL pode ser necessário.
  • Se os dados não puderem ser liberados para o público em geral, mas puderem ser compartilhados, você poderá se oferecer para enviá-los por e-mail às partes interessadas (embora isso reduza o número de pessoas que se preocuparão em trabalhar nele).
  • Na verdade, eu não vi isso ser feito, porque as pessoas que não podem liberar seus dados são sensíveis ao liberá-los de qualquer forma, mas parece plausível que em alguns casos ainda seja possível postar dados se forem anonimizados / embaralhados / corrompidos o suficiente de algum modo.

Se você não puder fazer nada disso, provavelmente precisará contratar um consultor para resolver seu problema ...

editar : Duas perguntas úteis do SO para anonimato / embaralhamento:

  • Como criar um conjunto de dados de exemplo a partir de dados privados (substituindo nomes de variáveis ​​e níveis por espaços reservados não informativos)?
  • Dado um conjunto de números aleatórios retirados de uma distribuição univariada contínua, encontre a distribuição
136 AriB.Friedman Jul 09 2012 at 22:41

As respostas até agora são obviamente ótimas para a parte de reprodutibilidade. Isso é apenas para esclarecer que um exemplo reproduzível não pode e não deve ser o único componente de uma pergunta. Não se esqueça de explicar como você deseja que seja e os contornos do seu problema, não apenas como você tentou chegar lá até agora. Código não é suficiente; você também precisa de palavras.

Aqui está um exemplo reproduzível do que evitar fazer (tirado de um exemplo real, nomes alterados para proteger os inocentes):


A seguir estão dados de amostra e parte da função com a qual tenho problemas.

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

Como posso conseguir isso?


124 jasmine_007 Feb 20 2014 at 16:11

Eu tenho uma maneira muito fácil e eficiente de fazer um exemplo R que não foi mencionada acima. Você pode definir sua estrutura em primeiro lugar. Por exemplo,

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

>fix(mydata)

Em seguida, você pode inserir seus dados manualmente. Isso é eficiente para exemplos menores em vez de grandes.

119 JT85 Apr 10 2013 at 21:51

Para criar rapidamente um dputdos seus dados, você pode simplesmente copiar (um pedaço) dos dados para a sua área de transferência e executar o seguinte em R:

para dados em Excel:

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

para dados em um arquivo txt:

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

Você pode alterar sepo último, se necessário. Isso só funcionará se seus dados estiverem na área de transferência, é claro.

118 BrodieG Feb 12 2015 at 22:24

Diretrizes:


Seu principal objetivo ao elaborar suas perguntas deve ser tornar o mais fácil possível para os leitores compreender e reproduzir seu problema em seus sistemas. Para fazer isso:

  1. Fornece dados de entrada
  2. Fornece a saída esperada
  3. Explique seu problema sucintamente
    • se você tem mais de 20 linhas de texto + código, você provavelmente pode voltar e simplificar
    • simplifique o seu código o máximo possível, preservando o problema / erro

Isso exige algum trabalho, mas parece uma troca justa, já que você está pedindo a outros que façam o trabalho para você.

Fornecendo dados:


Conjuntos de dados integrados

De longe, a melhor opção é contar com conjuntos de dados integrados. Isso torna muito mais fácil para outras pessoas trabalharem em seu problema. Digite data()no prompt R para ver quais dados estão disponíveis para você. Alguns exemplos clássicos:

  • iris
  • mtcars
  • ggplot2::diamonds (pacote externo, mas quase todo mundo tem)

Inspecione os conjuntos de dados integrados para encontrar um adequado para o seu problema.

Se você for capaz de reformular seu problema para usar os conjuntos de dados integrados, é muito mais provável que obtenha boas respostas (e votos positivos).

Dados Autogerados

Se o seu problema for muito específico para um tipo de dados que não está representado nos conjuntos de dados existentes, forneça o código R que gera o menor conjunto de dados possível em que seu problema se manifesta. Por exemplo

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

Agora, alguém tentando responder à minha pergunta pode copiar / colar essas duas linhas e começar a trabalhar no problema imediatamente.

dput

Como último recurso , você pode usar dputpara transformar um objeto de dados em código R (por exemplo dput(myData)). Digo como um "último recurso" porque a saída de dputmuitas vezes é bastante difícil de manejar, irritante de copiar e colar e obscurece o resto da sua pergunta.

Fornece o resultado esperado:


Alguém disse uma vez:

Uma imagem de saída esperada vale 1000 palavras

- uma pessoa muito sábia

Se você puder adicionar algo como "Eu esperava obter este resultado":

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

à sua pergunta, as pessoas têm muito mais probabilidade de entender rapidamente o que você está tentando fazer. Se o resultado esperado for grande e difícil de manejar, provavelmente você não pensou o suficiente sobre como simplificar seu problema (veja a seguir).

Explique seu problema de forma sucinta


A principal coisa a fazer é simplificar o seu problema o máximo possível antes de fazer sua pergunta. Reestruturar o problema para trabalhar com os conjuntos de dados integrados ajudará muito nesse aspecto. Freqüentemente, você também descobrirá que, apenas passando pelo processo de simplificação, responderá ao seu próprio problema.

Aqui estão alguns exemplos de boas perguntas:

  • com conjunto de dados integrado
  • com dados gerados pelo usuário

Em ambos os casos, os problemas do usuário quase certamente não estão nos exemplos simples que eles fornecem. Em vez disso, eles abstraíram a natureza de seu problema e o aplicaram a um conjunto de dados simples para fazer suas perguntas.

Por que mais uma resposta a esta pergunta?


Esta resposta enfoca o que eu acho que é a prática recomendada: use conjuntos de dados integrados e forneça o que você espera como resultado de uma forma mínima. As respostas mais proeminentes enfocam outros aspectos. Não espero que essa resposta ganhe destaque; ele está aqui apenas para que eu possa criar um link para ele em comentários a perguntas de novatos.

113 daniel Nov 27 2014 at 09:02

Código reproduzível é a chave para obter ajuda. No entanto, muitos usuários podem ser céticos em relação a colar até mesmo uma parte de seus dados. Por exemplo, eles podem estar trabalhando com dados confidenciais ou em dados originais coletados para uso em um artigo de pesquisa. Por qualquer motivo, achei que seria bom ter uma função útil para "deformar" meus dados antes de colá-los publicamente. A anonymizefunção do pacote SciencesPoé muito boba, mas para mim funciona bem com a dputfunção.

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

Então eu anonimizo:

> 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

Pode-se também querer amostrar algumas variáveis ​​em vez de todos os dados antes de aplicar o anonimato e o comando 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

Freqüentemente, você precisa de alguns dados para um exemplo, no entanto, não deseja postar seus dados exatos. Para usar algum data.frame existente na biblioteca estabelecida, use o comando data para importá-lo.

por exemplo,

data(mtcars)

e então resolva o problema

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

Se você tiver um grande conjunto de dados que não pode ser facilmente colocado no script usando dput(), poste seus dados no pastebin e carregue-os usando read.table:

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

Inspirado por @Henrik .

90 TylerRinker Jun 11 2015 at 20:57

Estou desenvolvendo o pacote wakefield para atender a essa necessidade de compartilhar rapidamente dados reproduzíveis; às vezes dputfunciona bem para conjuntos de dados menores, mas muitos dos problemas com os quais lidamos são muito maiores, compartilhar um conjunto de dados tão grande via dputé impraticável.

Sobre:

wakefield permite ao usuário compartilhar código mínimo para reproduzir dados. O usuário definen(número de linhas) e especifica qualquer número de funções variáveis ​​predefinidas (atualmente existem 70) que imitam dados reais (como sexo, idade, renda, etc.)

Instalação:

Atualmente (11/06/2015), wakefield é um pacote GitHub, mas irá para o CRAN eventualmente depois que os testes de unidade forem escritos. Para instalar rapidamente, use:

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

Exemplo:

Aqui está um exemplo:

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

Isso produz:

    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

Se você tiver uma ou mais factorvariáveis ​​em seus dados que deseja tornar reproduzíveis dput(head(mydata)), considere adicioná droplevels-las, de modo que os níveis de fatores que não estão presentes no conjunto de dados minimizado não sejam incluídos em sua dputsaída, a fim de faça o exemplo mínimo :

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

Eu me pergunto se um http://old.r-fiddle.org/o link pode ser uma maneira muito bacana de compartilhar um problema. Ele recebe um ID único como e pode-se até pensar em incorporá-lo ao SO.

49 user2100721 Jul 22 2016 at 17:01

Não cole as saídas do console desta forma:

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

Não podemos copiar e colar diretamente.

Para tornar as perguntas e respostas reproduzíveis adequadamente, tente remover +& >antes de postá-las e colocá-las #para saídas e comentários como este:

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

Mais uma coisa, se você usou alguma função de determinado pacote, mencione essa biblioteca.

34 andrii Aug 19 2017 at 02:02

Você pode fazer isso usando o reprex .

Como mt1022 observou , "... um bom pacote para produzir um exemplo mínimo reproduzível é " reprex " do tidyverse ".

De acordo com o Tidyverse :

O objetivo do "reprex" é empacotar seu código problemático de forma que outras pessoas possam executá-lo e sentir sua dor.

Um exemplo é dado no site tidyverse .

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

Acho que essa é a maneira mais simples de criar um exemplo reproduzível.

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

Além de todas as respostas acima, que achei muito interessantes, às vezes pode ser muito fácil, como é discutido aqui: - COMO FAZER UM EXEMPLO REPRODUÍVEL MÍNIMO PARA OBTER AJUDA COM R

Existem muitas maneiras de fazer um vetor aleatório Crie um vetor de 100 números com valores aleatórios em R arredondados para 2 casas decimais ou uma matriz aleatória em R

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

Observe que às vezes é muito difícil compartilhar um dado dado devido a vários motivos, como dimensão etc. No entanto, todas as respostas acima são ótimas e muito importantes para pensar e usar quando se deseja fazer um exemplo de dados reproduzível. Mas observe que, para tornar um dado tão representativo quanto o original (caso o OP não possa compartilhar os dados originais), é bom adicionar algumas informações com o exemplo de dados como (se chamarmos os dados de mydf1)

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

Além disso, deve-se saber o tipo, comprimento e atributos de um dado que pode ser Estruturas de dados

#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

Aqui estão algumas das minhas sugestões:

  • Tente usar conjuntos de dados R padrão
  • Se você tiver seu próprio conjunto de dados, inclua-os com dput, para que outras pessoas possam ajudá-lo mais facilmente
  • Não use a install.package()menos que seja realmente necessário, as pessoas entenderão se você apenas usar requireoulibrary
  • Tente ser conciso,

    • Tem algum conjunto de dados
    • Tente descrever a saída de que você precisa da maneira mais simples possível
    • Faça você mesmo antes de fazer a pergunta
  • É fácil fazer upload de uma imagem, então faça upload de plotagens, se você tiver
  • Inclua também quaisquer erros que possa ter

Tudo isso faz parte de um exemplo reproduzível.

18 dank Apr 05 2017 at 04:08

É uma boa ideia usar funções do testthatpacote para mostrar o que você espera que ocorra. Assim, outras pessoas podem alterar seu código até que ele seja executado sem erros. Isso alivia o fardo daqueles que gostariam de ajudá-lo, porque significa que eles não precisam decodificar sua descrição textual. Por exemplo

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

é mais claro do que "Acho que x resultaria em 1,23 para y igual ou superior a 10 e 3,21 caso contrário, mas não obtive nenhum resultado". Mesmo neste exemplo bobo, acho que o código é mais claro do que as palavras. Usar testthatpermite que seu ajudante se concentre no código, o que economiza tempo e fornece uma maneira de eles saberem que resolveram seu problema, antes de publicá-lo