ฉันทำอะไรกับ dtplyr ไม่ได้ใน data.table


9

ฉันควรจะลงทุนความพยายามในการเรียนรู้ของฉันสำหรับข้อมูลที่ถกเถียงในการวิจัยโดยเฉพาะระหว่างdplyr, dtplyrและdata.table?

  • ฉันใช้dplyrเป็นส่วนใหญ่ แต่เมื่อข้อมูลมีขนาดใหญ่เกินไปสำหรับที่ฉันจะใช้data.tableซึ่งเป็นเหตุการณ์ที่เกิดขึ้นได้ยาก ดังนั้นตอนนี้dtplyrv1.0 ก็กลายเป็นอินเทอร์เฟซสำหรับdata.tableบนพื้นผิวมันดูเหมือนว่าฉันไม่ต้องกังวลกับการใช้data.tableอินเทอร์เฟซอีกเลย

  • ดังนั้นสิ่งที่เป็นคุณสมบัติที่มีประโยชน์มากที่สุดหรือแง่มุมของการdata.tableที่ไม่สามารถทำได้โดยใช้dtplyrในขณะนี้และมีแนวโน้มที่จะไม่เคยทำได้ด้วยdtplyr?

  • บนใบหน้าของตนdplyrกับผลประโยชน์ของการdata.tableทำให้เสียงเหมือนจะแซงdtplyr dplyrมีเหตุผลใดบ้างที่จะใช้dplyrอีกครั้งเมื่อdtplyrครบกำหนด?

หมายเหตุ: ฉันไม่ได้ถามเกี่ยวกับdplyrvs data.table(เช่นเดียวกับdata.table vs dplyr: คนหนึ่งสามารถทำสิ่งที่ดีไม่สามารถหรือไม่ดีได้หรือไม่ ) แต่ให้คนอื่นเป็นที่ต้องการมากกว่าอีกปัญหาหนึ่งทำไมจะไม่ เสื้อdtplyrจะเป็นเครื่องมือในการใช้งาน


1
มีบางอย่างที่คุณทำได้ดีในdplyrสิ่งที่คุณทำไม่ได้data.tableใช่ไหม ถ้าไม่ได้เปลี่ยนไปเป็นไปได้ดีกว่าdata.table dtplyr
sindri_baldur

2
จากdtplyrreadme ' data.tableการแสดงออกบางอย่างไม่dplyrเทียบเท่าโดยตรง ตัวอย่างเช่นไม่มีทางที่จะแสดงการข้ามหรือการรวมเข้าด้วยdplyrกัน ' และ 'เพื่อให้ตรงกับdplyrความหมายmutate() จะไม่แก้ไขโดยค่าเริ่มต้น ซึ่งหมายความว่านิพจน์ส่วนใหญ่ที่เกี่ยวข้องmutate()ต้องทำสำเนาที่ไม่จำเป็นหากคุณใช้data.tableโดยตรง ' มีวิธีรอบส่วนที่สองนั้น แต่พิจารณาว่าmutateมีการใช้บ่อยแค่ไหนนั่นเป็นข้อเสียที่ค่อนข้างใหญ่ในสายตาของฉัน
ClancyStats

คำตอบ:


15

ฉันจะพยายามให้คำแนะนำที่ดีที่สุดของฉัน แต่มันก็ไม่ใช่เรื่องง่ายเพราะต้องมีความคุ้นเคยกับ {data.table}, {dplyr}, {dtplyr} และ {base R} ทั้งหมด ฉันใช้ {data.table} และแพ็คเกจ {tidy-world} จำนวนมาก (ยกเว้น {dplyr}) รักทั้งคู่ แต่ฉันชอบไวยากรณ์ของ data.table ถึง dplyr's ฉันหวังว่าแพ็คเกจที่เป็นระเบียบเรียบร้อยทั่วโลกจะใช้ {dtplyr} หรือ {data.table} เป็นแบ็กเอนด์เมื่อใดก็ตามที่จำเป็น

