วิธีทำตัวอย่าง R ที่สามารถทำซ้ำได้อย่างยอดเยี่ยม


2473

เมื่อพูดคุยเกี่ยวกับประสิทธิภาพกับเพื่อนร่วมงานการสอนการส่งรายงานข้อผิดพลาดหรือค้นหาคำแนะนำเกี่ยวกับรายชื่อผู้รับจดหมายและที่นี่ใน Stack Overflow ตัวอย่างที่ทำซ้ำได้มักถูกถามและเป็นประโยชน์เสมอ

เคล็ดลับในการสร้างตัวอย่างที่ยอดเยี่ยมคืออะไร คุณวางโครงสร้างข้อมูลได้อย่างไรในรูปแบบข้อความ? ข้อมูลอื่นใดที่คุณควรระบุ

เทคนิคอื่น ๆ ที่มีนอกเหนือจากการใช้dput(), dump()หรือstructure()? เมื่อใดที่คุณควรรวมlibrary()หรือrequire()ข้อความ ซึ่งคำสงวนควรหลีกเลี่ยงการอย่างใดอย่างหนึ่งนอกเหนือไปจากc, df, dataฯลฯ ?

วิธีการหนึ่งที่ทำให้ดี ตัวอย่างที่ทำซ้ำได้?


34
ฉันสับสนเกี่ยวกับขอบเขตของคำถาม ผู้คนดูเหมือนจะกระโดดขึ้นไปบนการตีความของตัวอย่างที่ทำซ้ำได้ในการถามคำถามเกี่ยวกับ SO หรือ R-help (วิธีการ "ทำซ้ำข้อผิดพลาด") สิ่งที่เกี่ยวกับตัวอย่าง R ที่ทำซ้ำได้ในหน้าช่วยเหลือ ในการสาธิตแพคเกจ? ในบทเรียน / งานนำเสนอ?
บัพติสต์

15
@ baptiste: เดียวกันลบข้อผิดพลาด เทคนิคทั้งหมดที่ฉันอธิบายถูกใช้ในหน้าช่วยเหลือแพคเกจและในแบบฝึกหัดและการนำเสนอที่ฉันให้เกี่ยวกับ R
Joris Meys

33
บางครั้งข้อมูลอาจเป็นปัจจัย จำกัด เนื่องจากโครงสร้างอาจซับซ้อนเกินกว่าจะจำลองได้ ในการผลิตข้อมูลสาธารณะจากข้อมูลส่วนตัว: stackoverflow.com/a/10458688/742447ในstackoverflow.com/questions/10454973/…
Etienne Low-Décarie

คำตอบ:


1727

ตัวอย่างทำซ้ำน้อยที่สุดประกอบด้วยรายการต่อไปนี้:

  • ชุดข้อมูลที่น้อยที่สุดจำเป็นต้องแสดงให้เห็นถึงปัญหา
  • น้อยที่สุดที่ทำงานได้รหัสที่จำเป็นในการทำซ้ำข้อผิดพลาดซึ่งสามารถทำงานในชุดข้อมูลที่ได้รับ
  • ข้อมูลที่จำเป็นเกี่ยวกับแพ็คเกจที่ใช้แล้วเวอร์ชัน R และระบบที่รันอยู่
  • ในกรณีของกระบวนการสุ่มเมล็ด (กำหนดโดยset.seed()) สำหรับการทำซ้ำ1

สำหรับตัวอย่างของตัวอย่างที่ทำซ้ำได้น้อยที่สุดให้ดูไฟล์วิธีใช้ของฟังก์ชันที่คุณใช้ โดยทั่วไปรหัสทั้งหมดที่ให้ไว้ตรงตามข้อกำหนดของตัวอย่างที่ทำซ้ำได้น้อยที่สุด: มีการให้ข้อมูลมีรหัสน้อยที่สุดและทุกอย่างสามารถรันได้ ดูคำถามใน Stack Overflow ด้วยจำนวน upvotes มากมาย

การผลิตชุดข้อมูลที่น้อยที่สุด

