ภาพรวม
ฉันค่อนข้างคุ้นเคยกับไม่มากด้วยdata.table
dplyr
ฉันได้อ่านdplyr
บทความสั้น ๆและตัวอย่างที่ผุดขึ้นมาบน SO และจนถึงตอนนี้ข้อสรุปของฉันก็คือ:
data.table
และdplyr
เทียบเคียงได้กับความเร็วยกเว้นเมื่อมีหลายกลุ่ม (เช่น> 10-100K) และในบางกรณี (ดูมาตรฐานด้านล่าง)dplyr
มีไวยากรณ์ที่เข้าถึงได้มากขึ้นdplyr
บทคัดย่อ (หรือจะ) ปฏิสัมพันธ์ DB ที่มีศักยภาพ- มีความแตกต่างการทำงานเล็กน้อย (ดู "ตัวอย่าง / การใช้งาน" ด้านล่าง)
ในใจของฉัน 2. ไม่ได้รับน้ำหนักมากเพราะฉันค่อนข้างคุ้นเคยกับมันdata.table
แต่ฉันเข้าใจว่าสำหรับผู้ใช้ที่เพิ่งเริ่มใช้ทั้งสองจะเป็นปัจจัยสำคัญ data.table
ฉันต้องการที่จะหลีกเลี่ยงการโต้แย้งเกี่ยวกับการที่สามารถใช้งานง่ายมากขึ้นเป็นที่ไม่เกี่ยวข้องสำหรับคำถามที่เฉพาะเจาะจงของฉันถามจากมุมมองของคนที่คุ้นเคยกับ ฉันยังต้องการหลีกเลี่ยงการอภิปรายเกี่ยวกับวิธีการที่ "ใช้งานง่ายมากขึ้น" นำไปสู่การวิเคราะห์ที่รวดเร็วขึ้น (แน่นอนจริง แต่อีกครั้งไม่ใช่สิ่งที่ฉันสนใจมากที่สุดที่นี่)
คำถาม
สิ่งที่ฉันอยากรู้คือ:
- มีงานการวิเคราะห์ที่ง่ายกว่าในการเขียนโค้ดด้วยแพ็คเกจหนึ่งหรืออีกแพคเกจสำหรับผู้ที่คุ้นเคยกับแพ็คเกจ (เช่นการกดแป้นบางอย่างร่วมกับการใช้ระดับ esotericism ที่ต้องการ
- มีงานวิเคราะห์ที่ดำเนินการอย่างมีนัยสำคัญ (เช่นมากกว่า 2x) มีประสิทธิภาพมากกว่าในแพ็คเกจหนึ่งเทียบกับแพ็คเกจอื่น
หนึ่งคำถามดังนั้นเมื่อเร็ว ๆ นี้มีฉันคิดเกี่ยวกับเรื่องนี้มากขึ้นอีกนิดเพราะจนถึงจุดที่ผมไม่คิดว่าจะมีมากเกินกว่าสิ่งที่ฉันสามารถทำได้ในdplyr
data.table
นี่คือdplyr
วิธีแก้ปัญหา (ข้อมูลเมื่อสิ้นสุด Q):
dat %.%
group_by(name, job) %.%
filter(job != "Boss" | year == min(year)) %.%
mutate(cumu_job2 = cumsum(job2))
ซึ่งดีกว่าความพยายามแฮ็คของฉันในการdata.table
แก้ปัญหา ที่กล่าวว่าdata.table
วิธีแก้ปัญหาที่ดีก็ค่อนข้างดี (ขอบคุณ Jean-Robert, อรุณและทราบที่นี่ฉันชอบคำสั่งเดียวมากกว่าทางออกที่ดีที่สุดอย่างเคร่งครัด):
setDT(dat)[,
.SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)],
by=list(id, job)
]
ไวยากรณ์สำหรับหลังอาจดูลึกลับมาก แต่จริง ๆ แล้วมันค่อนข้างตรงไปตรงมาถ้าคุณคุ้นเคยdata.table
(กล่าวคือไม่ได้ใช้กลอุบายลึกลับเพิ่มเติม)
นึกคิดสิ่งที่ฉันต้องการจะดูเป็นตัวอย่างที่ดีบางอย่างที่เป็นdplyr
หรือdata.table
วิธีที่มีความรัดกุมมากขึ้นหรือทำงานได้ดีขึ้นอย่างมีนัยสำคัญ
ตัวอย่าง
การใช้dplyr
ไม่อนุญาตการดำเนินการจัดกลุ่มที่ส่งคืนจำนวนแถวโดยพลการ (จากคำถามของ eddiหมายเหตุ: สิ่งนี้ดูเหมือนว่าจะถูกนำมาใช้ในdplyr 0.5เช่นกัน @beginneR แสดงการทำงานที่อาจเกิดขึ้นโดยใช้do
คำตอบของคำถาม @ eddi)data.table
รองรับการเข้าร่วมกลิ้ง (ขอบคุณ @dholstius) เช่นเดียวกับการรวมที่ทับซ้อนกันdata.table
เพิ่มประสิทธิภาพการแสดงออกของแบบฟอร์มภายในDT[col == value]
หรือDT[col %in% values]
เพื่อความเร็วผ่านการจัดทำดัชนีอัตโนมัติซึ่งใช้การค้นหาแบบไบนารีในขณะที่ใช้ไวยากรณ์ R พื้นฐานเดียวกัน ดูที่นี่สำหรับรายละเอียดเพิ่มเติมและมาตรฐานเล็ก ๆdplyr
ข้อเสนอมาตรฐานรุ่นการประเมินผลของฟังก์ชั่น (เช่นregroup
,summarize_each_
) ที่สามารถลดความซับซ้อนของการใช้งานที่ใช้โปรแกรมdplyr
(ใช้การเขียนโปรแกรมจดบันทึกdata.table
เป็นไปได้แน่นอนเพียงแค่ต้องมีความคิดอย่างรอบคอบเปลี่ยนตัว / quoting ฯลฯ อย่างน้อยความรู้ของฉัน)
- ฉันใช้การวัดประสิทธิภาพของตัวเองและพบว่าทั้งสองแพคเกจนั้นสามารถเทียบเคียงได้ในการวิเคราะห์รูปแบบ "แบ่งใช้การรวม" ยกเว้นเมื่อมีกลุ่มจำนวนมาก (> 100K) ที่จุดใด
data.table
กลายเป็นเร็วขึ้นอย่างมาก - @Arun รันการวัดประสิทธิภาพบางส่วนในการเข้าร่วมซึ่งแสดงว่า
data.table
สเกลนั้นดีกว่าdplyr
เมื่อจำนวนกลุ่มเพิ่มขึ้น (อัปเดตด้วยการปรับปรุงล่าสุดทั้งในแพ็คเกจและรุ่นล่าสุดของ R) นอกจากนี้เกณฑ์มาตรฐานเมื่อพยายามรับค่าที่ไม่ซ้ำกันนั้นมีความdata.table
รวดเร็วกว่า ~ 6x - (ไม่ได้ตรวจสอบ) มี
data.table
75% ที่เร็วขึ้นสำหรับกลุ่มขนาดใหญ่ / ใช้ / เรียงลำดับในขณะdplyr
ที่กลุ่มเล็ก ๆ เร็วขึ้น 40% ( คำถาม SO อื่นจากความคิดเห็นขอบคุณ danas) - แมตต์, ผู้เขียนหลักของการ
data.table
ได้วัดประสิทธิผลการจัดกลุ่มในการดำเนินงานdata.table
,dplyr
และงูหลามpandas
ได้ถึง 2 พันล้านแถว (~ 100GB ใน RAM) - มาตรฐานพี่ 80K กลุ่มมี
data.table
~ 8x ได้เร็วขึ้น
ข้อมูล
นี่เป็นตัวอย่างแรกที่ฉันแสดงในส่วนคำถาม
dat <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L), name = c("Jane", "Jane", "Jane", "Jane",
"Jane", "Jane", "Jane", "Jane", "Bob", "Bob", "Bob", "Bob", "Bob",
"Bob", "Bob", "Bob"), year = c(1980L, 1981L, 1982L, 1983L, 1984L,
1985L, 1986L, 1987L, 1985L, 1986L, 1987L, 1988L, 1989L, 1990L,
1991L, 1992L), job = c("Manager", "Manager", "Manager", "Manager",
"Manager", "Manager", "Boss", "Boss", "Manager", "Manager", "Manager",
"Boss", "Boss", "Boss", "Boss", "Boss"), job2 = c(1L, 1L, 1L,
1L, 1L, 1L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L)), .Names = c("id",
"name", "year", "job", "job2"), class = "data.frame", row.names = c(NA,
-16L))
dplyr
และdata.table
ทีมกำลังทำงานกับมาตรฐานดังนั้นคำตอบจะอยู่ที่จุดหนึ่ง # 2 (ไวยากรณ์) imO เป็นเท็จอย่างเคร่งครัด แต่นั่นแสดงให้เห็นอย่างชัดเจนในอาณาเขตความคิดเห็นดังนั้นฉันจึงลงคะแนนให้ปิดเช่นกัน
(d)plyr
มีมาตรการ 0
dplyr
และplyr
เกี่ยวกับไวยากรณ์และเป็นเหตุผลหลักที่ทำไมฉันไม่ชอบไวยากรณ์ของพวกเขาคือฉันต้องเรียนรู้วิธีมากเกินไป (อ่านมากกว่า 1) ฟังก์ชั่นพิเศษ (ชื่อที่ยังคงไม่สมเหตุสมผลสำหรับฉัน) จำสิ่งที่พวกเขาทำข้อโต้แย้งที่พวกเขารับ ฯลฯ ซึ่งเป็นจุดเปลี่ยนครั้งใหญ่สำหรับฉันจากปรัชญาชั้นลึก
.SD
น้อยเพียงใด [จริงจัง] ฉันคิดว่าสิ่งเหล่านี้เป็นความแตกต่างในการออกแบบที่ถูกกฎหมายที่จะดึงดูดผู้คนที่แตกต่างกัน
dplyr
หนึ่งคือ:as.data.table(dat)[, .SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)], by = list(name, job)]