เช่นเดียวกับการแปลอื่น ๆ (คิดว่า dplyr-to-sparkly / SQL) มีบางสิ่งที่สามารถหรือไม่สามารถแปลได้อย่างน้อยตอนนี้ ฉันหมายความว่าบางทีวันหนึ่ง {dtplyr} สามารถแปลได้ 100% ใครจะรู้ รายการด้านล่างไม่ครบถ้วนสมบูรณ์หรือไม่ถูกต้อง 100% เนื่องจากฉันจะพยายามอย่างดีที่สุดเพื่อตอบตามความรู้ของฉันเกี่ยวกับหัวข้อ / แพ็คเกจ / ปัญหา / อื่น ๆ ที่เกี่ยวข้อง

ที่สำคัญสำหรับคำตอบที่ไม่ถูกต้องทั้งหมดฉันหวังว่ามันจะให้คำแนะนำบางอย่างแก่คุณเกี่ยวกับแง่มุมของ {data.table} ที่คุณควรใส่ใจและเปรียบเทียบกับ {dtplyr} และค้นหาคำตอบด้วยตัวเอง อย่านำคำตอบเหล่านี้ไปใช้

และฉันหวังว่าโพสต์นี้สามารถใช้เป็นหนึ่งในแหล่งข้อมูลสำหรับ {dplyr}, {data.table} หรือ {dtplyr} ผู้ใช้ / ผู้สร้างสำหรับการสนทนาและการทำงานร่วมกันและทำให้ #RStats ดียิ่งขึ้น

{data.table} ไม่ได้ใช้สำหรับการดำเนินการที่รวดเร็วและมีประสิทธิภาพของหน่วยความจำเท่านั้น มีหลายคนรวมถึงตัวผมเองชอบไวยากรณ์ที่หรูหราของ {data.table} นอกจากนี้ยังรวมถึงการทำงานที่รวดเร็วอื่น ๆ เช่นฟังก์ชั่นอนุกรมเวลาเช่นการหมุนของตระกูล (เช่นfrollapply) ที่เขียนใน C มันสามารถใช้กับฟังก์ชั่นใด ๆ รวมถึง tidyverse ฉันใช้ {data.table} + {purrr} มาก!

ความซับซ้อนของการดำเนินงาน

สามารถแปลได้อย่างง่ายดาย

library(data.table)
library(dplyr)
library(flights)
data <- data.table(diamonds)

# dplyr 
diamonds %>%
  filter(cut != "Fair") %>% 
  group_by(cut) %>% 
  summarize(
    avg_price    = mean(price),
    median_price = as.numeric(median(price)),
    count        = n()
  ) %>%
  arrange(desc(count))

# data.table
data [
  ][cut != 'Fair', by = cut, .(
      avg_price    = mean(price),
      median_price = as.numeric(median(price)),
      count        = .N
    )
  ][order( - count)]

{data.table} มีความรวดเร็วและหน่วยความจำที่มีประสิทธิภาพเพราะ (เกือบ?) ทุกอย่างถูกสร้างขึ้นจากพื้นดินขึ้นจาก C ด้วยแนวคิดหลักของการอัปเดตโดยอ้างอิงคีย์ (คิดว่า SQL) และการเพิ่มประสิทธิภาพอย่างไม่หยุดยั้งทุกที่ในแพ็คเกจ (เช่นfifelse, การfread/freadเรียงลำดับ radix ที่นำมาใช้โดยฐาน R), ในขณะที่ทำให้แน่ใจว่าไวยากรณ์มีความกระชับและสอดคล้องกันนั่นคือเหตุผลที่ฉันคิดว่ามันสง่างาม

จากIntroduction to data.tableการดำเนินการจัดการข้อมูลหลักเช่นเซ็ตย่อยกลุ่มอัปเดตเข้าร่วม ฯลฯจะถูกเก็บไว้ด้วยกัน

  • กระชับและไวยากรณ์ที่สอดคล้องกัน ...

  • ดำเนินการวิเคราะห์อย่างคล่องแคล่วโดยไม่ต้องรับภาระความรู้ความเข้าใจในการทำแผนที่แต่ละการดำเนินการ ...

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

จุดสุดท้ายเป็นตัวอย่าง