สำหรับกรณีส่วนใหญ่สามารถทำได้อย่างง่ายดายเพียงแค่ให้ค่าเฟรม / เวกเตอร์กับค่าบางค่า หรือคุณสามารถใช้หนึ่งในชุดข้อมูลที่มีอยู่แล้วซึ่งให้มาพร้อมกับแพ็คเกจส่วนใหญ่ รายการที่ครอบคลุมของตัวในชุดข้อมูลที่สามารถเห็นได้ด้วย
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(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")

หากกรอบข้อมูลของคุณมีปัจจัยหลายระดับdputผลลัพธ์อาจไม่สะดวกเพราะมันจะยังคงแสดงรายการระดับปัจจัยที่เป็นไปได้ทั้งหมดแม้ว่าจะไม่มีอยู่ในส่วนย่อยของข้อมูลของคุณ เพื่อแก้ปัญหานี้คุณสามารถใช้droplevels()ฟังก์ชั่น โปรดสังเกตด้านล่างว่าสปีชีส์เป็นปัจจัยที่มีเพียงระดับเดียวเท่านั้น:

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

เมื่อใช้dputงานคุณอาจต้องการรวมเฉพาะคอลัมน์ที่เกี่ยวข้อง:

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

หนึ่งข้อแม้อื่น ๆ สำหรับการdputก็คือว่ามันจะไม่ทำงานสำหรับคีย์data.tableวัตถุหรือการจัดกลุ่มtbl_df(ชั้น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 ใหม่ที่ว่างเปล่าเพื่อให้แน่ใจว่าสามารถเรียกใช้รหัสได้ ผู้คนควรจะสามารถคัดลอกข้อมูลและรหัสของคุณในคอนโซลและได้รับเหมือนกับที่คุณมี

ให้ข้อมูลเพิ่มเติม

ในกรณีส่วนใหญ่เพียงรุ่น R และระบบปฏิบัติการจะพอเพียง เมื่อความขัดแย้งเกิดขึ้นกับแพคเกจการส่งออกของsessionInfo()สามารถช่วยจริงๆ เมื่อพูดถึงการเชื่อมต่อกับแอปพลิเคชั่นอื่น ๆ (ไม่ว่าจะผ่าน ODBC หรืออย่างอื่น) เราควรระบุหมายเลขเวอร์ชั่นสำหรับแอพพลิเคชั่นเหล่านั้น

หากคุณใช้ R ในR Studioโดยใช้rstudioapi::versionInfo()จะมีประโยชน์ในการรายงานรุ่น RStudio ของคุณ

packageVersion("name of the package")ถ้าคุณมีปัญหากับแพคเกจที่เฉพาะเจาะจงที่คุณอาจต้องการที่จะให้รุ่นของแพคเกจโดยการให้การส่งออกของ


1 หมายเหตุ:ผลลัพธ์ของset.seed()ความแตกต่างระหว่าง R> 3.6.0 และรุ่นก่อนหน้า อย่าระบุเวอร์ชัน R ที่คุณใช้สำหรับกระบวนการสุ่มและอย่าแปลกใจถ้าคุณได้รับผลลัพธ์ที่แตกต่างกันเล็กน้อยเมื่อทำตามคำถามเก่า เพื่อให้ได้ผลเหมือนกันในกรณีเช่นนี้คุณสามารถใช้RNGversion()ฟังก์ชั่ก่อนset.seed()(เช่นRNGversion("3.5.2"))


6
คุณจะใช้งานdputอย่างไรถ้าดาต้าเฟรมมีขนาดใหญ่มากและปัญหาถูกสร้างขึ้นที่กึ่งกลางของดาต้าเฟรม? มีวิธีใช้dputในการทำซ้ำส่วนกลางของข้อมูลพูดแถวที่ 60 ถึง 70 หรือไม่?
BgnR

27
@BgnR คุณสามารถแยกส่วนหนึ่งของกรอบข้อมูลโดยใช้ดัชนีเช่น: ตามมาด้วยtmp <- mydf[50:70,] dput(mydf)หากกรอบข้อมูลมีขนาดใหญ่มากให้ลองแยกปัญหาแล้วส่งเพียงไม่กี่บรรทัดที่ทำให้เกิดปัญหา
Joris Meys

4
@JorisMeys: มีวิธีบอกheadหรือdputจำกัด ข้อมูลให้อยู่ในระดับ N แบบวนซ้ำหรือไม่? ฉันพยายามหาตัวอย่างที่ทำซ้ำได้และข้อมูลของฉันเป็นรายการของกรอบข้อมูล ดังนั้นdput(head(myDataObj))ดูเหมือนว่าจะไม่เพียงพอเนื่องจากจะสร้างไฟล์เอาต์พุตขนาด 14MB
Aleksandr Blekh

5
@JorisMeys: เพียง FYI - คำถามที่โพสต์ในความคิดเห็นดังกล่าวข้างต้นเป็นคำถามเฉพาะกิจการ: stackoverflow.com/questions/25127026/...
Aleksandr Blekh

4
@Konrad สิ่งที่ดีที่สุดที่คุณสามารถทำได้คือเชื่อมโยงไปยังไฟล์และให้คำสั่งขั้นต่ำในการอ่านไฟล์นั้น นั่นจะยุ่งยากน้อยกว่าการคัดลอกการวางเอาท์พุทของ dput () :)
Joris Meys

590

(นี่คือคำแนะนำของฉันจากวิธีการเขียนตัวอย่างที่ทำซ้ำได้ฉันพยายามทำให้มันสั้น แต่หวาน)

วิธีเขียนตัวอย่างที่ทำซ้ำได้

คุณมักจะได้รับความช่วยเหลือที่ดีกับปัญหา R ของคุณถ้าคุณให้ตัวอย่างที่ทำซ้ำได้ ตัวอย่างที่ทำซ้ำได้อนุญาตให้บุคคลอื่นสร้างปัญหาของคุณใหม่โดยเพียงแค่คัดลอกและวางรหัส R

มีสี่สิ่งที่คุณต้องรวมไว้เพื่อทำให้ตัวอย่างของคุณสามารถทำซ้ำได้: แพ็คเกจข้อมูลรหัสและคำอธิบายของสภาพแวดล้อม R ของคุณ

  • ควรโหลดแพคเกจที่ด้านบนสุดของสคริปต์ดังนั้นจึงเป็นเรื่องง่ายที่จะดูตัวอย่างที่ต้องการ

  • วิธีที่ง่ายที่สุดในการรวมข้อมูลในอีเมลหรือคำถาม Stack Overflow คือการใช้dput()เพื่อสร้างรหัส R เพื่อสร้างมันขึ้นมาใหม่ ตัวอย่างเช่นในการสร้างmtcarsชุดข้อมูลใน R ใหม่ฉันจะทำตามขั้นตอนต่อไปนี้:

    1. ทำงานdput(mtcars)ใน R
    2. คัดลอกผลลัพธ์
    3. ในสคริปต์ที่ทำซ้ำได้ของฉันให้พิมพ์mtcars <-แล้ววาง
  • ใช้เวลาสักครู่เพื่อให้แน่ใจว่ารหัสของคุณเป็นเรื่องง่ายสำหรับผู้อื่นในการอ่าน:

    • ตรวจสอบให้แน่ใจว่าคุณใช้ช่องว่างและชื่อตัวแปรของคุณกระชับ แต่มีข้อมูล

    • ใช้ความคิดเห็นเพื่อระบุว่าปัญหาของคุณอยู่ที่ใด

    • พยายามอย่างที่สุดที่จะลบทุกสิ่งที่ไม่เกี่ยวข้องกับปัญหา
      ยิ่งรหัสของคุณสั้นลงเท่าไหร่ก็จะเข้าใจได้ง่ายขึ้นเท่านั้น

  • รวมเอาท์พุทของsessionInfo()ในความคิดเห็นในรหัสของคุณ สิ่งนี้จะสรุปสภาพแวดล้อม Rของคุณและทำให้ง่ายต่อการตรวจสอบว่าคุณใช้แพ็คเกจที่ล้าสมัยหรือไม่

คุณสามารถตรวจสอบว่าคุณได้ทำตัวอย่างที่ทำซ้ำได้จริงโดยเริ่มเซสชัน R ใหม่และวางสคริปต์ของคุณ

ก่อนที่จะวางทั้งหมดของรหัสของคุณในอีเมลพิจารณาวางไว้บนกระทู้ GitHub มันจะให้รหัสของคุณเน้นไวยากรณ์ที่ดีและคุณไม่ต้องกังวลเกี่ยวกับสิ่งใดก็ตามที่ยุ่งเหยิงโดยระบบอีเมล


24
reprexในtidyverseเป็นแพคเกจที่ดีสำหรับการผลิตตัวอย่างที่น้อยที่สุดและทำซ้ำได้: github.com/tidyverse/reprex
mt1022

19
ฉันได้รับอีเมลพร้อมรหัสเป็นประจำ ฉันยังได้รับอีเมลพร้อมเอกสารคำที่แนบมาซึ่งมีรหัส บางครั้งฉันยังได้รับอีเมลพร้อมเอกสารคำที่แนบมาซึ่งมีรหัสของหน้าจอ
hadley

304

โดยส่วนตัวแล้วฉันชอบ liners "หนึ่ง" บางสิ่งบางอย่างตามสาย:

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 Shapefile) ในแพ็คเกจ "อวกาศ" (ดูมุมมองเชิงพื้นที่ในมุมมองงาน)

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

