При обсуждении работы с коллегами, обучении, отправке отчета об ошибке или поиске инструкций в списках рассылки, а также в разделе "Переполнение стека" часто повторяется воспроизводимый пример и всегда полезно.
Каковы ваши советы по созданию отличного примера? Как вы вставляете структуры данных из r в текстовом формате? Какую еще информацию вы должны включить?
Существуют ли другие трюки в дополнение к использованию dput()
, dump()
или structure()
? Когда следует включать в себя library()
или require()
? Какие зарезервированные слова следует избегать, помимо c
, df
, data
и т.д.?
Как сделать отличный r воспроизводимый пример?
Минимальный воспроизводимый пример состоит из следующих элементов:
set.seed()
) для воспроизводимостиЧасто полезно ознакомиться с примерами в файлах справки используемых функций. В общем, весь приведенный здесь код удовлетворяет требованиям минимального воспроизводимого примера: предоставляются данные, предоставляется минимальный код, и все выполняется.
В большинстве случаев это можно легко сделать, просто предоставив вектор/фрейм данных с некоторыми значениями. Или вы можете использовать один из встроенных наборов данных, которые предоставляются с большинством пакетов.
Полный список встроенных наборов данных можно увидеть с library(help = "datasets")
. Для каждого набора данных есть краткое описание, и может быть получена дополнительная информация, например, с ?mtcars
где "mtcars" является одним из наборов данных в списке. Другие пакеты могут содержать дополнительные наборы данных.
Сделать вектор легко. Иногда необходимо добавить к нему некоторую случайность, и для этого есть целый ряд функций. sample()
может случайным образом определять вектор или давать случайный вектор с несколькими значениями. letters
- полезный вектор, содержащий алфавит. Это можно использовать для создания факторов.
Несколько примеров:
x <- rnorm(10)
для нормального распределения, x <- runif(10)
для равномерного распределения,...x <- sample(1:10)
для вектора 1:10 в случайном порядке.x <- sample(letters[1:4], 20, replace = TRUE)
Для матриц можно использовать matrix()
, например:
matrix(1:10, ncol = 2)
Создание кадров данных можно выполнить с помощью data.frame()
. Следует обратить внимание на имена записей в кадре данных и не сделать их чрезмерно сложными.
Пример:
set.seed(1)
Data <- data.frame(
X = sample(1:10),
Y = sample(c("yes", "no"), 10, replace = TRUE)
)
Для некоторых вопросов могут потребоваться конкретные форматы. Для этого можно использовать любую из предоставленных функций as.someType
: as.factor
, as.Date
, as.xts
,... Они в сочетании с трюками векторных и/или данных.
Если у вас есть некоторые данные, которые было бы слишком сложно построить с помощью этих советов, вы всегда можете сделать подмножество исходных данных, используя, например, head()
, subset()
или индексы. Затем используйте, например. dput()
чтобы дать нам что-то, что можно сразу положить в R:
> dput(head(iris,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 = 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")
Если ваш фрейм данных имеет коэффициент со многими уровнями, выход dput
может быть громоздким, поскольку он все равно будет перечислять все возможные уровни факторов, даже если они не присутствуют в подмножестве ваших данных. Чтобы решить эту проблему, вы можете использовать droplevels()
. Ниже следует, как вид является фактором только с одним уровнем:
> dput(droplevels(head(iris, 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")
Еще одна оговорка для dput
заключается в том, что она не будет работать для ключевых данных. data.table
объекты или для группировки tbl_df
(class grouped_df
) из dplyr
. В этих случаях вы можете конвертировать обратно в обычный кадр данных до совместного использования, dput(as.data.frame(my_data))
.
В худшем случае вы можете дать текстовое представление, которое можно прочитать при использовании text
параметра 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)
Это должно быть легкой частью, но часто это не так. То, что вы не должны делать, это:
Что вы должны делать, это:
library()
)unlink()
)op <- par(mfrow=c(1,2))...some code... par(op)
) В большинстве случаев достаточно только версии R и операционной системы. Когда конфликты возникают с пакетами, предоставление вывода sessionInfo()
может действительно помочь. Говоря о подключении к другим приложениям (будь то через ODBC или что-то еще), нужно также указать номера версий для них и, если возможно, также необходимую информацию об установке.
Если вы используете R в R Studio, используя rstudioapi::versionInfo()
может быть полезно сообщить о вашей версии RStudio.
Если у вас возникла проблема с конкретным пакетом, вы можете предоставить версию пакета, предоставив результат packageVersion("name of the package")
.
dput
если dput
очень большой и проблема генерируется серединой фрейма? Есть ли способ использовать dput
для воспроизведения средней части данных, скажем, строк с 60 по 70?
tmp <- mydf[50:70,]
а затем dput(mydf)
. Если кадр данных действительно большой, попробуйте выделить проблему и просто отправьте несколько строк, которые вызывают проблему.
(Здесь мой совет от Как написать воспроизводимый пример. Я пытался сделать его коротким, но сладким)
Вы, скорее всего, получите хорошую помощь с вашей проблемой R, если вы предоставите воспроизводимый пример. Воспроизводимый пример позволяет кому-то еще воссоздать вашу проблему, просто скопировав и вставив R-код.
Есть четыре вещи, которые необходимо включить, чтобы сделать ваш пример воспроизводимым: требуемые пакеты, данные, код и описание вашей среды R.
Пакеты должны быть загружены в верхней части script, поэтому легко посмотрите, какие из них нужны для примера.
Самый простой способ включить данные в вопрос по электронной почте или переполнение стека - использовать dput()
для генерации
R-код для его воссоздания. Например, чтобы воссоздать набор данных mtcars
в R,
Я бы выполнил следующие шаги:
dput(mtcars)
в Rmtcars <-
, затем вставьте.Проведите немного времени, гарантируя, что ваш код легко для других следующим образом:
убедитесь, что вы использовали пробелы, а имена переменных краткие, но информативный
используйте комментарии, чтобы указать, где находится ваша проблема.
сделайте все возможное, чтобы удалить все, что не связано с проблемой.
Чем короче ваш код, тем легче это понимать.
Включите вывод sessionInfo()
в комментарии в коде. Это суммирует ваш R
окружающей среды и позволяет легко проверить, используете ли вы устаревшие
пакет.
Вы можете проверить, действительно ли вы сделали воспроизводимый пример, запустив новый сеанс R и вставив script в.
Перед тем, как поместить весь свой код в электронное письмо, подумайте о том, чтобы положить его на Gist github. Это придаст вашему коду приятный синтаксический подсветка, и вам не придется беспокоиться о чем-либо, искаженном системой электронной почты.
reprex
в tidyverse
- хороший пакет для создания минимального воспроизводимого примера: github.com/tidyverse/reprex
Лично я предпочитаю "один" лайнер. Что-то вроде строк:
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)
Структура данных должна имитировать идею проблемы писателя, а не точную дословную структуру. Я очень ценю это, когда переменные не перезаписывают мои собственные переменные или запрещают богу функции (например, df
).
В качестве альтернативы можно было бы разрезать несколько углов и указать на уже существующий набор данных, например:
library(vegan)
data(varespec)
ord <- metaMDS(varespec)
Не забудьте указать какие-либо специальные пакеты, которые вы могли бы использовать.
Если вы пытаетесь продемонстрировать что-то на более крупных объектах, вы можете попробовать
my.df2 <- data.frame(a = sample(10e6), b = sample(letters, 10e6, replace = TRUE))
Если вы работаете с пространственными данными через пакет raster
, вы можете сгенерировать некоторые случайные данные. Много примеров можно найти в виньетике пакета, но здесь небольшой самородок.
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
, вы можете получить некоторые наборы данных через внешние файлы (например, шейп файл ESRI) в "пространственных" пакетах (см. Пространственный вид в представлениях задач).
library(rgdal)
ogrDrivers()
dsn <- system.file("vectors", package = "rgdal")[1]
ogrListLayers(dsn)
ogrInfo(dsn=dsn, layer="cities")
cities <- readOGR(dsn=dsn, layer="cities")
sample
или runif
целесообразно установить set.seed
. По крайней мере, это предположение я получил при создании примеров, касающихся выборки или генерации случайных чисел.
Вдохновленный этим самым сообщением, теперь я использую удобную функцию
reproduce(<mydata>)
, когда мне нужно отправить сообщение в StackOverflow.
Если myData
- это имя вашего объекта для воспроизведения, запустите в R:
install.packages("devtools")
library(devtools)
source_url("https://raw.github.com/rsaporta/pubR/gitbranch/reproduce.R")
reproduce(myData)
Эта функция является интеллектуальной оболочкой для dput
и выполняет следующие действия:
dput
objName <- ...
, чтобы его можно было легко скопировать + вставить, но...# 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==
Обратите внимание также, что весь вывод находится в хорошей одиночной, длинной строке, а не в высоком абзаце изрезанных строк. Это облегчает чтение сообщений на SO-сообщениях, а также проще скопировать + вставить.
Теперь вы можете указать, сколько строк текстового вывода будет занимать (то есть, что вы будете вставлять в StackOverflow). Для этого используйте аргумент lines.out=n
. Пример:
reproduce(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==
Вот хорошее руководство:
http://www.r-bloggers.com/three-tips-for-posting-good-questions-to-r-help-and-stack-overflow/
Но самое главное: просто убедитесь, что вы создаете небольшой фрагмент кода, который мы можем запустить, чтобы посмотреть, в чем проблема. Полезной функцией для этого является dput()
, но если у вас очень большие данные, вы можете захотеть создать небольшой набор данных образца или использовать только первые 10 строк.
EDIT:
Также убедитесь, что вы определили, где проблема сама. В примере не должно быть целого R script с "В строке 200 есть ошибка". Если вы используете инструменты отладки в R (я люблю browser()
) и google, вы должны быть в состоянии действительно определить, где проблема, и воспроизвести тривиальный пример, в котором то же самое происходит неправильно.
В списке рассылки 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 строками и тремя столбцами с именем 'row', 'col' и 'value', которые имеют имена размеров как значения "row" и "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")
)
Особенно важно слово small. Вы должны стремиться к минимальному воспроизводимому примеру, что означает, что данные и код должны быть как можно более простыми, чтобы объяснить проблему.
РЕДАКТИРОВАТЬ: Довольно простой код легче читать, чем уродливый код. Используйте руководство по стилю.
Так как R.2.14 (я думаю), вы можете подавать свое текстовое представление данных непосредственно на read.table:
df <- read.table(header=T, 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
")
read.table("clipboard", header=TRUE)
.
Иногда проблема действительно не воспроизводится с меньшим объемом данных, как бы вы ни старались, и не происходит с синтетическими данными (хотя полезно показать, как вы создали синтетические наборы данных, которые сделали не воспроизвести проблему, поскольку она исключает некоторые гипотезы).
Если вы не можете сделать ни одно из них, вам, вероятно, потребуется нанять консультанта для решения вашей проблемы...
edit: два полезных вопроса SO для анонимности/скремблирования:
fitdistr
и fitdistrplus
.
Ответы, по-видимому, отлично подходят для части воспроизводимости. Это просто пояснить, что воспроизводимый пример не может и не должен быть единственным компонентом вопроса. Не забудьте объяснить, что вы хотите, чтобы это выглядело, и контуры вашей проблемы, а не только то, как вы пытались добраться до сих пор. Кода недостаточно; вам также нужны слова.
Здесь воспроизводимый пример того, чего следует избегать (нарисованный из реального примера, имена изменены для защиты невинных):
Ниже приведены примеры данных и часть функции, с которой я столкнулся.
code
code
code
code
code (40 or so lines of it)
Как я могу это достичь?
Чтобы быстро создать dput
ваших данных, вы можете просто скопировать (часть) данных в буфер обмена и запустить в R:
для данных в Excel:
dput(read.table("clipboard",sep="\t",header=TRUE))
для данных в файле txt:
dput(read.table("clipboard",sep="",header=TRUE))
При необходимости вы можете изменить sep
в последнем.
Это будет работать, только если ваши данные находятся в буфере обмена, конечно.
У меня очень простой и эффективный способ сделать пример R, который не упоминался выше. Сначала вы можете определить свою структуру. Например,
mydata <- data.frame(a=character(0), b=numeric(0), c=numeric(0), d=numeric(0))
>fix(mydata)
Затем вы можете ввести свои данные вручную. Это эффективно для небольших примеров, а не для больших.
dput(mydata)
for (d in data) {...}
.
Ваша основная задача в решении ваших вопросов должна заключаться в том, чтобы как можно проще понять и воспроизвести вашу проблему в своих системах. Для этого:
Это требует некоторой работы, но кажется хорошим компромиссом, поскольку вы просите других работать для вас.
Лучший вариант на сегодняшний день - полагаться на встроенные наборы данных. Это облегчает для других работу над вашей проблемой. Введите data()
в командной строке R, чтобы узнать, какие данные доступны для вас. Некоторые классические примеры:
iris
mtcars
ggplot2::diamonds
(внешний пакет, но почти у всех есть)Посмотрите на SO QA, чтобы найти наборы данных, подходящие для вашей проблемы.
Если вы можете перефразировать свою проблему, чтобы использовать встроенные наборы данных, у вас гораздо больше шансов получить хорошие ответы (и upvotes).
Если ваша проблема очень специфична для типа данных, которые не представлены в существующих наборах данных, тогда укажите код R, который генерирует самый маленький возможный набор данных, который проявляется в вашей проблеме. Например
set.seed(1) # important to make random data reproducible
myData <- data.frame(a=sample(letters[1:5], 20, rep=T), b=runif(20))
Теперь кто-то, кто пытается ответить на мой вопрос, может скопировать/вставить эти две строки и немедленно начать работу над проблемой.
Как последнее средство, вы можете использовать dput
для преобразования объекта данных в R-код (например, dput(myData)
). Я говорю как "последнее средство", потому что вывод dput
часто довольно громоздкий, раздражающий для копирования-вставки и скрывает остальную часть вашего вопроса.
Кто-то сказал:
Изображение ожидаемого результата стоит 1000 слов
- очень мудрый человек
Если вы можете добавить что-то вроде "Я ожидал получить этот результат":
cyl mean.hp
1: 6 122.28571
2: 4 82.63636
3: 8 209.21429
к вашему вопросу, люди гораздо чаще будут быстро понимать, что вы пытаетесь сделать. Если ваш ожидаемый результат большой и громоздкий, то вы, вероятно, недостаточно думали о том, как упростить свою проблему (см. Следующий).
Главное, чтобы максимально упростить вашу проблему, прежде чем задавать свой вопрос. Повторное создание проблемы для работы со встроенными наборами данных очень поможет в этом отношении. Вы также часто обнаружите, что просто пройдя процесс упрощения, вы ответите на собственную проблему.
Вот несколько примеров хороших вопросов:
В обоих случаях проблемы пользователей почти наверняка не с простыми примерами, которые они предоставляют. Скорее они отвлекли характер своей проблемы и применили ее к простому набору данных, чтобы задать свой вопрос.
В этом ответе основное внимание уделяется тому, что я считаю лучшей практикой: используйте встроенные наборы данных и обеспечивайте то, что вы ожидаете в результате в минимальной форме. Наиболее важные ответы сосредоточены на других аспектах. Я не ожидаю, что этот ответ станет заметным; это здесь исключительно для того, чтобы я мог ссылаться на него в комментариях к вопросам новичков.
Воспроизводимый код является ключевым для получения справки. Однако есть много пользователей, которые могут скептически относиться к вставке даже части их данных. Например, они могут работать с конфиденциальными данными или с исходными данными, собранными для использования в исследовательском документе. По какой-то причине я подумал, что было бы неплохо иметь удобную функцию для "деформирования" моих данных, прежде чем публиковать ее. Функция anonymize
из пакета SciencesPo
очень глупа, но для меня она отлично работает с функцией dput
.
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
Затем я анонимизирую его:
> 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
Также может потребоваться выборка нескольких переменных вместо всех данных, прежде чем применять команду anonymization и 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
Часто вам нужны некоторые данные для примера, однако вы не хотите публиковать свои точные данные. Чтобы использовать некоторые существующие data.frame в установленной библиотеке, используйте команду data для ее импорта.
например.
data(mtcars)
а затем выполните задачу
names(mtcars)
your problem demostrated on the mtcars data set
mtcars
данных mtcars
и iris
) фактически не нуждаются в вызове data
.
Я разрабатываю пакет wakefield, чтобы решить эту проблему, чтобы быстро обмениваться воспроизводимыми данными, иногда dput
отлично работает для небольших наборов данных но многие проблемы, с которыми мы имеем дело, намного больше, использование такого большого набора данных через dput
нецелесообразно.
О:
wakefield позволяет пользователю делиться минимальным кодом для воспроизведения данных. Пользователь устанавливает n
(количество строк) и задает любое количество предустановленных переменных (в настоящее время 70), которые имитируют реальные данные (такие как пол, возраст, доход и т.д.).
Установка:
В настоящее время (2015-06-11), wakefield является пакетом GitHub, но после этого будет отправлен в CRAN после модульных тестов. Для быстрой установки используйте:
if (!require("pacman")) install.packages("pacman")
pacman::p_load_gh("trinker/wakefield")
Пример:
Вот пример:
r_data_frame(
n = 500,
id,
race,
age,
sex,
hour,
iq,
height,
died
)
Это дает:
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
.. ... ... ... ... ... ... ... ...
Если у вас есть одна или несколько переменных factor
в ваших данных, которые вы хотите воспроизвести с помощью dput(head(mydata))
, подумайте о добавлении к ней droplevels
, чтобы уровни факторов, которых нет в минимизированной набор данных не включены в ваш вывод dput
, чтобы сделать пример минимальным:
dput(droplevels(head(mydata)))
Интересно, может ли ссылка http://old.r-fiddle.org/ быть очень аккуратным способом поделиться проблемой. Он получает уникальный идентификатор типа, и можно даже подумать о встраивании его в SO.
Не вставляйте консольные выходы следующим образом:
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")
)
Мы не можем скопировать-вставить его напрямую.
Чтобы правильно отвечать на вопросы и ответы, попробуйте удалить +
& >
перед публикацией и поставить #
для выходов и комментариев следующим образом:
#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")
Еще одна вещь, если вы использовали какую-либо функцию из определенного пакета, укажите эту библиотеку.
>
и добавляете #
вручную или есть автоматический способ сделать это?
>
вручную. Но для добавления #
я использую Ctrl+Shift+C
в редакторе RStudio
.
Помимо всех вышеперечисленных ответов, которые я нашел очень интересными, иногда это может быть очень просто, поскольку здесь обсуждается: - КАК СДЕЛАТЬ МИНИМАЛЬНЫЙ ВОСПРОИЗВЕДЕННЫЙ ПРИМЕР ПОЛУЧИТЬ ПОМОЩЬ С R
Существует множество способов создания случайного вектора. Создайте 100-числовой вектор со случайными значениями в R, округленными до 2 десятичных знаков или случайной матрицы в R
mydf1<- matrix(rnorm(20),nrow=20,ncol=5)
Обратите внимание, что иногда очень сложно делиться данными по различным причинам, таким как размерность и т.д. Однако все вышеприведенные ответы велики и очень важны для размышлений и использования, когда нужно сделать пример воспроизводимых данных. Но обратите внимание, что для того, чтобы сделать данные такими же репрезентативными, как оригинал (в случае, если OP не может делиться исходными данными), полезно добавить некоторую информацию с примером данных как (если мы будем называть данные mydf1)
class(mydf1)
# this shows the type of the data you have
dim(mydf1)
# this shows the dimension of your data
Кроме того, следует знать тип, длину и атрибуты данных, которые могут быть структурами данных
#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))
Вот некоторые из моих предложений:
dput
, чтобы другие могли помочь вам легче.install.package()
, если это действительно необходимо, люди поймут, если вы просто используете require
или library
Постарайтесь быть краткими,
Все это часть воспроизводимого примера.
dput()
упоминался ранее, и большая часть этого просто повторяет стандартные рекомендации SO.
install.package
включенной в пример, которая на самом деле не нужна (по моему мнению). Кроме того, использование набора данных R по умолчанию облегчит воспроизводимость. В руководящих принципах СО ничего конкретно об этих темах не говорится. Кроме того, это было сделано, чтобы высказать свое мнение, и именно с этим я столкнулся больше всего.
Вы можете сделать это, используя reprex.
Как отметил mt1022, "... хороший пакет для создания минимального воспроизводимого примера - " reprex " из tidyverse".
Согласно Tidyverse:
Цель "reprex" - упаковать ваш проблемный код таким образом, чтобы другие люди могли запускать его и чувствовать вашу боль.
Пример приведен на веб-сайте tidyverse.
library(reprex)
y <- 1:4
mean(y)
reprex()
Я думаю, что это самый простой способ, чтобы создать воспроизводимый пример.
Рекомендуется использовать функции из пакета testthat
, чтобы показать, что вы ожидаете. Таким образом, другие люди могут изменять ваш код до тех пор, пока он не будет работать без ошибок. Это облегчает бремя тех, кто хотел бы помочь вам, потому что это означает, что им не нужно расшифровывать ваше текстовое описание. Например
library(testthat)
# code defining x and y
if (y >= 10) {
expect_equal(x, 1.23)
} else {
expect_equal(x, 3.21)
}
понятнее, чем "Я думаю, х получится равным 1,23 для y, равным или превышающим 10, и 3.21 в противном случае, но я не получил ни результата". Даже в этом глупом примере, я думаю, код более ясный, чем слова. Использование testthat
позволяет вашему помощнику сосредоточиться на коде, что экономит время, и это дает им возможность узнать, что они решили вашу проблему, прежде чем отправлять ее