# Calculate the average arrival and departure delay for all flights with “JFK” as the origin airport in the month of June.
flights[origin == 'JFK' & month == 6L,
        .(m_arr = mean(arr_delay), m_dep = mean(dep_delay))]
  • เราเซตย่อยแรกใน i เพื่อค้นหาดัชนีแถวที่ตรงกันที่สนามบินต้นทางเท่ากับ "JFK" และเดือนเท่ากับ 6L เรายังไม่ได้ย่อย data.table ทั้งหมดที่สอดคล้องกับแถวเหล่านั้น

  • ตอนนี้เราดูที่ j และพบว่ามันใช้เพียงสองคอลัมน์ และสิ่งที่เราต้องทำคือการคำนวณค่าเฉลี่ย () ดังนั้นเราจึงเซ็ตเฉพาะคอลัมน์ที่สอดคล้องกับแถวที่ตรงกันและคำนวณค่าเฉลี่ย ()

เพราะสามองค์ประกอบหลักของแบบสอบถาม (ฉัน j และ) อยู่ด้วยกันภายใน [ ... ] , data.table สามารถมองเห็นทั้งสามและเพิ่มประสิทธิภาพการค้นหาทั้งหมดก่อนที่จะประเมินผลไม่ได้แยกจากกัน เราสามารถหลีกเลี่ยงชุดย่อยทั้งหมด (เช่นการแบ่งคอลัมน์นอกเหนือจาก arr_delay และ dep_delay) สำหรับทั้งความเร็วและประสิทธิภาพของหน่วยความจำ

ระบุว่าในการเก็บเกี่ยวผลประโยชน์ของ {data.table} การแปลของ {dtplr} จะต้องถูกต้องตามลำดับนั้น การดำเนินงานที่ซับซ้อนมากขึ้นการแปลที่ยากขึ้น สำหรับการดำเนินการอย่างง่ายเช่นด้านบนจะสามารถแปลได้อย่างง่ายดาย สำหรับผู้ที่มีความซับซ้อนหรือผู้ที่ไม่ได้รับการสนับสนุนโดย {dtplyr} คุณต้องค้นหาด้วยตัวคุณเองตามที่กล่าวไว้ข้างต้นเราจะต้องเปรียบเทียบไวยากรณ์ที่แปลแล้วและการเปรียบเทียบและเป็นแพคเกจที่เกี่ยวข้องที่คุ้นเคย

สำหรับการดำเนินการที่ซับซ้อนหรือการดำเนินการที่ไม่ได้รับการสนับสนุนฉันอาจให้ตัวอย่างด้านล่าง อีกครั้งฉันแค่พยายามทำให้ดีที่สุด อ่อนโยนกับฉัน

ปรับปรุงโดยการอ้างอิง

ฉันจะไม่เข้าไปในบทนำ / รายละเอียด แต่นี่คือลิงค์

ทรัพยากรหลัก: ความหมายอ้างอิง

รายละเอียดเพิ่มเติม: ทำความเข้าใจอย่างถูกต้องเมื่อ data.table เป็นการอ้างอิงถึง (เทียบกับสำเนา) data.table อื่น

โดยอ้างอิงจากการปรับปรุงฉันคิดว่าคุณสมบัติที่สำคัญที่สุดของ {data.table} และนั่นคือสิ่งที่ทำให้มันเร็วและมีประสิทธิภาพของหน่วยความจำ dplyr::mutateไม่สนับสนุนตามค่าเริ่มต้น เนื่องจากฉันไม่คุ้นเคยกับ {dtplyr} ฉันจึงไม่แน่ใจว่าจำนวนเท่าใดและ {dtplyr} สนับสนุนการดำเนินการใดได้บ้างและไม่สามารถรองรับได้ ดังกล่าวข้างต้นก็ยังขึ้นอยู่กับความซับซ้อนของการดำเนินงานซึ่งจะมีผลต่อการแปล

มีสองวิธีในการใช้การอัปเดตโดยอ้างอิงใน {data.table}

  • ผู้ประกอบการที่ได้รับมอบหมายของ {data.table} :=

  • set-Family: set, setnames, setcolorder, setkey, setDT, fsetdiffและอื่น ๆ อีกมากมาย