1
IMHO เมื่อใช้sampleหรือมันสมควรที่จะrunif set.seedอย่างน้อยที่สุดข้อเสนอแนะนี้ฉันได้รับเมื่อสร้างตัวอย่างที่ถ่ายทอดการสุ่มตัวอย่างหรือการสร้างหมายเลขสุ่ม
Konrad

1
@ Konrad ฉันเห็นด้วย แต่สิ่งนี้อาจขึ้นอยู่กับ หากคุณเพียงแค่พยายามที่จะสร้างตัวเลขบางตัวเมล็ดอาจไม่จำเป็น แต่ถ้าคุณกำลังพยายามที่จะเข้าใจบางสิ่งบางอย่างโดยเฉพาะที่จำเป็นต้องใช้หมายเลขคงที่เมล็ดจะต้องได้รับคำสั่ง
Roman Luštrik

1
มันจะดีกว่าเสมอกับเมล็ดพันธุ์ imo ทำให้การเปรียบเทียบโซลูชันของตัวเองกับผลลัพธ์ที่คาดไว้ง่ายขึ้นเพื่อเปรียบเทียบโซลูชันระหว่างพวกเขาและวิธีนี้ผู้ใช้ที่ไม่ทราบ (และไม่จำเป็นต้องรู้) ฟังก์ชั่นเหมือนrunifหรือsampleไม่สับสน ว่าพวกเขาไม่สามารถรับข้อมูลเดียวกันได้
Moody_Mudskipper

