Ao discutir o desempenho com colegas, ensinar, enviar um relatório de erro ou procurar orientação nas listas de discussão e aqui no Stack Overflow, um exemplo reproduzível é frequentemente solicitado e sempre útil.
Quais são as suas dicas para criar um excelente exemplo? Como você cola estruturas de dados derem 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 library()
ou require()
declarações? Que palavras reservadas deve uma evitar, além de c
, df
, data
, etc.?
Como alguém faz um ótimo r exemplo reproduzível?
Respostas:
Um exemplo reprodutível mínimo consiste nos seguintes itens:
set.seed()
) para reprodutibilidade 1Para 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 lá atende aos requisitos de um exemplo reproduzível mínimo: dados são fornecidos, código mínimo é fornecido e tudo é executável. Veja também as perguntas no Stack Overflow com muitas votações.
Produzindo um conjunto de dados mínimo
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 internos, fornecidos com a maioria dos pacotes.
Uma lista abrangente de conjuntos de dados internos pode ser vista com
library(help = "datasets")
. Há uma descrição curta para todos os conjuntos de dados e mais informações podem ser obtidas, por exemplo,?mtcars
onde 'mtcars' é um dos conjuntos de dados na lista. Outros pacotes podem conter conjuntos de dados adicionais.Fazer um vetor é fácil. Às vezes, é necessário adicionar alguma aleatoriedade a ele, e há um número inteiro de funções para fazer isso.
sample()
pode randomizar um vetor ou fornecer um vetor aleatório com apenas alguns valores.letters
é um vetor útil que contém o alfabeto. Isso pode ser usado para criar fatores.Alguns exemplos:
x <- rnorm(10)
para distribuição normal,x <- runif(10)
para distribuição uniforme, ...x <- sample(1:10)
para o vetor 1:10 em ordem aleatória.x <- sample(letters[1:4], 20, replace = TRUE)
Para matrizes, pode-se usar
matrix()
, por exemplo:A criação de quadros de dados pode ser feita usando
data.frame()
. Deve-se prestar atenção ao nome das entradas no quadro de dados e para não torná-lo excessivamente complicado.Um exemplo :
Para algumas perguntas, formatos específicos podem ser necessários. Para estes, pode-se usar qualquer um dos fornecidos
as.someType
funçõ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, usedput()
para nos fornecer algo que possa ser colocado no R imediatamente:Se o seu quadro de dados tiver um fator com muitos níveis, a
dput
saída poderá ser difícil, pois ainda listará todos os níveis possíveis, mesmo que não estejam presentes no subconjunto dos seus dados. Para resolver esse problema, você pode usar adroplevels()
função Observe abaixo como a espécie é um fator com apenas um nível:Ao usar
dput
, você também pode incluir apenas colunas relevantes:Uma outra ressalva
dput
é que ele não funcionará paradata.table
objetos com chave ou para agrupadostbl_df
(classegrouped_df
) dedplyr
. Nesses casos, você pode converter novamente em um quadro de dados regular antes de compartilhardput(as.data.frame(my_data))
,.No pior cenário, você pode fornecer uma representação de texto que pode ser lida usando o
text
parâmetro deread.table
:Produzindo código mínimo
Essa deve ser a parte mais fácil, mas geralmente não é. O que você não deve fazer é:
O que você deve fazer é:
library()
)unlink()
)op <- par(mfrow=c(1,2)) ...some code... par(op)
)Forneça 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. Ao falar sobre conexões com outros aplicativos (seja através do ODBC ou qualquer outra coisa), deve-se também fornecer números de versão para esses e, se possível, também as informações necessárias sobre a instalaçã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 a saída 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 nesses casos, você pode usar aRNGversion()
função -finalset.seed()
(por exemplo :)RNGversion("3.5.2")
.fonte
dput
se o quadro de dados é muito grande e o problema é gerado no meio do quadro de dados? Existe uma maneira dedput
reproduzir a seção intermediária de dados, digamos linhas 60 a 70?tmp <- mydf[50:70,]
seguido pordput(mydf)
. Se o quadro de dados for realmente grande, tente isolar o problema e envie as poucas linhas que causam o problema.head
oudput
limitar os dados ao nível N recursivamente? Estou tentando criar um exemplo reproduzível e meus dados são uma lista de quadros de dados. Portanto,dput(head(myDataObj))
parece não ser suficiente, pois gera um arquivo de saída com tamanho de 14 MB.(Aqui está o meu conselho de Como escrever um exemplo reproduzível . Tentei torná-lo curto, mas agradável)
Como escrever um exemplo reproduzível.
É mais provável que você obtenha uma boa ajuda com o 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 do seu ambiente R.
Os pacotes devem ser carregados na parte superior do script, para que seja fácil ver quais deles o exemplo precisa.
A maneira mais fácil de incluir dados em um email ou em uma pergunta sobre estouro de pilha é usar
dput()
para gerar o código R para recriá-lo. Por exemplo, para recriar omtcars
conjunto de dados em R, execute as seguintes etapas:dput(mtcars)
em Rmtcars <-
e cole.Gaste um pouco de tempo para garantir que seu código seja fácil para outras pessoas lerem:
verifique se você usou espaços e seus nomes de variáveis são concisos, mas informativos
use comentários para indicar onde está o seu problema
faça o seu melhor para remover tudo o que não está relacionado ao problema.
Quanto menor o seu código, mais fácil é entender.
Inclua a saída de
sessionInfo()
em um comentário no seu código. Isso resume seu ambiente R e facilita 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 email, considere colocá-lo no Gist github . Isso dará ao seu código uma boa sintaxe de destaque, e você não precisa se preocupar com nada que ocorra com o sistema de email.
fonte
reprex
emtidyverse
é um pacote bom para produzir mínima, exemplo reproduzível: github.com/tidyverse/reprexPessoalmente, eu prefiro "one" forros. Algo ao longo das linhas:
A estrutura de dados deve imitar a idéia do problema do escritor e não a estrutura exata exata. Eu realmente aprecio quando variáveis não sobrescrevem minhas próprias variáveis ou, se Deus não proíbe, funções (como
df
).Como alternativa, é possível cortar alguns cantos e apontar para um conjunto de dados pré-existente, algo como:
Não se esqueça de mencionar quaisquer pacotes especiais que você possa estar usando.
Se você estiver tentando demonstrar algo em objetos maiores, tente
Se você estiver trabalhando com dados espaciais por meio do
raster
pacote, poderá gerar alguns dados aleatórios. Muitos exemplos podem ser encontrados na vinheta do pacote, mas aqui está uma pequena pepita.Se você precisar de algum objeto espacial, conforme implementado em
sp
, poderá obter alguns conjuntos de dados por meio de arquivos externos (como o ESRI shapefile) em pacotes "espaciais" (consulte a visualização Espacial nas exibições de tarefas).fonte
sample
ourunif
é prudenteset.seed
. Pelo menos, essa é a sugestão que recebi ao produzir exemplos baseados em amostragem ou geração aleatória de números.runif
ousample
não estão confusos que eles não podem obter os mesmos dados.Inspirado por este post, agora uso uma função útil
reproduce(<mydata>)
quando preciso postar no StackOverflow.INSTRUÇÕES RÁPIDAS
Se
myData
é o nome do seu objeto a ser reproduzido, execute o seguinte em R:Detalhes:
Essa função é um invólucro inteligente
dput
e faz o seguinte:dput
saídaobjName <- ...
para que possa ser facilmente copiada + colada, mas ...A fonte está disponível aqui:
Exemplo:
DF é de cerca de 100 x 102. Quero provar 10 linhas e algumas colunas específicas
Fornece a seguinte saída:
Observe também que a totalidade da saída está em uma única linha longa e agradável, e não em um parágrafo alto de linhas cortadas. Isso facilita a leitura nas postagens das perguntas do SO e também a cópia + colar.
Atualização em outubro de 2013:
Agora você pode especificar quantas linhas de saída de texto serão ocupadas (ou seja, o que será colado no StackOverflow). Use o
lines.out=n
argumento para isso. Exemplo:reproduce(DF, cols=c(1:3, 17, 23), lines.out=7)
rendimentos:fonte
Aqui está um bom guia .
O ponto mais importante é: Apenas certifique-se de criar um pequeno pedaço 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, convém criar um pequeno conjunto de dados de amostra ou usar apenas as 10 primeiras linhas ou mais.EDITAR:
Verifique também se você identificou 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 no R (eu amo
browser()
) e no Google, conseguirá realmente identificar onde está o problema e reproduzir um exemplo trivial no qual a mesma coisa dá errado.fonte
A lista de discussão da R-help possui um guia de postagem, que abrange perguntas e respostas, incluindo um exemplo de geração de dados:
A palavra pequeno é especialmente importante. Você deve procurar um exemplo reprodutí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: Código bonito é mais fácil de ler do que código feio. Use um guia de estilo .
fonte
Desde a R.2.14 (eu acho), você pode alimentar sua representação de texto de dados diretamente para
read.table
:fonte
Às vezes, o problema realmente não é reproduzível com dados menores, por mais que 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).
Se você não pode fazer um desses, provavelmente precisará contratar um consultor para resolver seu problema ...
edit : Duas questões úteis para anonimização / embaralhamento:
fonte
fitdistr
efitdistrplus
.As respostas até agora são obviamente ótimas para a parte da reprodutibilidade. Isso serve 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ê quer que seja e os contornos do seu problema, não apenas como você tentou chegar lá até agora. Código não é suficiente; você precisa de palavras também.
Aqui está um exemplo reproduzível do que evitar fazer (extraído de um exemplo real, nomes alterados para proteger os inocentes):
A seguir, são apresentados dados de amostra e parte da função com a qual tenho problemas.
Como posso conseguir isso?
fonte
Eu tenho uma maneira muito fácil e eficiente de fazer um exemplo de R que não foi mencionado acima. Você pode definir sua estrutura primeiro. Por exemplo,
Então você pode inserir seus dados manualmente. Isso é eficiente para exemplos menores, em vez de grandes.
fonte
dput(mydata)
for (d in data) {...}
.Para criar rapidamente um
dput
dos seus dados, você pode apenas copiar (um pedaço) dos dados para a área de transferência e executar o seguinte em R:para dados no Excel:
para dados em um arquivo txt:
Você pode alterar
sep
o último, se necessário. Isso só funcionará se seus dados estiverem na área de transferência, é claro.fonte
Diretrizes:
Seu principal objetivo ao elaborar suas perguntas deve ser o mais fácil possível para os leitores entenderem e reproduzirem o seu problema nos sistemas deles. Para fazer isso:
Isso exige algum trabalho, mas parece uma troca justa, pois você está pedindo que outras pessoas trabalhem para você.
Fornecendo dados:
Conjuntos de dados internos
A melhor opção, de longe, é confiar em conjuntos de dados internos. Isso facilita muito o trabalho de outras pessoas no 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)Consulte este SO QA para saber como encontrar conjuntos de dados adequados para o seu problema.
Se você conseguir reformular seu problema para usar os conjuntos de dados internos, é muito mais provável que você obtenha boas respostas (e votos positivos).
Dados Auto-Gerados
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 o seu problema se manifesta. Por exemplo
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
dput
para transformar um objeto de dados em código R (por exemplodput(myData)
). Digo como um "último recurso", porque a saída dedput
muitas vezes é bastante pesada, irritante para copiar e colar e obscurece o restante da sua pergunta.Fornecer saída esperada:
Alguém disse uma vez:
Se você pode adicionar algo como "Eu esperava obter este resultado":
Na sua pergunta, é muito mais provável que as pessoas entendam rapidamente o que você está tentando fazer. Se o resultado esperado for grande e difícil de manusear, provavelmente você não pensou o suficiente sobre como simplificar o problema (veja a seguir).
Explique Seu Problema Sucintamente
A principal coisa a fazer é simplificar o seu problema o máximo possível antes de fazer sua pergunta. Re-enquadrar o problema para trabalhar com os conjuntos de dados internos ajudará muito nesse sentido. Você também encontrará frequentemente que, apenas passando pelo processo de simplificação, responderá ao seu próprio problema.
Aqui estão alguns exemplos de boas perguntas:
Nos dois casos, os problemas do usuário quase certamente não estão nos exemplos simples que eles fornecem. Em vez disso, abstraíram a natureza do problema e o aplicaram a um conjunto de dados simples para fazer sua pergunta.
Por que mais uma resposta a esta pergunta?
Esta resposta se concentra no que considero a melhor prática: use conjuntos de dados internos e forneça o que você espera como resultado de uma forma mínima. As respostas mais importantes se concentram em outros aspectos. Não espero que essa resposta se destaque; isso está aqui apenas para que eu possa vincular a ele nos comentários das perguntas dos novatos.
fonte
O código reproduzível é essencial para obter ajuda. No entanto, existem muitos usuários que podem ser céticos em colar até mesmo uma parte de seus dados. Por exemplo, eles poderiam estar trabalhando com dados confidenciais ou em dados originais coletados para uso em um trabalho de pesquisa. Por qualquer motivo, achei que seria bom ter uma função útil para "deformar" meus dados antes de colá-los publicamente. A
anonymize
função do pacoteSciencesPo
é muito boba, mas para mim funciona bem com adput
função.Então eu anonimo:
Pode-se também querer amostrar poucas variáveis em vez de dados completos antes de aplicar o comando anonimização e dput.
fonte
Muitas vezes, 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,
e então faça o problema
fonte
mtcars
e deiris
dados) não precisam realmente dadata
chamada para ser usada.Se você possui um conjunto de dados grande que não pode ser facilmente colocado no script
dput()
, poste seus dados no pastebin e carregue-os usandoread.table
:Inspirado por @Henrik .
fonte
Estou desenvolvendo o pacote wakefield para atender a essa necessidade de compartilhar dados reproduzíveis rapidamente, às vezes
dput
funciona bem para conjuntos de dados menores, mas muitos dos problemas com os quais lidamos são muito maiores, o compartilhamento de um conjunto de dados tão grande por issodput
é impraticável.Sobre:
O wakefield permite que o usuário compartilhe um código mínimo para reproduzir dados. O usuário define
n
(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 do GitHub, mas irá para o CRAN eventualmente após a gravação dos testes de unidade. Para instalar rapidamente, use:
Exemplo:
Aqui está um exemplo:
Isso produz:
fonte
Se você tiver uma ou mais
factor
variáveis em seus dados com as quais deseja reproduzirdput(head(mydata))
, considere adicionádroplevels
-las para que os níveis de fatores que não estão presentes no conjunto de dados minimizados não sejam incluídos em suadput
saída, a fim de torne o exemplo mínimo :fonte
Gostaria de saber se um link http://old.r-fiddle.org/ poderia ser uma maneira muito interessante de compartilhar um problema. Ele recebe um ID único e pode-se pensar em incorporá-lo ao SO.
fonte
Por favor, não cole as saídas do console assim:
Não podemos copiar e colar diretamente.
Para tornar as perguntas e respostas reproduzíveis adequadamente, tente remover
+
&>
antes de publicá-las e colocar#
para saídas e comentários como este:Mais uma coisa, se você usou alguma função de determinado pacote, mencione essa biblioteca.
fonte
>
e adiciona#
manualmente ou existe uma maneira automática de fazer isso?>
manualmente. Mas, além disso#
, eu uso oCtrl+Shift+C
atalho noRStudio
editor.Você pode fazer isso usando reprex .
Como o mt1022 observou , "... um bom pacote para produzir um exemplo mínimo e reproduzível é " reprex " do tidyverse ".
De acordo com Tidyverse :
Um exemplo é dado no site arrumado .
Eu acho que essa é a maneira mais simples de criar um exemplo reproduzível.
fonte
Além de todas as respostas acima que achei muito interessantes, às vezes pode ser muito fácil, conforme discutido aqui: - COMO FAZER UM EXEMPLO MÍNIMO REPRODUCÍVEL PARA AJUDAR COM R
Existem várias maneiras de criar um vetor aleatório. Crie um vetor de número 100 com valores aleatórios em R arredondado para 2 casas decimais ou matriz aleatória em R
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íveis. Mas observe que, para tornar os dados tão representativos quanto os originais (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)
Além disso, deve-se conhecer o tipo, comprimento e atributos de um dado que pode ser uma estrutura de dados.
fonte
Aqui estão algumas das minhas sugestões:
dput
para que outros possam ajudá-lo mais facilmenteinstall.package()
menos que seja realmente necessário, as pessoas entenderão se você apenas usarequire
oulibrary
Tente ser conciso,
Tudo isso faz parte de um exemplo reproduzível.
fonte
dput()
foi mencionado anteriormente e muito disso está apenas reiterando as diretrizes padrão de SO.install.package
função incluída no exemplo, o que não é realmente necessário (na minha opinião). Além disso, o uso do conjunto de dados R padrão tornaria a reprodução mais fácil. As diretrizes de SO não falaram nada sobre esses tópicos especificamente. Além disso, pretendia dar a minha opinião e é a que mais encontro.É uma boa ideia usar funções do
testthat
pacote para mostrar o que você espera que ocorra. Assim, outras pessoas podem alterar seu código até que ele seja executado sem erros. Isso facilita o fardo daqueles que gostariam de ajudá-lo, porque significa que eles não precisam decodificar sua descrição textual. Por exemploé mais claro que "eu acho que x seria 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. O uso
testthat
permite que seu assistente se concentre no código, o que economiza tempo, e fornece uma maneira de saber que resolveram o seu problema antes de publicá-lofonte