. SD ย่อมาจาก data.table ใน R


173

.SDดูมีประโยชน์ แต่ฉันไม่รู้จริงๆว่าฉันกำลังทำอะไรอยู่ มันหมายถึงอะไร ทำไมถึงมีช่วงเวลาก่อนหน้านี้ (หยุดเต็ม) จะเกิดอะไรขึ้นเมื่อฉันใช้งาน

ฉันอ่านแล้ว: .SDเป็นdata.tableชุดย่อยของxข้อมูลสำหรับแต่ละกลุ่มยกเว้นคอลัมน์กลุ่ม มันสามารถใช้เมื่อจัดกลุ่มโดยi, เมื่อจัดกลุ่มโดยby, คีย์byและ _ad hoc_by

นั่นหมายความว่าลูกสาวdata.tableมีความทรงจำในการปฏิบัติการครั้งต่อไปหรือไม่?


30
?data.tableได้รับการปรับปรุงใน v1.7.10 ขอบคุณคำถามนี้ ตอนนี้อธิบายชื่อ.SDตามคำตอบที่ยอมรับแล้ว
Matt Dowle

คำตอบ:


205

.SDย่อมาจากบางสิ่งเช่น " Subset of Data.table" ไม่มีความสำคัญในการเริ่มต้น"."ยกเว้นว่ามันทำให้มันไม่น่าเป็นไปได้มากขึ้นว่าจะมีการปะทะกันกับชื่อคอลัมน์ที่ผู้ใช้กำหนด

ถ้านี่คือ data.table ของคุณ:

DT = data.table(x=rep(c("a","b","c"),each=2), y=c(1,3), v=1:6)
setkey(DT, y)
DT
#    x y v
# 1: a 1 1
# 2: b 1 3
# 3: c 1 5
# 4: a 3 2
# 5: b 3 4
# 6: c 3 6

การทำเช่นนี้อาจช่วยให้คุณเห็นสิ่งที่.SD:

DT[ , .SD[ , paste(x, v, sep="", collapse="_")], by=y]
#    y       V1
# 1: 1 a1_b3_c5
# 2: 3 a2_b4_c6

โดยพื้นฐานแล้วby=yคำสั่งจะแบ่งข้อมูลดั้งเดิมออกเป็นสองส่วนย่อยdata.tables

DT[ , print(.SD), by=y]
# <1st sub-data.table, called '.SD' while it's being operated on>
#    x v
# 1: a 1
# 2: b 3
# 3: c 5
# <2nd sub-data.table, ALSO called '.SD' while it's being operated on>
#    x v
# 1: a 2
# 2: b 4
# 3: c 6
# <final output, since print() doesn't return anything>
# Empty data.table (0 rows) of 1 col: y

และดำเนินการกับพวกเขาในทางกลับกัน

ในขณะที่มันมีการดำเนินงานเกี่ยวกับคนใดคนหนึ่งจะช่วยให้คุณดูที่ย่อยในปัจจุบันโดยใช้ชื่อเล่นdata.table / จับ / สัญลักษณ์ .SDมันมีประโยชน์มากเพราะคุณสามารถเข้าถึงและใช้งานคอลัมน์ได้ราวกับว่าคุณกำลังนั่งอยู่ที่บรรทัดคำสั่งที่ทำงานกับ data.table เดียวที่เรียกว่า.SD... ยกเว้นที่นี่data.tableจะทำการดำเนินการเหล่านั้นในทุก ๆ ย่อยที่data.tableกำหนดโดย การรวมกันของคีย์ "วาง" พวกเขากลับมารวมกันและส่งคืนผลลัพธ์ในหนึ่งเดียวdata.table!


12
ใช่แล้ว วิธีการที่จะดูอีกคือ.SD DT[,print(.SD),by=y]
Matt Dowle