2
@mikey คุณได้ดูแพคเกจusmap แล้วหรือยัง
Roman Luštrik

2
@mikey แพคเกจไทกริสเชปไฟล์ดาวน์โหลดจากสำนักสำมะโนประชากรในความหลากหลายของรูปแบบ
คามิลล์

277

แรงบันดาลใจจากโพสต์นี้ตอนนี้ฉันใช้ฟังก์ชั่นที่สะดวก
reproduce(<mydata>)เมื่อฉันต้องการโพสต์ไปยัง StackOverflow


คำแนะนำอย่างรวดเร็ว

หากmyDataเป็นชื่อของวัตถุของคุณที่จะทำซ้ำเรียกใช้ต่อไปนี้ใน R:

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

reproduce(myData)

รายละเอียด:

ฟังก์ชั่นนี้เป็น wrapper อัจฉริยะสำหรับdputทำสิ่งต่อไปนี้

  • ตัวอย่างชุดข้อมูลขนาดใหญ่โดยอัตโนมัติ (ขึ้นอยู่กับขนาดและคลาสสามารถปรับขนาดตัวอย่างได้)
  • สร้างdputผลลัพธ์
  • ช่วยให้คุณระบุที่คอลัมน์ที่จะส่งออก
  • ต่อท้ายด้านหน้าobjName <- ...เพื่อให้สามารถคัดลอก + วางได้อย่างง่ายดาย แต่ ...
  • หากทำงานกับ mac เอาต์พุตจะถูกคัดลอกไปยังคลิปบอร์ดโดยอัตโนมัติเพื่อให้คุณสามารถเรียกใช้แล้ววางคำถามของคุณ

แหล่งที่มามีอยู่ที่นี่:


ตัวอย่าง:

# 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 ได้ง่ายขึ้นและคัดลอก + วางได้ง่ายขึ้น


อัปเดต ต.ค. 2556:

ตอนนี้คุณสามารถระบุจำนวนบรรทัดของการส่งออกข้อความที่จะใช้ (เช่นสิ่งที่คุณจะวางลงใน 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==

196

นี่คือสิ่งที่ดีคู่มือ

จุดที่สำคัญที่สุดคือ: ตรวจสอบให้แน่ใจว่าคุณสร้างรหัสชิ้นเล็ก ๆ ที่เราสามารถเรียกใช้เพื่อดูว่าปัญหาคืออะไร ฟังก์ชันที่มีประโยชน์สำหรับสิ่งนี้คือdput()แต่ถ้าคุณมีข้อมูลที่มีขนาดใหญ่มากคุณอาจต้องการสร้างชุดข้อมูลตัวอย่างขนาดเล็กหรือใช้เพียง 10 บรรทัดแรกเท่านั้น

แก้ไข:

ตรวจสอบให้แน่ใจด้วยว่าคุณได้ระบุว่าปัญหาอยู่ที่ใด ตัวอย่างไม่ควรเป็นสคริปต์ R ทั้งหมดที่มี "On line 200 มีข้อผิดพลาด" หากคุณใช้เครื่องมือตรวจแก้จุดบกพร่องใน R (I love browser()) และ Google คุณควรจะสามารถระบุได้อย่างแท้จริงว่าปัญหาอยู่ที่ไหนและทำซ้ำตัวอย่างเล็ก ๆ น้อย ๆ ที่สิ่งเดียวกันผิดพลาด


165

รายชื่อผู้รับจดหมาย 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
  >

ฉันจะเปลี่ยนเป็น dataframe ด้วย 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")

)

คำเล็ก ๆมีความสำคัญอย่างยิ่ง คุณควรตั้งเป้าหมายสำหรับตัวอย่างที่ทำซ้ำได้น้อยที่สุดซึ่งหมายความว่าข้อมูลและรหัสควรเรียบง่ายที่สุดเท่าที่จะทำได้เพื่ออธิบายปัญหา

แก้ไข: รหัสสวยอ่านง่ายกว่ารหัสน่าเกลียด ใช้คู่มือสไตล์


164