:=setเป็นที่นิยมใช้มากขึ้นเมื่อเทียบกับ สำหรับชุดข้อมูลที่ซับซ้อนและมีขนาดใหญ่การอัพเดทโดยอ้างอิงเป็นกุญแจสำคัญในการรับความเร็วสูงสุดและประสิทธิภาพของหน่วยความจำ วิธีคิดที่ง่าย (ไม่ถูกต้อง 100% เนื่องจากรายละเอียดซับซ้อนกว่านี้มากเนื่องจากเกี่ยวข้องกับการคัดลอกที่ยาก / ตื้นและปัจจัยอื่น ๆ อีกมากมาย) สมมติว่าคุณกำลังจัดการกับชุดข้อมูลขนาดใหญ่ 10GB โดยมี 10 คอลัมน์และ 1GB แต่ละรายการ . หากต้องการจัดการหนึ่งคอลัมน์คุณต้องจัดการกับ 1GB เท่านั้น

จุดสำคัญคือด้วยการอ้างอิงโดยการอัพเดตคุณจะต้องจัดการกับข้อมูลที่จำเป็นเท่านั้น นั่นเป็นเหตุผลที่เมื่อใช้ {data.table} โดยเฉพาะการจัดการกับชุดข้อมูลขนาดใหญ่เราใช้การอัปเดตอ้างอิงตลอดเวลาเมื่อใดก็ตามที่เป็นไปได้ ตัวอย่างเช่นการจัดการชุดข้อมูลการสร้างแบบจำลองขนาดใหญ่

# Manipulating list columns

df <- purrr::map_dfr(1:1e5, ~ iris)
dt <- data.table(df)

# data.table
dt [,
    by = Species, .(data   = .( .SD )) ][,  # `.(` shorthand for `list`
    model   := map(data, ~ lm(Sepal.Length ~ Sepal.Width, data = . )) ][,
    summary := map(model, summary) ][,
    plot    := map(data, ~ ggplot( . , aes(Sepal.Length, Sepal.Width)) +
                           geom_point())]

# dplyr
df %>% 
  group_by(Species) %>% 
  nest() %>% 
  mutate(
    model   = map(data, ~ lm(Sepal.Length ~ Sepal.Width, data = . )),
    summary = map(model, summary),
    plot    = map(data, ~ ggplot( . , aes(Sepal.Length, Sepal.Width)) +
                          geom_point())
  )

การดำเนินการซ้อนlist(.SD)อาจไม่รองรับโดย {dtlyr} ตามที่ผู้ใช้ tidyverse ใช้tidyr::nest? ดังนั้นฉันไม่แน่ใจว่าการดำเนินการที่ตามมาสามารถแปลเป็นวิธีของ {data.table} ได้เร็วขึ้นและมีหน่วยความจำน้อยลง

หมายเหตุ: ผลลัพธ์ของ data.table เป็น "มิลลิวินาที", dplyr ใน "นาที"

df <- purrr::map_dfr(1:1e5, ~ iris)
dt <- copy(data.table(df))

bench::mark(
  check = FALSE,

  dt[, by = Species, .(data = list(.SD))],
  df %>% group_by(Species) %>% nest()
)
# # A tibble: 2 x 13
#   expression                                   min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc
#   <bch:expr>                              <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int> <dbl>
# 1 dt[, by = Species, .(data = list(.SD))] 361.94ms 402.04ms   2.49      705.8MB     1.24     2     1
# 2 df %>% group_by(Species) %>% nest()        6.85m    6.85m   0.00243     1.4GB     2.28     1   937
# # ... with 5 more variables: total_time <bch:tm>, result <list>, memory <list>, time <list>,
# #   gc <list>

มีหลายกรณีการใช้งานของการอัพเดทโดยอ้างอิงและแม้กระทั่งผู้ใช้ {data.table} จะไม่ใช้เวอร์ชันขั้นสูงตลอดเวลาเนื่องจากต้องการรหัสเพิ่มเติม ไม่ว่าจะเป็น {dtplyr} สนับสนุนนอกกรอบเหล่านี้คุณต้องค้นหาด้วยตนเอง

