При построении выражений для размещения в слоте j
вызова [.data.table
часто бывает полезно иметь возможность изучить и поэкспериментировать с содержимым .SD
.
Эта наивная попытка не работает...
library(data.table)
DT = data.table(x=rep(c("a","b","c"),each=3), y=c(1,3,6), v=1:9)
DT[, browser(), by=x]
# Called from: `[.data.table`(DT, , browser(), by = x)
Browse[1]>
Browse[1]> .SD
# NULL data.table
... хотя переменная с именем .SD
и несколько других, связанных с текущим подмножеством data.table, присутствуют в локальной среде
Browse[1]> ls(all.names = TRUE)
# [1] ".BY" ".GRP" ".I" ".iSD" ".N" ".SD"
# [7] "Cfastmean" "mean" "print" "x"
Browse[1]> .N
# [1] 3
Browse[1]> .I
# [1] 4 5 6
Используя .I
, я могу просмотреть что-то +/- вроде .SD
, но было бы неплохо иметь прямой доступ к его значению:
Browse[1]> DT[.I]
# x y v
# 1: b 1 4
# 2: b 3 5
# 3: b 6 6
Мои вопросы: Почему ожидаемое значение .SD
недоступно напрямую из вызова browser()
(в то время как .I
, .N
, .GRP
и .BY
доступны)? Есть ли альтернативный способ получить доступ к значению .SD
?
data.table
FAQ относится к очень медленному вниз, что может повлечь за собой использование.SD
. 28.03.2013.SD
, но не сwith = FALSE
. ‹quote› Объект SD эффективно реализован внутри и более эффективен, чем передача аргумента в функцию. Пожалуйста, не делайте этого :DT[,.SD[,"sales",with=FALSE],by=grp]
‹/quote›. 28.03.2013with=FALSE
? Думаю, я должен признать, что никогда не понимал, о чем именно говорится в этом разделе, поэтому просто избегал.SD
, когда мог. 28.03.2013with = FALSE
в основном имитирует эквивалентdata.frame
. Например, если вам нужно получить доступ к 3-му столбцу, вы можете сделать:DT[, 3, with = FALSE]
. Но без этого.SD
определенно быстрее, особенно при работе со столбцами (или по столбцам). 28.03.2013.SD
вj
приводит к тому, что.SD
заполняется всеми столбцами подмножества. В противном случае.SD
заполняется только теми столбцами, которые нужныj
. Внутри, на уровне C,.SD
является статической средой, в которой оцениваетсяj
. Именно здесь происходит вся магия, независимо от того, используется ли.SD
(как символ)j
или нет. Это то, на что ссылается FAQ 3.1, пункт 1. И именно поэтому мы советуем не использовать.SD
, если толькоj
действительно не нужны все столбцы и все строки из него (например,DT[,lapply(.SD,sum),by=...]
). 28.03.2013DT[, {browser(); .SD}, by=x]
. Отредактирую свой ответ, чтобы отразить это, когда у меня будет шанс. (2) Re: Комментарий Аруна, должны ли эти два устройства быть одинаково быстрыми:DT[,.N*.SD[,v], by=x]; DT[,.N*.SD[,"v",with=FALSE], by=x]
? Оптимизирует ли[.data.table
первое выражениеj
, но не второе? Или, поскольку они оба ссылаются на.SD
, получают ли они один и тот же удар? (3) Еще раз спасибо за всю вашу работу над этим проектом! 28.03.2013j
сначала проверяется один раз, прежде чем начнется группировка. (2) Оба одинаково медленные и одинаково плохие методы (см. конец FAQ 2.1), потому что оба используют.SD
расточительно, а также обаj
вызывают[.data.table
, которые имеют накладные расходы при зацикливании или группировании. Но дайте мне знать, если тесты докажут, что я ошибаюсь! (3) Нет проблем, спасибо! 28.03.2013data.table
есть в R, а не, например, в Python или Julia. Без ленивой оценки R было бы невозможно проверитьi
иj
и оптимизировать их перед оценкой, iiuc. 28.03.2013