ตั้งแต่ R.2.14 (ฉันเดา) คุณสามารถป้อนการแสดงข้อความข้อมูลของคุณโดยตรงไปที่read.table:

 df <- read.table(header=TRUE, 
  text="Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa
") 

3
@ sebastian-c มันดีสำหรับการทำตัวอย่างซ้ำได้อย่างไร ?? :)
TMS

@TMS ให้ความคิดที่จริงจังหากผู้ถามได้ให้ข้อมูลและปัญหามีขนาดเล็ก (แต่อาจมีวิธีแก้ปัญหาเล็กน้อย) แสดงว่าอาจเร็วขึ้นและคุณสามารถทำตามขั้นตอนทั้งหมดได้
sebastian-c

146

บางครั้งปัญหานั้นไม่สามารถทำซ้ำได้ด้วยชิ้นส่วนข้อมูลขนาดเล็กไม่ว่าคุณจะพยายามอย่างหนักเพียงใดและไม่เกิดขึ้นกับข้อมูลสังเคราะห์ (แม้ว่าจะเป็นประโยชน์ในการแสดงว่าคุณผลิตชุดข้อมูลสังเคราะห์ที่ไม่ทำให้เกิดปัญหาเพราะ มันออกกฎบางข้อ)

  • โพสต์ข้อมูลไปยังเว็บบางแห่งและให้ URL อาจจำเป็น
  • หากข้อมูลไม่สามารถเผยแพร่สู่สาธารณะได้ แต่สามารถแบ่งปันได้เลยคุณอาจเสนอให้ส่งอีเมลไปยังผู้ที่สนใจได้ (แม้ว่าจะเป็นการลดจำนวนคนที่ต้องทำงาน บนมัน)
  • ฉันไม่ได้เห็นสิ่งนี้จริงเพราะคนที่ไม่สามารถปล่อยข้อมูลของพวกเขามีความละเอียดอ่อนเกี่ยวกับการปล่อยมันในรูปแบบใด ๆ แต่มันก็น่าจะเป็นไปได้ว่าในบางกรณีหนึ่งยังคงสามารถโพสต์ข้อมูลถ้ามันไม่เพียงพอ ในทางใดทางหนึ่ง

หากคุณไม่สามารถทำสิ่งใดสิ่งหนึ่งได้คุณอาจต้องจ้างที่ปรึกษาเพื่อแก้ปัญหาของคุณ ...

แก้ไข : สองคำถาม SO ที่มีประโยชน์สำหรับการลบข้อมูลระบุตัวตน / scrambling:


1
สำหรับการผลิตชุดข้อมูลสังเคราะห์ตอบคำถามนี้ให้ตัวอย่างที่เป็นประโยชน์รวมทั้งการประยุกต์ใช้และfitdistr fitdistrplus
Iterator

137

คำตอบที่เห็นได้ชัดนั้นยอดเยี่ยมสำหรับส่วนการทำซ้ำ นี่เป็นเพียงการชี้แจงว่าตัวอย่างที่ทำซ้ำได้ไม่สามารถและไม่ควรเป็นองค์ประกอบเดียวของคำถาม อย่าลืมอธิบายว่าคุณต้องการให้มันเป็นอย่างไรและรูปร่างของปัญหาของคุณไม่ใช่แค่วิธีที่คุณพยายามจะไปถึงที่นั่น รหัสไม่เพียงพอ คุณต้องการคำพูดด้วย

นี่คือตัวอย่างที่ทำซ้ำได้ของสิ่งที่ควรหลีกเลี่ยง (ดึงมาจากตัวอย่างจริงเปลี่ยนชื่อเพื่อปกป้องผู้บริสุทธิ์):


ต่อไปนี้เป็นข้อมูลตัวอย่างและส่วนหนึ่งของฟังก์ชั่นที่ฉันมีปัญหา

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

ฉันจะบรรลุสิ่งนี้ได้อย่างไร



124

ฉันมีวิธีที่ง่ายและมีประสิทธิภาพในการทำตัวอย่าง R ที่ไม่ได้กล่าวถึงข้างต้น คุณสามารถกำหนดโครงสร้างของคุณได้ในตอนแรก ตัวอย่างเช่น,

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

>fix(mydata)

เมื่อคุณรันคำสั่ง 'แก้ไข' คุณจะได้รับกล่องป๊อปอัปนี้

จากนั้นคุณสามารถป้อนข้อมูลด้วยตนเอง สิ่งนี้มีประสิทธิภาพสำหรับตัวอย่างขนาดเล็กแทนที่จะเป็นชิ้นใหญ่


18
... จากนั้นdput(mydata)
GSee

ส่วนหน้าของคุณคืออะไร มันจะดีถ้ามีคำตอบที่สมบูรณ์ ฯลฯ for (d in data) {...}ให้ข้อมูลที่คุณสามารถโดยตรงห่วงเช่น
LéoLéopold Hertz 준영