6
@MatthewDowle - ในขณะที่คุณอยู่ที่นี่คำถามสำหรับคุณ ทำDT[,print(.SD[,y]),by=y]บ่งชี้ว่าฉันมีสิทธิ์เข้าถึงyถึงแม้ว่ามันจะไม่ได้เป็นส่วนหนึ่งของ.SDก็ตาม มูลค่าของyการถูกกำหนดขอบเขตจากที่ใด มี b / c เป็นมูลค่าปัจจุบันbyหรือไม่
Josh O'Brien

8
@Josh Nice ใช่. .SD[,y]เป็นปกติdata.tableเซตดังนั้นตั้งแต่yไม่ได้เป็นคอลัมน์ของ.SDมันก็ดูในสภาพแวดล้อมที่เรียกว่าซึ่งในกรณีนี้เป็นjสภาพแวดล้อม (ของDTแบบสอบถาม) ที่byตัวแปรที่มีอยู่ หากไม่พบที่นั่นจะมีลักษณะเป็นพาเรนต์และพาเรนต์เป็นต้นตามวิธี R ปกติ (ก็คือผ่านการเข้าร่วมขอบเขตที่สืบทอดด้วยซึ่งไม่ได้ใช้ในตัวอย่างเหล่านี้เนื่องจากไม่มีi)
Matt Dowle

1
@Josh คำถามที่พบบ่อย 2.8 มีมากขึ้นในเรื่องนี้อาจต้องปรับปรุง (ยินดีต้อนรับคำแนะนำ)
Matt Dowle

3
@ Josh เพราะตัวแปรกลุ่มที่มีอยู่ในเจเกินไปและมีความยาว 1 by=list(x,y,z)จะหมายถึงx, yและพร้อมที่จะz jสำหรับการเข้าถึงทั่วไปพวกเขาก็ถูกห่อด้วย.BYเช่นกัน คำถามที่พบบ่อย 2.10 มีประวัติบางอย่างกับมัน ?data.tableแต่ความชัดเจนบางอย่างอาจจะเพิ่ม ยอดเยี่ยมความช่วยเหลือจาก docu จะได้รับการต้อนรับอย่างมาก ดียิ่งขึ้นถ้าคุณต้องการเข้าร่วมโครงการและเปลี่ยนโดยตรง
Matt Dowle

98

แก้ไข:

กำหนดวิธีการดีที่ได้รับคำตอบนี้ที่ผมได้แปลงลงในบทความแพคเกจนี้สามารถใช้ได้ที่นี่


เมื่อพิจารณาว่าสิ่งนี้เกิดขึ้นบ่อยแค่ไหนฉันคิดว่าสิ่งนี้รับประกันได้มากกว่าคำอธิบายที่เป็นประโยชน์นอกเหนือจากคำตอบที่มีประโยชน์ของ Josh O'Brien ด้านบน