การอัพเดทโดยอ้างอิงหลายครั้งสำหรับฟังก์ชั่นเดียวกัน

ทรัพยากรหลัก: การกำหนดคอลัมน์หลายคอลัมน์อย่างสง่างามใน data.table ด้วย lapply ()

นี้เกี่ยวข้องกับการอย่างใดอย่างหนึ่งที่ใช้กันทั่วไปมากขึ้นหรือ:=set

dt <- data.table( matrix(runif(10000), nrow = 100) )

# A few variants

for (col in paste0('V', 20:100))
  set(dt, j = col, value = sqrt(get(col)))

for (col in paste0('V', 20:100))
  dt[, (col) := sqrt(get(col))]

# I prefer `purrr::map` to `for`
library(purrr)
map(paste0('V', 20:100), ~ dt[, (.) := sqrt(get(.))])

ตามผู้สร้างของ {data.table} Matt Dowle

(โปรดสังเกตว่าอาจเป็นการทั่วไปมากกว่าที่จะวนซ้ำตั้งแถวจำนวนมากมากกว่าคอลัมน์จำนวนมาก)

เข้าร่วม + setkey + อัปเดตโดยอ้างอิง

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

ฉันทำเกณฑ์มาตรฐานที่นี่: data.table join + update-by-reference + setkey

สรุป

# For brevity, only the codes for join-operation are shown here. Please refer to the link for details

# Normal_join
x <- y[x, on = 'a']

# update_by_reference
x_2[y_2, on = 'a', c := c]

# setkey_n_update
setkey(x_3, a) [ setkey(y_3, a), on = 'a', c := c ]

หมายเหตุ: dplyr::left_joinได้รับการทดสอบแล้วและช้าที่สุดด้วย ~ 9,000 ms ใช้หน่วยความจำมากกว่าทั้ง {data.table} update_by_referenceและsetkey_n_updateใช้หน่วยความจำน้อยกว่า normal_join {data.table} ของ ใช้หน่วยความจำประมาณ ~ 2.0GB ฉันไม่ได้รวมไว้เพราะฉันต้องการมุ่งเน้นที่ {data.table} เพียงอย่างเดียว

การค้นพบที่สำคัญ

  • setkey + updateและupdateจะเร็วกว่า ~ 11 และ ~ 6.5 เท่าnormal joinตามลำดับ
  • เมื่อเข้าร่วมครั้งแรกประสิทธิภาพการทำงานของsetkey + updateจะคล้ายกับupdateค่าใช้จ่ายsetkeyส่วนใหญ่ชดเชยประสิทธิภาพการทำงานของตัวเอง
  • ในการเข้าร่วมครั้งที่สองและครั้งต่อไปตามที่setkeyไม่จำเป็นsetkey + updateจะเร็วกว่าupdate~ 1.8 เท่า (หรือเร็วกว่าnormal joinโดย ~ 11 ครั้ง)

ภาพ

ตัวอย่าง

สำหรับนักแสดงและการรวมหน่วยความจำอย่างมีประสิทธิภาพให้ใช้วิธีใดวิธีหนึ่งupdateหรือsetkey + updateในกรณีที่รหัสหลังเร็วกว่าโดยมีรหัสเพิ่มเติม

เรามาดูโค้ดหลอกๆ เพื่อความกระชับ logics เหมือนกัน

สำหรับหนึ่งหรือสองสามคอลัมน์

a <- data.table(x = ..., y = ..., z = ..., ...)
b <- data.table(x = ..., y = ..., z = ..., ...)

# `update`
a[b, on = .(x), y := y]
a[b, on = .(x),  `:=` (y = y, z = z, ...)]
# `setkey + update`
setkey(a, x) [ setkey(b, x), on = .(x), y := y ]
setkey(a, x) [ setkey(b, x), on = .(x),  `:=` (y = y, z = z, ...) ]

สำหรับหลายคอลัมน์