119

หากต้องการสร้างข้อมูลdputของคุณอย่างรวดเร็วคุณสามารถคัดลอกข้อมูลไปยังคลิปบอร์ดของคุณและเรียกใช้สิ่งต่อไปนี้ใน R:

สำหรับข้อมูลใน Excel:

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

สำหรับข้อมูลในไฟล์ txt:

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

คุณสามารถเปลี่ยนsepในภายหลังหากจำเป็น วิธีนี้จะใช้งานได้หากข้อมูลของคุณอยู่ในคลิปบอร์ดแน่นอน


116

แนวทาง:


วัตถุประสงค์หลักของคุณในการกำหนดคำถามของคุณควรทำให้ง่ายที่สุดสำหรับผู้อ่านในการทำความเข้าใจและจำลองปัญหาของคุณในระบบของพวกเขา โดยทำดังนี้

  1. จัดเตรียมข้อมูลอินพุต
  2. ให้ผลลัพธ์ที่คาดหวัง
  3. อธิบายปัญหาของคุณอย่างกระชับ
    • หากคุณมีข้อความ + รหัสมากกว่า 20 บรรทัดคุณสามารถย้อนกลับและลดความซับซ้อนได้
    • ลดความซับซ้อนของรหัสของคุณมากที่สุดในขณะที่รักษาปัญหา / ข้อผิดพลาด

สิ่งนี้ใช้เวลาทำงานบางอย่าง แต่ดูเหมือนเป็นการค้าที่ยุติธรรมเนื่องจากคุณขอให้ผู้อื่นทำงานให้คุณ

การให้ข้อมูล:


ชุดข้อมูลในตัว

เลือกที่ดีที่สุดโดยไกลคือการพึ่งพาตัวในชุดข้อมูล สิ่งนี้ทำให้ผู้อื่นสามารถแก้ไขปัญหาของคุณได้ง่ายมาก พิมพ์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

เป็นทางเลือกสุดท้ายคุณสามารถใช้dputเพื่อแปลงวัตถุข้อมูลเป็นรหัส R (เช่นdput(myData)) ฉันพูดว่าเป็น "วิธีสุดท้าย" เพราะผลลัพธ์ของdputมักจะเทอะทะค่อนข้างน่ารำคาญคัดลอกวางและปิดบังส่วนที่เหลือของคำถามของคุณ

ให้ผลลัพธ์ที่คาดหวัง:


มีคนเคยพูดว่า:

รูปภาพของเอาต์พุตที่คาดหวังมีค่า 1,000 คำ

- เป็นคนฉลาดมาก

หากคุณสามารถเพิ่มบางสิ่งเช่น "ฉันคาดว่าจะได้ผลลัพธ์นี้"

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

สำหรับคำถามของคุณผู้คนมักจะเข้าใจสิ่งที่คุณพยายามทำอย่างรวดเร็ว หากผลลัพธ์ที่คุณคาดหวังมีขนาดใหญ่และไม่แน่นอนคุณอาจไม่ได้คิดมากพอที่จะทำให้ปัญหาของคุณง่ายขึ้น (ดูต่อไป)

อธิบายปัญหาของคุณอย่างชัดเจน


สิ่งสำคัญที่ต้องทำคือลดความซับซ้อนของปัญหาให้มากที่สุดก่อนที่คุณจะถามคำถาม การกำหนดกรอบปัญหาให้ทำงานกับชุดข้อมูลในตัวจะช่วยได้มากในเรื่องนี้ คุณมักจะพบว่าเพียงแค่ผ่านกระบวนการทำให้เข้าใจง่ายคุณจะตอบปัญหาของคุณเอง

นี่คือตัวอย่างของคำถามที่ดี:

ในทั้งสองกรณีปัญหาของผู้ใช้นั้นแทบจะไม่ได้เกิดจากตัวอย่างง่ายๆที่พวกเขาให้มา แต่พวกเขาแยกแยะธรรมชาติของปัญหาและนำไปใช้กับชุดข้อมูลอย่างง่ายเพื่อถามคำถาม

ทำไมยังมีคำตอบสำหรับคำถามนี้อีก?


คำตอบนี้มุ่งเน้นไปที่สิ่งที่ฉันคิดว่าเป็นแนวปฏิบัติที่ดีที่สุด: ใช้ชุดข้อมูลในตัวและให้สิ่งที่คุณคาดหวังจากผลลัพธ์ที่ได้ในรูปแบบที่น้อยที่สุด คำตอบที่โดดเด่นที่สุดมุ่งเน้นด้านอื่น ๆ ฉันไม่คาดหวังคำตอบนี้เพื่อเพิ่มความโดดเด่นใด ๆ ; นี่คือที่นี่ แต่เพียงผู้เดียวเพื่อให้ฉันสามารถเชื่อมโยงไปในความคิดเห็นคำถามมือใหม่