นอกจากตัวย่อS ubset ของD ata ที่มักจะอ้างถึง / สร้างโดย Josh ฉันคิดว่าการพิจารณา "S" เพื่อยืนสำหรับ "Selfsame" หรือ "Self-reference" .SDนั้นเป็นประโยชน์ในการสะท้อนการอ้างอิงถึงdata.tableตัวเอง - ดังที่เราจะเห็นในตัวอย่างด้านล่างสิ่งนี้มีประโยชน์อย่างยิ่งสำหรับการผูกมัด "ข้อความค้นหา" ร่วมกัน (การแยก / ส่วนย่อย / ฯลฯ โดยใช้[) โดยเฉพาะอย่างยิ่งยังนี้หมายความว่า.SDเป็นตัวเองdata.table (มีข้อแม้ที่ว่ามันไม่ได้ช่วยให้ได้รับมอบหมายด้วย:=)

การใช้งานที่ง่ายขึ้นของใช้.SDสำหรับการแบ่งคอลัมน์ (เช่นเมื่อ.SDcolsมีการระบุ); ฉันคิดว่ารุ่นนี้ตรงไปตรงมามากกว่าที่จะเข้าใจดังนั้นเราจะพูดถึงเรื่องนี้ก่อน การตีความ.SDในการใช้งานครั้งที่สองสถานการณ์การจัดกลุ่ม (เช่นเมื่อby =หรือkeyby =มีการระบุ) แตกต่างกันเล็กน้อยในเชิงแนวคิด (แม้ว่าที่แกนกลางจะเหมือนกันเนื่องจากหลังจากทั้งหมดการดำเนินการที่ไม่จัดกลุ่มเป็นกรณีขอบของการจัดกลุ่มที่มีเพียง กลุ่มหนึ่ง)


นี่คือตัวอย่างที่แสดงให้เห็นและตัวอย่างของประเพณีที่ฉันใช้บ่อย ๆ :

กำลังโหลดข้อมูล Lahman

เพื่อให้ความรู้สึกในโลกแห่งความเป็นจริงมากกว่าการสร้างข้อมูลลองโหลดชุดข้อมูลบางอย่างเกี่ยวกับกีฬาเบสบอลจากLahman:

library(data.table) 
library(magrittr) # some piping can be beautiful
library(Lahman)
Teams = as.data.table(Teams)
# *I'm selectively suppressing the printed output of tables here*
Teams
Pitching = as.data.table(Pitching)
# subset for conciseness
Pitching = Pitching[ , .(playerID, yearID, teamID, W, L, G, ERA)]
Pitching

เปลือยกาย .SD

เพื่อแสดงให้เห็นถึงสิ่งที่ฉันหมายถึงเกี่ยวกับลักษณะที่สะท้อนกลับของ.SDพิจารณาการใช้งานที่ซ้ำซากที่สุด:

Pitching[ , .SD]
#         playerID yearID teamID  W  L  G   ERA
#     1: bechtge01   1871    PH1  1  2  3  7.96
#     2: brainas01   1871    WS3 12 15 30  4.50
#     3: fergubo01   1871    NY2  0  0  1 27.00
#     4: fishech01   1871    RC1  4 16 24  4.35
#     5: fleetfr01   1871    NY2  0  1  1 10.00
#    ---                                       
# 44959: zastrro01   2016    CHN  1  0  8  1.13
# 44960: zieglbr01   2016    ARI  2  3 36  2.82
# 44961: zieglbr01   2016    BOS  2  4 33  1.52
# 44962: zimmejo02   2016    DET  9  7 19  4.87
# 44963:  zychto01   2016    SEA  1  0 12  3.29

นั่นคือเราเพิ่งกลับมาPitchingกล่าวคือนี่เป็นวิธีการเขียนที่มากเกินไปPitchingหรือPitching[]:

identical(Pitching, Pitching[ , .SD])
# [1] TRUE

ในแง่ของ.SDการย่อยยังคงเป็นส่วนย่อยของข้อมูลมันเป็นแค่เรื่องเล็กน้อย (การตั้งค่าเอง)

การจัดกลุ่มคอลัมน์: .SDcols

วิธีแรกที่จะกระทบสิ่งที่.SDต้อง จำกัดคอลัมน์ที่มีอยู่ในการ.SDใช้.SDcolsอาร์กิวเมนต์เป็น[:

Pitching[ , .SD, .SDcols = c('W', 'L', 'G')]
#         W  L  G
#     1:  1  2  3
#     2: 12 15 30
#     3:  0  0  1
#     4:  4 16 24
#     5:  0  1  1
# ---         
# 44959:  1  0  8
# 44960:  2  3 36
# 44961:  2  4 33
# 44962:  9  7 19
# 44963:  1  0 12

นี่เป็นเพียงภาพประกอบและน่าเบื่อมาก แต่การใช้งานเพียงอย่างเดียวก็ยังช่วยให้การดำเนินการจัดการข้อมูลที่เป็นประโยชน์ / แพร่หลายอย่างกว้างขวาง:

การแปลงประเภทคอลัมน์

การแปลงชนิดคอลัมน์เป็นข้อเท็จจริงของอายุการใช้งานของข้อมูลที่ถูกบันทึกซึ่งในขณะที่เขียนนี้fwriteไม่สามารถอ่านDateหรือPOSIXctคอลัมน์โดยอัตโนมัติและการแปลงไปมาระหว่างcharacter/ factor/ numericเป็นเรื่องธรรมดา เราสามารถใช้.SDและ.SDcolsเพื่อแปลงกลุ่มกลุ่มของคอลัมน์ดังกล่าว

เราสังเกตเห็นว่าคอลัมน์ต่อไปนี้ถูกเก็บไว้characterในTeamsชุดข้อมูล:

# see ?Teams for explanation; these are various IDs
#   used to identify the multitude of teams from
#   across the long history of baseball
fkt = c('teamIDBR', 'teamIDlahman45', 'teamIDretro')
# confirm that they're stored as `character`
Teams[ , sapply(.SD, is.character), .SDcols = fkt]
# teamIDBR teamIDlahman45    teamIDretro 
#     TRUE           TRUE           TRUE 

หากคุณสับสนโดยการใช้sapplyที่นี่โปรดทราบว่ามันเป็นเช่นเดียวกับฐาน R data.frames:

setDF(Teams) # convert to data.frame for illustration
sapply(Teams[ , fkt], is.character)
# teamIDBR teamIDlahman45    teamIDretro 
#     TRUE           TRUE           TRUE 
setDT(Teams) # convert back to data.table

กุญแจสำคัญในการทำความเข้าใจกับไวยากรณ์นี้คือการจำได้ว่าdata.table(เช่นเดียวกับdata.frame) ถือได้ว่าเป็นlistที่ที่แต่ละองค์ประกอบเป็นคอลัมน์ - ดังนั้นsapply/ lapplyนำFUNไปใช้กับแต่ละคอลัมน์และส่งกลับผลลัพธ์เป็นsapply/ lapplyมักจะ (ที่นี่FUN == is.characterกลับlogicalความยาว 1 ดังนั้นsapplyส่งคืนเวกเตอร์)

ไวยากรณ์ในการแปลงคอลัมน์เหล่านี้factorคล้ายกันมาก - เพียงแค่เพิ่มตัว:=ดำเนินการที่ได้รับมอบหมาย

Teams[ , (fkt) := lapply(.SD, factor), .SDcols = fkt]

โปรดทราบว่าเราต้องห่อfktในวงเล็บ()เพื่อบังคับให้ R แปลความหมายนี้เป็นชื่อคอลัมน์แทนที่จะพยายามกำหนดชื่อfktให้กับ RHS

ความยืดหยุ่นของ.SDcols(และ:=) ที่จะยอมรับcharacterเวกเตอร์หรือintegerเวกเตอร์ของตำแหน่งคอลัมน์ยังสามารถเข้ามามีประโยชน์สำหรับการแปลงรูปแบบที่ใช้ชื่อคอลัมน์ * เราสามารถแปลงfactorคอลัมน์ทั้งหมดเป็นcharacter:

fkt_idx = which(sapply(Teams, is.factor))
Teams[ , (fkt_idx) := lapply(.SD, as.character), .SDcols = fkt_idx]

จากนั้นแปลงคอลัมน์ทั้งหมดที่มีteamกลับไปเป็นfactor:

team_idx = grep('team', names(Teams), value = TRUE)
Teams[ , (team_idx) := lapply(.SD, factor), .SDcols = team_idx]

** การใช้หมายเลขคอลัมน์อย่างชัดเจนDT[ , (1) := rnorm(.N)]เป็นวิธีปฏิบัติที่ไม่ดีและอาจนำไปสู่โค้ดที่เสียหายในช่วงเวลาหนึ่งหากตำแหน่งของคอลัมน์เปลี่ยนไป แม้การใช้ตัวเลขโดยนัยอาจเป็นอันตรายหากเราไม่ควบคุมอย่างฉลาด / เข้มงวดกับการเรียงลำดับเมื่อเราสร้างดัชนีตัวเลขและเมื่อเราใช้

การควบคุม RHS ของแบบจำลอง

ข้อมูลจำเพาะของรุ่นที่หลากหลายนั้นเป็นคุณสมบัติหลักของการวิเคราะห์ทางสถิติ ลองและทำนาย ERA ของเหยือก (Earned Runs Average ซึ่งเป็นเครื่องวัดประสิทธิภาพ) โดยใช้ covariates ขนาดเล็กที่มีอยู่ในPitchingตาราง ความสัมพันธ์ (เชิงเส้น) ระหว่างW(ชนะ) และERAแตกต่างกันอย่างไรขึ้นอยู่กับความแปรปรวนร่วมอื่น ๆ ที่รวมอยู่ในข้อมูลจำเพาะ?

นี่เป็นสคริปต์สั้น ๆ ที่ใช้ประโยชน์จากพลัง.SDที่สำรวจคำถามนี้:

# this generates a list of the 2^k possible extra variables
#   for models of the form ERA ~ G + (...)
extra_var = c('yearID', 'teamID', 'G', 'L')
models =
  lapply(0L:length(extra_var), combn, x = extra_var, simplify = FALSE) %>%
  unlist(recursive = FALSE)

# here are 16 visually distinct colors, taken from the list of 20 here:
#   https://sashat.me/2017/01/11/list-of-20-simple-distinct-colors/
col16 = c('#e6194b', '#3cb44b', '#ffe119', '#0082c8', '#f58231', '#911eb4',
          '#46f0f0', '#f032e6', '#d2f53c', '#fabebe', '#008080', '#e6beff',
          '#aa6e28', '#fffac8', '#800000', '#aaffc3')

par(oma = c(2, 0, 0, 0))
sapply(models, function(rhs) {
  # using ERA ~ . and data = .SD, then varying which
  #   columns are included in .SD allows us to perform this
  #   iteration over 16 models succinctly.
  #   coef(.)['W'] extracts the W coefficient from each model fit
  Pitching[ , coef(lm(ERA ~ ., data = .SD))['W'], .SDcols = c('W', rhs)]
}) %>% barplot(names.arg = sapply(models, paste, collapse = '/'),
               main = 'Wins Coefficient with Various Covariates',
               col = col16, las = 2L, cex.names = .8)

พอดีกับ OLS สัมประสิทธิ์ W, ข้อกำหนดต่าง ๆ

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

เข้าร่วมแบบมีเงื่อนไข

data.tableไวยากรณ์มีความสวยงามสำหรับความเรียบง่ายและความทนทานของมัน ไวยากรณ์x[i]มีความยืดหยุ่นจับสองทั่วไปวิธีการ Subsetting - เมื่อiเป็นlogicalเวกเตอร์x[i]จะกลับมาแถวเหล่านั้นxสอดคล้องกับที่iเป็นTRUE; เมื่อiเป็นอีกdata.tableที่joinจะดำเนินการ (ในรูปแบบธรรมดาโดยใช้keyของxและiมิฉะนั้นเมื่อon =มีการระบุโดยใช้การแข่งขันของคอลัมน์เหล่านั้น)

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

ตัวอย่างนี้เป็นแบบตาด แต่แสดงให้เห็นถึงความคิด; ดูที่นี่ ( 1 , 2 ) เพื่อเพิ่มเติม

เป้าหมายคือการเพิ่มคอลัมน์team_performanceลงในPitchingตารางที่บันทึกประสิทธิภาพการทำงานของทีม (อันดับ) ของเหยือกที่ดีที่สุดในแต่ละทีม (วัดจาก ERA ที่ต่ำที่สุดในบรรดาเหยือกที่มีเกมที่บันทึกไว้อย่างน้อย 6 เกม)

# to exclude pitchers with exceptional performance in a few games,
#   subset first; then define rank of pitchers within their team each year
#   (in general, we should put more care into the 'ties.method'
Pitching[G > 5, rank_in_team := frank(ERA), by = .(teamID, yearID)]
Pitching[rank_in_team == 1, team_performance := 
           # this should work without needing copy(); 
           #   that it doesn't appears to be a bug: 
           #   https://github.com/Rdatatable/data.table/issues/1926
           Teams[copy(.SD), Rank, .(teamID, yearID)]]

โปรดทราบว่าx[y]ไวยากรณ์ส่งคืนnrow(y)ค่าซึ่งเป็นสาเหตุที่.SDอยู่ทางขวาในTeams[.SD](เนื่องจาก RHS ของ:=ในกรณีนี้ต้องใช้nrow(Pitching[rank_in_team == 1])ค่า

.SDการดำเนินงานเป็นกลุ่ม

บ่อยครั้งที่เราต้องการที่จะดำเนินการบางอย่างเกี่ยวกับข้อมูลของเราในระดับกลุ่ม เมื่อเราระบุby =(หรือkeyby =) แบบจำลองทางจิตสำหรับสิ่งที่เกิดขึ้นเมื่อdata.tableกระบวนการjคิดว่าคุณdata.tableถูกแบ่งออกเป็นหลายองค์ประกอบย่อยdata.tableซึ่งแต่ละแบบนั้นสอดคล้องกับค่าเดียวของbyตัวแปรของคุณ:

ภาพประกอบการจัดกลุ่ม

ในกรณีนี้.SDคือหลายในธรรมชาติ - มันหมายถึงแต่ละย่อยเหล่านี้data.tables, หนึ่งที่-a-เวลา (เล็กน้อยขึ้นอย่างถูกต้องขอบเขตของ.SDเป็นอนุกรรมการเดียวdata.table) สิ่งนี้ช่วยให้เราสามารถแสดงการดำเนินการอย่างย่อที่เราต้องการดำเนินการในแต่ละรายการย่อยdata.tableก่อนที่ผลลัพธ์ที่ประกอบใหม่จะถูกส่งกลับมาให้เรา

สิ่งนี้มีประโยชน์ในการตั้งค่าที่หลากหลายซึ่งส่วนใหญ่จะแสดงที่นี่:

การจัดกลุ่มเป็นกลุ่ม

มาดูฤดูกาลล่าสุดของข้อมูลสำหรับแต่ละทีมในข้อมูล Lahman สามารถทำได้ค่อนข้างง่ายด้วย:

# the data is already sorted by year; if it weren't
#   we could do Teams[order(yearID), .SD[.N], by = teamID]
Teams[ , .SD[.N], by = teamID]

จำได้ว่า.SDตัวเองเป็นdata.tableและที่.Nหมายถึงจำนวนแถวในกลุ่ม (มันเท่ากับnrow(.SD)ในแต่ละกลุ่ม) เพื่อ.SD[.N]ส่งกลับทั้งหมดของ.SDteamIDแถวสุดท้ายที่เกี่ยวข้องกับแต่ละ

อีกรุ่นทั่วไปนี้ใช้.SD[1L]แทนการสังเกตครั้งแรกสำหรับแต่ละกลุ่ม

กลุ่ม Optima

สมมติว่าเราต้องการคืนปีที่ดีที่สุดสำหรับแต่ละทีมโดยวัดจากจำนวนการวิ่งทั้งหมด ( Rเราสามารถปรับได้อย่างง่ายดายเพื่ออ้างอิงตัวชี้วัดอื่น ๆ แน่นอน) แทนที่จะใช้องค์ประกอบคงที่จากแต่ละย่อยdata.tableตอนนี้เรากำหนดดัชนีที่ต้องการแบบไดนามิกดังนี้:

Teams[ , .SD[which.max(R)], by = teamID]

โปรดทราบว่าวิธีการนี้สามารถใช้ร่วมกับ.SDcolsการส่งคืนเฉพาะบางส่วนของdata.tableแต่ละรายการ.SD(ด้วยคำเตือนที่.SDcolsควรได้รับการแก้ไขในส่วนย่อยต่างๆ)

หมายเหตุ : .SD[1L]ขณะนี้ได้รับการปรับให้เหมาะสมโดยGForce( ดูเพิ่มเติม ) data.tableภายในซึ่งมีความเร็วในการดำเนินการจัดกลุ่มทั่วไปเช่นsumหรือmean- ดู?GForceรายละเอียดเพิ่มเติมและจับตาดู / สนับสนุนเสียงสำหรับการร้องขอการปรับปรุงคุณสมบัติสำหรับการอัพเดตในหน้านี้: 1 , 2 , 3 , 4 , 5 , 6

การถดถอยแบบกลุ่ม

กลับไปที่การสอบสวนข้างต้นเกี่ยวกับความสัมพันธ์ระหว่างERAและWสมมติว่าเราคาดว่าความสัมพันธ์นี้จะแตกต่างกันไปตามทีม (กล่าวคือมีความลาดชันที่แตกต่างกันสำหรับแต่ละทีม) เราสามารถเรียกการถดถอยนี้กลับมาใช้ใหม่ได้อย่างง่ายดายเพื่อสำรวจความแตกต่างในความสัมพันธ์นี้ดังนี้ (สังเกตว่าข้อผิดพลาดมาตรฐานจากวิธีการนี้โดยทั่วไปไม่ถูกต้อง - ข้อมูลจำเพาะERA ~ W*teamIDจะดีกว่า - วิธีนี้ง่ายต่อการอ่านและสัมประสิทธิ์เป็น OK) :

# use the .N > 20 filter to exclude teams with few observations
Pitching[ , if (.N > 20) .(w_coef = coef(lm(ERA ~ W))['W']), by = teamID
          ][ , hist(w_coef, 20, xlab = 'Fitted Coefficient on W',
                    ylab = 'Number of Teams', col = 'darkgreen',
                    main = 'Distribution of Team-Level Win Coefficients on ERA')]

การกระจายของสัมประสิทธิ์การติดตั้ง

ในขณะที่มีความแตกต่างในปริมาณที่พอใช้ แต่ก็มีความเข้มข้นที่แตกต่างกันโดยรอบค่าโดยรวมที่สังเกตได้

หวังว่านี่จะอธิบายพลังของการ.SDอำนวยความสะดวกในรหัสที่สวยงามและมีประสิทธิภาพในdata.table!


5
คำอธิบายที่ดี เพียงแค่ความคิดเห็นเดียว: แทนที่จะเป็นทีม [, .SD [ซึ่ง. max (R)], โดย = teamID] คุณสามารถใช้ประโยชน์จากฟังก์ชั่นการสั่งซื้อ data.table ที่รวดเร็ว: ผ่านทีม [สั่งซื้อ (ทีม ID, -R), .SD [ 1L], keyby = teamID] ควรจะเร็วกว่านี้
บาร์เทลบี้

@ Bartleby ขอบคุณแน่นอนถูกต้อง แต่วิธีการทั่วไปยังคงมีประโยชน์ที่จะรู้ - เช่นถ้าเราต้องการสั่งซื้อโดยปริมาณขึ้นอยู่กับกลุ่ม บางทีฉันจะเปลี่ยนตัวอย่าง
MichaelChirico

3

ฉันทำวิดีโอเกี่ยวกับเรื่องนี้หลังจากพูดคุยกับ Matt Dowle เกี่ยวกับ. SD คุณสามารถดูได้ใน YouTube: https://www.youtube.com/watch?v=DwEzQuYfMsI


2
แต่น่าเสียดายที่ Stack Overflow ไม่ตอบรับที่ประกอบด้วยลิงก์ภายนอกเป็นหลัก คุณอาจต้องการแก้ไขข้อความและรหัสข้อมูลเพิ่มเติมหรือไม่ Fyi Matt ได้เพิ่มวิดีโอของคุณลงในวิกิ: github.com/Rdatatable/data.table/wiki/Presentations
Frank
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.