cols <- c('x', 'y', ...)
# `update`
a[b, on = .(x), (cols) := mget( paste0('i.', cols) )]
# `setkey + update`
setkey(a, x) [ setkey(b, x), on = .(x), (cols) := mget( paste0('i.', cols) ) ]

Wrapper ได้อย่างรวดเร็วและมีประสิทธิภาพหน่วยความจำร่วม ... หลายคน ... ที่มีลักษณะคล้ายกันเข้าร่วมรูปแบบห่อพวกเขาเช่นsetjoinเหนือ - กับupdate - มีหรือไม่มีsetkey

setjoin(a, b, on = ...)  # join all columns
setjoin(a, b, on = ..., select = c('columns_to_be_included', ...))
setjoin(a, b, on = ..., drop   = c('columns_to_be_excluded', ...))
# With that, you can even use it with `magrittr` pipe
a %>%
  setjoin(...) %>%
  setjoin(...)

ด้วยsetkeyอาร์กิวเมนต์onสามารถละเว้นได้ นอกจากนี้ยังสามารถรวมไว้เพื่อให้สามารถอ่านได้โดยเฉพาะอย่างยิ่งสำหรับการร่วมมือกับผู้อื่น

การดำเนินงานแถวขนาดใหญ่

  • ดังกล่าวข้างต้นใช้ set
  • เติมข้อมูลในตารางของคุณล่วงหน้าใช้เทคนิคการอัพเดทอ้างอิง
  • เซ็ตย่อยโดยใช้คีย์ (เช่นsetkey)

ทรัพยากรที่เกี่ยวข้อง: เพิ่มแถวโดยการอ้างอิงที่ท้ายวัตถุ data.table

สรุปการอัพเดทโดยอ้างอิง

เหล่านี้เป็นเพียงบางกรณีการใช้การปรับปรุงโดยการอ้างอิง ยังมีอีกมากมาย

อย่างที่คุณเห็นสำหรับการใช้งานขั้นสูงในการจัดการกับข้อมูลขนาดใหญ่มีหลายกรณีการใช้งานและเทคนิคการใช้การปรับปรุงโดยอ้างอิงสำหรับชุดข้อมูลขนาดใหญ่ ไม่ใช่เรื่องง่ายที่จะใช้ใน {data.table} และไม่ว่า {dtplyr} สนับสนุนคุณสามารถค้นหาด้วยตนเอง

ฉันมุ่งเน้นที่การอ้างอิงโดยอัปเดตในโพสต์นี้เนื่องจากฉันคิดว่ามันเป็นคุณสมบัติที่ทรงพลังที่สุดของ {data.table} สำหรับการดำเนินการที่รวดเร็วและมีประสิทธิภาพของหน่วยความจำ ที่กล่าวว่ามีหลายแง่มุมอื่น ๆ อีกมากมายที่ทำให้มีประสิทธิภาพเช่นกันและฉันคิดว่าไม่สนับสนุนโดย {dtplyr}

ประเด็นสำคัญอื่น ๆ

อะไรคือสิ่งที่ / ไม่สนับสนุนก็ยังขึ้นอยู่กับความซับซ้อนของการดำเนินงานและไม่ว่าจะเกี่ยวข้องกับของ data.table คุณลักษณะพื้นเมืองเช่นการปรับปรุงโดยการอ้างอิงsetkeyหรือ และไม่ว่าโค้ดที่แปลแล้วจะมีประสิทธิภาพมากกว่าหรือไม่ (หนึ่งที่ผู้ใช้ data.table เขียนจะเขียน) ก็เป็นอีกปัจจัยหนึ่ง (นั่นคือการแปลโค้ด แต่เป็นรุ่นที่มีประสิทธิภาพหรือไม่) หลายสิ่งเชื่อมต่อกัน

หลายแง่มุมเหล่านี้เกี่ยวข้องกับประเด็นที่กล่าวถึงข้างต้น

  • ความซับซ้อนของการดำเนินงาน

  • การปรับปรุงโดยการอ้างอิง

คุณสามารถค้นหาว่า {dtplyr} สนับสนุนการดำเนินการเหล่านี้โดยเฉพาะเมื่อรวมเข้าด้วยกันหรือไม่