113

รหัสที่ทำซ้ำได้เป็นกุญแจสำคัญในการขอความช่วยเหลือ อย่างไรก็ตามมีผู้ใช้จำนวนมากที่อาจสงสัยว่าจะมีการวางข้อมูลจำนวนมาก ตัวอย่างเช่นพวกเขาอาจทำงานกับข้อมูลที่ละเอียดอ่อนหรือข้อมูลต้นฉบับที่รวบรวมเพื่อใช้ในรายงานการวิจัย ด้วยเหตุผลใดก็ตามฉันคิดว่ามันคงจะดีถ้ามีฟังก์ชั่นที่ใช้งานง่ายสำหรับ "การเปลี่ยนรูป" ข้อมูลของฉันก่อนที่จะวางมันต่อสาธารณะ 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

หนึ่งอาจต้องการตัวอย่างตัวแปรน้อยแทนข้อมูลทั้งหมดก่อนที่จะใช้คำสั่งไม่ระบุชื่อและคำสั่ง 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

บ่อยครั้งที่คุณต้องการข้อมูลบางอย่างอย่างไรก็ตามคุณไม่ต้องการโพสต์ข้อมูลที่แน่นอน หากต้องการใช้ data.frame ที่มีอยู่บางตัวในไลบรารีที่สร้างขึ้นให้ใช้คำสั่ง data เพื่อนำเข้า

เช่น,

data(mtcars)

แล้วทำปัญหา

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

13
ชุดข้อมูลในตัวหลายชุด (เช่นชุดข้อมูลยอดนิยมmtcarsและirisชุดข้อมูล) ไม่จำเป็นต้องใช้การdataโทรจริง
Gregor Thomas

92

หากคุณมีชุดข้อมูลขนาดใหญ่ซึ่งไม่สามารถนำไปใช้กับสคริปต์ได้อย่างง่ายดายให้dput()โพสต์ข้อมูลของคุณไปที่pastebinและโหลดโดยใช้read.table:

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

แรงบันดาลใจจาก@Henrik


90

ฉันกำลังพัฒนาเวกแพคเกจที่อยู่ต้องนี้ได้อย่างรวดเร็วแบ่งปันข้อมูลทำซ้ำบางครั้ง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
.. ...   ... ...    ...      ... ...    ...   ...

72

หากคุณมีfactorตัวแปรอย่างน้อยหนึ่งตัวในข้อมูลของคุณที่คุณต้องการให้ทำซ้ำได้dput(head(mydata))ให้พิจารณาเพิ่มdroplevelsลงไปเพื่อให้ระดับของปัจจัยที่ไม่ปรากฏในชุดข้อมูลที่ย่อเล็กสุดจะไม่รวมอยู่ในdputผลลัพธ์ของคุณทำให้ตัวอย่างน้อยที่สุด :

dput(droplevels(head(mydata)))

65

ฉันสงสัยว่าลิงก์http://old.r-fiddle.org/อาจเป็นวิธีที่ใช้งานได้ดีมากในการแบ่งปันปัญหา มันได้รับ ID ที่ไม่เหมือนใครและใคร ๆ ก็สามารถคิดได้ว่าฝังไว้ใน SO


47

โปรดอย่าวางเอาต์พุตคอนโซลของคุณเช่นนี้:

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

อีกอย่างหนึ่งถ้าคุณใช้ฟังก์ชั่นใด ๆ จากบางแพ็คเกจพูดถึงไลบรารี่นั้น


2
คุณลบ>และเพิ่ม#ด้วยตนเองหรือมีวิธีการทำเช่นนั้นโดยอัตโนมัติ?
BCArg

3
@BCArg ฉันลบ>ด้วยตนเอง แต่สำหรับการเพิ่มเติม#ฉันใช้Ctrl+Shift+CทางลัดในตัวRStudioแก้ไข
user2100721

33

คุณสามารถทำได้โดยใช้reprex reprex

ดังที่mt1022 ตั้งข้อสังเกตว่า "... แพคเกจที่ดีสำหรับการผลิตตัวอย่างที่ทำซ้ำได้น้อยที่สุดคือ" reprex "จากtidyverse "

ตามที่Tidyverse :

เป้าหมายของ "reprex" คือการบรรจุรหัสที่มีปัญหาของคุณในแบบที่คนอื่นสามารถวิ่งได้และรู้สึกถึงความเจ็บปวดของคุณ

ตัวอย่างที่จะได้รับในtidyverseเว็บไซต์

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

ฉันคิดว่านี่เป็นวิธีที่ง่ายที่สุดในการสร้างตัวอย่างที่ทำซ้ำได้


33

นอกเหนือจากคำตอบข้างต้นทั้งหมดที่ฉันพบว่าน่าสนใจมากบางครั้งอาจเป็นเรื่องง่ายมากตามที่กล่าวไว้ที่นี่: - วิธีทำตัวอย่างแบบจำลองขั้นต่ำสุดเพื่อรับความช่วยเหลือด้วย R

มีหลายวิธีในการสร้างเวกเตอร์แบบสุ่มสร้างเวกเตอร์จำนวน 100 ด้วยค่าสุ่มใน R ปัดเศษเป็นทศนิยม 2 ตำแหน่ง หรือเมทริกซ์สุ่มใน R

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

โปรดทราบว่าบางครั้งมันเป็นเรื่องยากมากที่จะแบ่งปันข้อมูลที่กำหนดเนื่องจากเหตุผลต่าง ๆ เช่นมิติ ฯลฯ อย่างไรก็ตามคำตอบทั้งหมดข้างต้นนั้นดีมากและสำคัญมากที่จะต้องคิดและใช้เมื่อต้องการทำตัวอย่างข้อมูลที่ทำซ้ำได้ แต่โปรดทราบว่าในการสร้างข้อมูลในฐานะตัวแทนเหมือนต้นฉบับ (ในกรณีที่ OP ไม่สามารถแบ่งปันข้อมูลดั้งเดิมได้) ควรเพิ่มข้อมูลด้วยตัวอย่างข้อมูลเช่น (ถ้าเราเรียก data 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))

28

นี่คือคำแนะนำของฉัน:

  • ลองใช้ชุดข้อมูล R เริ่มต้น
  • หากคุณมีชุดข้อมูลของคุณเองให้รวมไว้ด้วย dputเพื่อให้ผู้อื่นสามารถช่วยคุณได้ง่ายขึ้น
  • ห้ามใช้install.package()นอกเสียจากว่าจำเป็นจริงๆผู้คนจะเข้าใจถ้าคุณใช้requireหรือlibrary
  • พยายามรัดกุม

    • มีชุดข้อมูลบางส่วน
    • พยายามอธิบายผลลัพธ์ที่คุณต้องการอย่างง่ายดาย
    • ทำมันเองก่อนที่คุณจะถามคำถาม
  • มันง่ายในการอัพโหลดภาพดังนั้นถ้าคุณมีการอัพโหลด
  • รวมถึงข้อผิดพลาดที่คุณอาจมี

ทั้งหมดนี้เป็นส่วนหนึ่งของตัวอย่างที่ทำซ้ำได้


1
คุณยังไม่ได้เพิ่มเนื้อหาใด ๆ ที่นี่ dput()ได้รับการกล่าวถึงก่อนหน้านี้และสิ่งนี้ส่วนใหญ่เป็นเพียงการทบทวนแนวทางแนวทางมาตรฐาน
Rich Scriven

1
ฉันมีปัญหากับinstall.packageฟังก์ชั่นรวมอยู่ในตัวอย่างที่ไม่จำเป็นจริงๆ (ในความคิดของฉัน) นอกจากนี้การใช้ชุดข้อมูล R เริ่มต้นจะทำให้การทำสำเนาง่ายขึ้น แนวทาง SO ไม่ได้พูดอะไรเกี่ยวกับหัวข้อเหล่านี้โดยเฉพาะ ยิ่งกว่านั้นมันมีความหมายที่จะให้ความเห็นของฉันและสิ่งเหล่านี้เป็นสิ่งที่ฉันได้พบมากที่สุด
TheRimalaya

18

เป็นความคิดที่ดีที่จะใช้ฟังก์ชั่นจากtestthatแพ็คเกจเพื่อแสดงสิ่งที่คุณคาดว่าจะเกิดขึ้น ดังนั้นบุคคลอื่นสามารถแก้ไขโค้ดของคุณจนกว่าจะรันโดยไม่มีข้อผิดพลาด วิธีนี้จะช่วยลดภาระของผู้ที่ต้องการช่วยคุณเพราะมันหมายความว่าพวกเขาไม่จำเป็นต้องถอดรหัสคำอธิบายที่เป็นข้อความของคุณ ตัวอย่างเช่น

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

ชัดเจนกว่า "ฉันคิดว่า x จะออกมาเป็น 1.23 สำหรับ y เท่ากับหรือมากกว่า 10 และ 3.21 เป็นอย่างอื่น แต่ฉันไม่ได้ผลลัพธ์" แม้ในตัวอย่างที่โง่เง่านี้ฉันคิดว่ารหัสนั้นชัดเจนกว่าคำพูด การใช้testthatช่วยให้ผู้ช่วยของคุณมุ่งเน้นไปที่โค้ดซึ่งจะช่วยประหยัดเวลาและช่วยให้พวกเขารู้ว่าพวกเขาแก้ไขปัญหาของคุณก่อนที่พวกเขาจะโพสต์มัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.