อีกเทคนิคที่มีประโยชน์เมื่อจัดการกับชุดข้อมูลขนาดเล็กหรือขนาดใหญ่ในระหว่างเซสชันแบบโต้ตอบ {data.table} มีชีวิตจริงตามคำสัญญาในการลดการเขียนโปรแกรมและคำนวณเวลาอย่างมาก

การตั้งค่าคีย์สำหรับตัวแปรที่ใช้ซ้ำสำหรับทั้งความเร็วและ 'ชื่อแถวที่อัดมากเกินไป' (ชุดย่อยโดยไม่ระบุชื่อตัวแปร)

dt <- data.table(iris)
setkey(dt, Species) 

dt['setosa',    do_something(...), ...]
dt['virginica', do_another(...),   ...]
dt['setosa',    more(...),         ...]

# `by` argument can also be omitted, particularly useful during interactive session
# this ultimately becomes what I call 'naked' syntax, just type what you want to do, without any placeholders. 
# It's simply elegant
dt['setosa', do_something(...), Species, ...]

หากการดำเนินการของคุณเกี่ยวข้องกับวิธรรมดา ๆ อย่างในตัวอย่างแรก {dtplyr} สามารถทำให้งานสำเร็จ สำหรับผู้ที่มีความซับซ้อน / ไม่ได้รับการสนับสนุนคุณสามารถใช้คำแนะนำนี้เพื่อเปรียบเทียบคำแปลที่แปลแล้วของ {dtplyr} กับผู้ใช้ data.table ที่มีประสบการณ์ในการเขียนโค้ดด้วยวิธีที่รวดเร็วและมีประสิทธิภาพของหน่วยความจำกับไวยากรณ์ที่หรูหราของ data.table การแปลไม่ได้หมายความว่าเป็นวิธีที่มีประสิทธิภาพมากที่สุดเนื่องจากอาจมีเทคนิคที่แตกต่างกันในการจัดการกับกรณีข้อมูลขนาดใหญ่ที่แตกต่างกัน สำหรับชุดข้อมูลที่ใหญ่ขึ้นคุณสามารถรวม {data.table} กับ{disk.frame} , {fst}และ{drake}และแพ็คเกจสุดเจ๋งอื่น ๆ เพื่อให้ได้ประโยชน์สูงสุด นอกจากนี้ยังมี{big.data.table}แต่ขณะนี้ไม่ได้ใช้งาน

ฉันหวังว่ามันจะช่วยทุกคน ขอให้มีความสุขมาก ๆ ในวันนี้☺☺


2

การรวมที่ไม่ใช่ของ Equi และการรวมเข้าด้วยกันเป็นสิ่งสำคัญ ดูเหมือนจะไม่มีแผนใด ๆ ที่จะรวมฟังก์ชั่นที่เทียบเท่าเลยใน dplyr ดังนั้นจึงไม่มีอะไรที่จะแปล dtplyr ได้

นอกจากนี้ยังมีการปรับแต่ง (dcast ที่เหมาะสมที่สุดและละลายเทียบเท่ากับฟังก์ชั่นเดียวกันใน reshape2) ที่ไม่ได้อยู่ใน dplyr ด้วย

ขณะนี้ฟังก์ชั่น * _if และ * _at ทั้งหมดไม่สามารถแปลด้วย dtplyr ได้เช่นกัน แต่ฟังก์ชันเหล่านั้นยังอยู่ในการทำงาน


0

อัปเดตคอลัมน์เมื่อเข้าร่วมเทคนิค. SD บางฟังก์ชั่น f และพระเจ้ารู้ดีว่ามีอะไรอีกบ้างเพราะ #rdatable เป็นมากกว่าห้องสมุดที่ธรรมดาและไม่สามารถสรุปได้ด้วยฟังก์ชั่นบางอย่าง

มันเป็นระบบนิเวศทั้งหมดด้วยตัวมันเอง

ฉันไม่เคยต้องการ dplyr ตั้งแต่วันที่ฉันเริ่มต้น R เพราะ data.table เป็นสิ่งที่ดีมาก

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